set_bucket(dlon, dlat);
}
+SGBucket::SGBucket(const SGGeod& geod) {
+ set_bucket(geod);
+}
// create an impossible bucket if false
SGBucket::SGBucket(const bool is_good) {
}
-// default destructor
-SGBucket::~SGBucket() {
-}
-
-
// Set the bucket params for the specified lat and lon
void SGBucket::set_bucket( double *lonlat ) {
set_bucket( lonlat[0], lonlat[1] );
}
+void SGBucket::set_bucket(const SGGeod& geod)
+{
+ set_bucket(geod.getLongitudeDeg(), geod.getLatitudeDeg());
+}
+
// Build the path name for this bucket
string SGBucket::gen_base_path() const {
// long int index;
*/
SGBucket(const double dlon, const double dlat);
+ /**
+ * Construct a bucket given a specific location.
+ * @param dlon longitude specified in degrees
+ * @param dlat latitude specified in degrees
+ */
+ SGBucket(const SGGeod& geod);
+
/** Construct a bucket.
* @param is_good if false, create an invalid bucket. This is
* useful * if you are comparing cur_bucket to last_bucket and
*/
SGBucket(const long int bindex);
- /**
- * Default destructor.
- */
- ~SGBucket();
-
/**
* Reset a bucket to represent a new lat and lon
* @param dlon longitude specified in degrees
*/
void set_bucket( double *lonlat );
+ /**
+ * Reset a bucket to represent a new lat and lon
+ * @param dlon longitude specified in degrees
+ * @param dlat latitude specified in degrees
+ */
+ void set_bucket(const SGGeod& geod);
+
/**
* Create an impossible bucket.
* This is useful if you are comparing cur_bucket to last_bucket
obj.get_gbs_radius());
cout << endl;
- point_list nodes = obj.get_wgs84_nodes();
+ std::vector<SGVec3d> nodes = obj.get_wgs84_nodes();
cout << "# vertex list" << endl;
for ( i = 0; i < (int)nodes.size(); ++i ) {
printf("v %.5f %.5f %.5f\n", nodes[i].x(), nodes[i].y(), nodes[i].z() );
}
cout << endl;
- point_list normals = obj.get_normals();
+ std::vector<SGVec3f> normals = obj.get_normals();
cout << "# vertex normal list" << endl;
for ( i = 0; i < (int)normals.size(); ++i ) {
printf("vn %.5f %.5f %.5f\n",
}
cout << endl;
- point_list texcoords = obj.get_texcoords();
+ std::vector<SGVec2f> texcoords = obj.get_texcoords();
cout << "# texture coordinate list" << endl;
for ( i = 0; i < (int)texcoords.size(); ++i ) {
printf("vt %.5f %.5f\n",
int idx_size;
bool do_vertices, do_normals, do_colors, do_texcoords;
int j, k, idx;
- static sgSimpleBuffer buf( 32768 ); // 32 Kb
+ sgSimpleBuffer buf( 32768 ); // 32 Kb
char material[256];
// default values
// read a binary file and populate the provided structures.
bool SGBinObject::read_bin( const string& file ) {
- Point3D p;
+ SGVec3d p;
int i, j, k;
unsigned int nbytes;
- static sgSimpleBuffer buf( 32768 ); // 32 Kb
+ sgSimpleBuffer buf( 32768 ); // 32 Kb
// zero out structures
- gbs_center = Point3D( 0 );
+ gbs_center = SGVec3d(0, 0, 0);
gbs_radius = 0.0;
wgs84_nodes.clear();
sgEndianSwap( (uint64_t *)&(dptr[1]) );
sgEndianSwap( (uint64_t *)&(dptr[2]) );
}
- gbs_center = Point3D( dptr[0], dptr[1], dptr[2] );
+ gbs_center = SGVec3d( dptr[0], dptr[1], dptr[2] );
// cout << "Center = " << gbs_center << endl;
ptr += sizeof(double) * 3;
sgEndianSwap( (uint32_t *)&(fptr[1]) );
sgEndianSwap( (uint32_t *)&(fptr[2]) );
}
- wgs84_nodes.push_back( Point3D(fptr[0], fptr[1], fptr[2]) );
+ wgs84_nodes.push_back( SGVec3d(fptr[0], fptr[1], fptr[2]) );
fptr += 3;
}
}
sgEndianSwap( (uint32_t *)&(fptr[2]) );
sgEndianSwap( (uint32_t *)&(fptr[3]) );
}
- colors.push_back( Point3D( fptr[0], fptr[1], fptr[2] ) );
+ SGVec4f color( fptr[0], fptr[1], fptr[2], fptr[3] );
+ colors.push_back( color );
fptr += 4;
}
}
int count = nbytes / 3;
normals.reserve( count );
for ( k = 0; k < count; ++k ) {
- sgdVec3 normal;
- sgdSetVec3( normal,
- (ptr[0]) / 127.5 - 1.0,
- (ptr[1]) / 127.5 - 1.0,
- (ptr[2]) / 127.5 - 1.0 );
- sgdNormalizeVec3( normal );
-
- normals.push_back(Point3D(normal[0], normal[1], normal[2]));
+ SGVec3f normal((ptr[0]) / 127.5 - 1.0,
+ (ptr[1]) / 127.5 - 1.0,
+ (ptr[2]) / 127.5 - 1.0);
+
+ normals.push_back(normalize(normal));
ptr += 3;
}
}
sgEndianSwap( (uint32_t *)&(fptr[0]) );
sgEndianSwap( (uint32_t *)&(fptr[1]) );
}
- texcoords.push_back( Point3D( fptr[0], fptr[1], 0 ) );
+ texcoords.push_back( SGVec2f( fptr[0], fptr[1] ) );
fptr += 2;
}
}
bool SGBinObject::write_bin( const string& base, const string& name,
const SGBucket& b )
{
- Point3D p;
- sgVec2 t;
- sgVec3 pt;
- sgVec4 color;
int i, j;
unsigned char idx_mask;
int idx_size;
sgWriteShort( fp, 1 ); // nelements
sgWriteUInt( fp, wgs84_nodes.size() * sizeof(float) * 3 ); // nbytes
for ( i = 0; i < (int)wgs84_nodes.size(); ++i ) {
- p = wgs84_nodes[i] - gbs_center;
- sgSetVec3( pt, p.x(), p.y(), p.z() );
- sgWriteVec3( fp, pt );
+ SGVec3f p = toVec3f(wgs84_nodes[i] - gbs_center);
+ sgWriteVec3( fp, p.data() );
}
// dump vertex color list
sgWriteShort( fp, 1 ); // nelements
sgWriteUInt( fp, colors.size() * sizeof(float) * 4 ); // nbytes
for ( i = 0; i < (int)colors.size(); ++i ) {
- p = colors[i];
- // Right now we have a place holder for color alpha but we
- // need to update the interface so the calling program can
- // provide the info.
- sgSetVec4( color, p.x(), p.y(), p.z(), 1.0 );
- sgWriteVec4( fp, color );
+ sgWriteVec4( fp, colors[i].data() );
}
// dump vertex normal list
sgWriteUInt( fp, normals.size() * 3 ); // nbytes
char normal[3];
for ( i = 0; i < (int)normals.size(); ++i ) {
- p = normals[i];
+ SGVec3f p = normals[i];
normal[0] = (unsigned char)((p.x() + 1.0) * 127.5);
normal[1] = (unsigned char)((p.y() + 1.0) * 127.5);
normal[2] = (unsigned char)((p.z() + 1.0) * 127.5);
sgWriteShort( fp, 1 ); // nelements
sgWriteUInt( fp, texcoords.size() * sizeof(float) * 2 ); // nbytes
for ( i = 0; i < (int)texcoords.size(); ++i ) {
- p = texcoords[i];
- sgSetVec2( t, p.x(), p.y() );
- sgWriteVec2( fp, t );
+ sgWriteVec2( fp, texcoords[i].data() );
}
// dump point groups if they exist
bool SGBinObject::write_ascii( const string& base, const string& name,
const SGBucket& b )
{
- Point3D p;
int i, j;
SGPath file = base + "/" + b.gen_base_path() + "/" + name;
// dump vertex list
fprintf(fp, "# vertex list\n");
for ( i = 0; i < (int)wgs84_nodes.size(); ++i ) {
- p = wgs84_nodes[i] - gbs_center;
+ SGVec3d p = wgs84_nodes[i] - gbs_center;
fprintf(fp, "v %.5f %.5f %.5f\n", p.x(), p.y(), p.z() );
}
fprintf(fp, "# vertex normal list\n");
for ( i = 0; i < (int)normals.size(); ++i ) {
- p = normals[i];
+ SGVec3f p = normals[i];
fprintf(fp, "vn %.5f %.5f %.5f\n", p.x(), p.y(), p.z() );
}
fprintf(fp, "\n");
// dump texture coordinates
fprintf(fp, "# texture coordinate list\n");
for ( i = 0; i < (int)texcoords.size(); ++i ) {
- p = texcoords[i];
+ SGVec2f p = texcoords[i];
fprintf(fp, "vt %.5f %.5f\n", p.x(), p.y() );
}
fprintf(fp, "\n");
// make a list of points for the group
point_list group_nodes;
group_nodes.clear();
- Point3D bs_center;
+ SGVec3d bs_center;
double bs_radius = 0;
for ( i = start; i < end; ++i ) {
for ( j = 0; j < (int)tris_v[i].size(); ++j ) {
- group_nodes.push_back( wgs84_nodes[ tris_v[i][j] ] );
- bs_center = sgCalcCenter( group_nodes );
- bs_radius = sgCalcBoundingRadius( bs_center, group_nodes );
+ group_nodes.push_back( Point3D::fromSGVec3(wgs84_nodes[ tris_v[i][j] ]) );
+ bs_center = sgCalcCenter( group_nodes ).toSGVec3d();
+ bs_radius = sgCalcBoundingRadius( Point3D::fromSGVec3(bs_center), group_nodes );
}
}
// make a list of points for the group
point_list group_nodes;
group_nodes.clear();
- Point3D bs_center;
+ SGVec3d bs_center;
double bs_radius = 0;
for ( i = start; i < end; ++i ) {
for ( j = 0; j < (int)strips_v[i].size(); ++j ) {
- group_nodes.push_back( wgs84_nodes[ strips_v[i][j] ] );
- bs_center = sgCalcCenter( group_nodes );
- bs_radius = sgCalcBoundingRadius( bs_center, group_nodes );
+ group_nodes.push_back( Point3D::fromSGVec3(wgs84_nodes[ strips_v[i][j] ]) );
+ bs_center = sgCalcCenter( group_nodes ).toSGVec3d();
+ bs_radius = sgCalcBoundingRadius( Point3D::fromSGVec3(bs_center), group_nodes );
}
}
class SGBinObject {
unsigned short version;
- Point3D gbs_center;
+ SGVec3d gbs_center;
float gbs_radius;
- point_list wgs84_nodes; // vertex list
- point_list colors; // color list
- point_list normals; // normal list
- point_list texcoords; // texture coordinate list
+ std::vector<SGVec3d> wgs84_nodes; // vertex list
+ std::vector<SGVec4f> colors; // color list
+ std::vector<SGVec3f> normals; // normal list
+ std::vector<SGVec2f> texcoords; // texture coordinate list
group_list pts_v; // points vertex index
group_list pts_n; // points normal index
inline unsigned short get_version() const { return version; }
- inline const Point3D& get_gbs_center() const { return gbs_center; }
- inline void set_gbs_center( const Point3D& p ) { gbs_center = p; }
+ inline Point3D get_gbs_center() const { return Point3D::fromSGVec3(gbs_center); }
+ inline void set_gbs_center( const Point3D& p ) { gbs_center = p.toSGVec3d(); }
+ inline const SGVec3d& get_gbs_center2() const { return gbs_center; }
+ inline void set_gbs_center( const SGVec3d& p ) { gbs_center = p; }
inline float get_gbs_radius() const { return gbs_radius; }
inline void set_gbs_radius( float r ) { gbs_radius = r; }
- inline const point_list& get_wgs84_nodes() const { return wgs84_nodes; }
- inline void set_wgs84_nodes( const point_list& n ) { wgs84_nodes = n; }
-
- inline const point_list& get_colors() const { return colors; }
- inline void set_colors( const point_list& c ) { colors = c; }
-
- inline const point_list& get_normals() const { return normals; }
- inline void set_normals( const point_list& n ) { normals = n; }
-
- inline const point_list& get_texcoords() const { return texcoords; }
- inline void set_texcoords( const point_list& t ) { texcoords = t; }
+ inline const std::vector<SGVec3d>& get_wgs84_nodes() const
+ { return wgs84_nodes; }
+ inline void set_wgs84_nodes( const std::vector<SGVec3d>& n )
+ { wgs84_nodes = n; }
+ inline void set_wgs84_nodes( const point_list& n )
+ {
+ wgs84_nodes.resize(n.size());
+ for (unsigned i = 0; i < wgs84_nodes.size(); ++i)
+ wgs84_nodes[i] = n[i].toSGVec3d();
+ }
+
+ inline const std::vector<SGVec4f>& get_colors() const { return colors; }
+ inline void set_colors( const std::vector<SGVec4f>& c ) { colors = c; }
+ inline void set_colors( const point_list& c )
+ {
+ colors.resize(c.size());
+ for (unsigned i = 0; i < colors.size(); ++i)
+ colors[i] = SGVec4f(c[i].toSGVec3f(), 1);
+ }
+
+ inline const std::vector<SGVec3f>& get_normals() const { return normals; }
+ inline void set_normals( const std::vector<SGVec3f>& n ) { normals = n; }
+ inline void set_normals( const point_list& n )
+ {
+ normals.resize(n.size());
+ for (unsigned i = 0; i < normals.size(); ++i)
+ normals[i] = n[i].toSGVec3f();
+ }
+
+ inline const std::vector<SGVec2f>& get_texcoords() const { return texcoords; }
+ inline void set_texcoords( const std::vector<SGVec2f>& t ) { texcoords = t; }
+ inline void set_texcoords( const point_list& t )
+ {
+ texcoords.resize(t.size());
+ for (unsigned i = 0; i < texcoords.size(); ++i)
+ texcoords[i] = t[i].toSGVec2f();
+ }
inline const group_list& get_pts_v() const { return pts_v; }
inline void set_pts_v( const group_list& g ) { pts_v = g; }
operator*(const SGVec2<T>& v, S s)
{ return SGVec2<T>(s*v(0), s*v(1)); }
+/// multiplication as a multiplicator, that is assume that the first vector
+/// represents a 2x2 diagonal matrix with the diagonal elements in the vector.
+/// Then the result is the product of that matrix times the second vector.
+template<typename T>
+inline
+SGVec2<T>
+mult(const SGVec2<T>& v1, const SGVec2<T>& v2)
+{ return SGVec2<T>(v1(0)*v2(0), v1(1)*v2(1)); }
+
/// component wise min
template<typename T>
inline
operator*(const SGVec3<T>& v, S s)
{ return SGVec3<T>(s*v(0), s*v(1), s*v(2)); }
+/// multiplication as a multiplicator, that is assume that the first vector
+/// represents a 3x3 diagonal matrix with the diagonal elements in the vector.
+/// Then the result is the product of that matrix times the second vector.
+template<typename T>
+inline
+SGVec3<T>
+mult(const SGVec3<T>& v1, const SGVec3<T>& v2)
+{ return SGVec3<T>(v1(0)*v2(0), v1(1)*v2(1), v1(2)*v2(2)); }
+
/// component wise min
template<typename T>
inline
operator*(const SGVec4<T>& v, S s)
{ return SGVec4<T>(s*v(0), s*v(1), s*v(2), s*v(3)); }
+/// multiplication as a multiplicator, that is assume that the first vector
+/// represents a 4x4 diagonal matrix with the diagonal elements in the vector.
+/// Then the result is the product of that matrix times the second vector.
+template<typename T>
+inline
+SGVec4<T>
+mult(const SGVec4<T>& v1, const SGVec4<T>& v2)
+{ return SGVec4<T>(v1(0)*v2(0), v1(1)*v2(1), v1(2)*v2(2), v1(3)*v2(3)); }
+
/// component wise min
template<typename T>
inline
*/
SGMaterialGlyph * get_glyph (const string& name) const;
+ void set_light_color(const SGVec4f& color)
+ { emission = color; }
+ const SGVec4f& get_light_color() const
+ { return emission; }
+
+ SGVec2f get_tex_coord_scale() const
+ {
+ float tex_width = get_xsize();
+ float tex_height = get_ysize();
+
+ return SGVec2f((0 < tex_width) ? 1000.0f/tex_width : 1.0f,
+ (0 < tex_height) ? 1000.0f/tex_height : 1.0f);
+ }
+
protected:
\f
#include <osg/BlendFunc>
#include <osg/CullFace>
#include <osg/Material>
-// #include <osg/Multisample>
#include <osg/Point>
#include <osg/PointSprite>
#include <osg/PolygonMode>
SG_USING_NAMESPACE(std);
SG_USING_STD(string);
-extern bool SGPointLightsUseSprites;
-extern bool SGPointLightsEnhancedLighting;
-extern bool SGPointLightsDistanceAttenuation;
-
-// FIXME: should make this configurable
-static const bool sprite_lighting = true;
-
// Constructor
SGMaterialLib::SGMaterialLib ( void ) {
}
-// generate standard colored directional light environment texture map
-static osg::Texture2D*
-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;
-
- osg::Image* image = new osg::Image;
- image->allocateImage(env_tex_res, env_tex_res, 1,
- GL_RGBA, GL_UNSIGNED_BYTE);
- 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; }
- unsigned char* env_map = image->data(i, j);
- env_map[0] = r;
- env_map[1] = g;
- env_map[2] = b;
- env_map[3] = (int)(bright * alpha);
- }
- }
-
- osg::Texture2D* texture = new osg::Texture2D;
- texture->setImage(image);
-
- return texture;
-}
-
-
-// generate standard colored directional light environment texture map
-static osg::Texture2D*
-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;
-
- osg::Image* image = new osg::Image;
- image->allocateImage(env_tex_res, env_tex_res, 1,
- GL_RGBA, GL_UNSIGNED_BYTE);
-
- 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; }
- unsigned char* env_map = image->data(i, j);
- env_map[0] = r;
- env_map[1] = g;
- env_map[2] = b;
- env_map[3] = (int)(bright * alpha);
- }
- }
-
- osg::Texture2D* texture = new osg::Texture2D;
- texture->setImage(image);
-
- return texture;
-}
-
-static osg::Texture2D*
-gen_standard_light_sprite( int r, int g, int b, int alpha ) {
- const int env_tex_res = 32;
- int half_res = env_tex_res / 2;
-
- osg::Image* image = new osg::Image;
- image->allocateImage(env_tex_res, env_tex_res, 1,
- GL_RGBA, GL_UNSIGNED_BYTE);
-
- 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.01 ) { bright = 0.0; }
- unsigned char* env_map = image->data(i, j);
- env_map[0] = r;
- env_map[1] = g;
- env_map[2] = b;
- env_map[3] = (int)(bright * alpha);
- }
- }
-
- osg::Texture2D* texture = new osg::Texture2D;
- texture->setImage(image);
-
- return texture;
-}
-
-
// Load a library of material properties
bool SGMaterialLib::load( const string &fg_root, const string& mpath, const char *season ) {
throw;
}
- SGSharedPtr<SGMaterial> m;
-
int nMaterials = materials.nChildren();
for (int i = 0; i < nMaterials; i++) {
const SGPropertyNode * node = materials.getChild(i);
if (!strcmp(node->getName(), "material")) {
- m = new SGMaterial( fg_root, node, season );
+ SGSharedPtr<SGMaterial> m = new SGMaterial(fg_root, node, season);
vector<SGPropertyNode_ptr>names = node->getChildren("name");
for ( unsigned int j = 0; j < names.size(); j++ ) {
}
}
- osg::ref_ptr<osg::StateSet> lightStateSet = new osg::StateSet;
- {
- lightStateSet->setRenderBinDetails(9, "DepthSortedBin");
- lightStateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
-// lightStateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON);
-
- lightStateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
-
- lightStateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::OFF);
- lightStateSet->setAttribute(new osg::AlphaFunc(osg::AlphaFunc::GREATER, 0.01));
- lightStateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::ON);
-
- osg::CullFace* cullFace = new osg::CullFace;
- cullFace->setMode(osg::CullFace::BACK);
- lightStateSet->setAttributeAndModes(cullFace, osg::StateAttribute::ON);
-
- osg::BlendFunc* blendFunc = new osg::BlendFunc;
- blendFunc->setFunction(osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::ONE_MINUS_SRC_ALPHA);
- lightStateSet->setAttributeAndModes(blendFunc, osg::StateAttribute::ON);
-
- osg::PolygonMode* polygonMode = new osg::PolygonMode;
- polygonMode->setMode(osg::PolygonMode::FRONT, osg::PolygonMode::POINT);
- lightStateSet->setAttribute(polygonMode);
-
-// if (SGPointLightsUseSprites) {
- osg::PointSprite* pointSprite = new osg::PointSprite;
- lightStateSet->setTextureAttributeAndModes(0, pointSprite, osg::StateAttribute::ON);
-// }
-
-// if (SGPointLightsDistanceAttenuation) {
- osg::Point* point = new osg::Point;
- point->setMinSize(2);
- point->setSize(8);
- point->setDistanceAttenuation(osg::Vec3(1.0, 0.001, 0.000001));
- lightStateSet->setAttribute(point);
-// }
-
- osg::PolygonOffset* polygonOffset = new osg::PolygonOffset;
- polygonOffset->setFactor(-1);
- polygonOffset->setUnits(-1);
- lightStateSet->setAttributeAndModes(polygonOffset, osg::StateAttribute::ON);
-
- osg::TexGen* texGen = new osg::TexGen;
- texGen->setMode(osg::TexGen::SPHERE_MAP);
- lightStateSet->setTextureAttribute(0, texGen);
- lightStateSet->setTextureMode(0, GL_TEXTURE_GEN_S, osg::StateAttribute::ON);
- lightStateSet->setTextureMode(0, GL_TEXTURE_GEN_T, osg::StateAttribute::ON);
- osg::TexEnv* texEnv = new osg::TexEnv;
- texEnv->setMode(osg::TexEnv::MODULATE);
- lightStateSet->setTextureAttribute(0, texEnv);
-
- osg::Material* material = new osg::Material;
- lightStateSet->setAttribute(material);
- }
-
-
- // hard coded ground light state
- osg::StateSet *gnd_lights = static_cast<osg::StateSet*>(lightStateSet->clone(osg::CopyOp::DEEP_COPY_ALL));
-// if (SGPointLightsDistanceAttenuation) {
- osg::Point* point = new osg::Point;
- point->setMinSize(1);
- point->setSize(2);
- point->setMaxSize(4);
- point->setDistanceAttenuation(osg::Vec3(1.0, 0.01, 0.0001));
- while (gnd_lights->getAttribute(osg::StateAttribute::POINT)) {
- gnd_lights->removeAttribute(osg::StateAttribute::POINT);
- }
- gnd_lights->setAttribute(point);
-// }
- m = new SGMaterial( gnd_lights );
- m->add_name("GROUND_LIGHTS");
- matlib["GROUND_LIGHTS"] = m;
-
- // hard coded runway white light state
- osg::Texture2D* texture;
- if ( sprite_lighting ) {
- texture = gen_standard_light_sprite(235, 235, 195, 255);
- } else {
- texture = gen_standard_dir_light_map(235, 235, 195, 255);
- }
- osg::StateSet *rwy_white_lights = static_cast<osg::StateSet*>(lightStateSet->clone(osg::CopyOp::DEEP_COPY_ALL));
- rwy_white_lights->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
-
- m = new SGMaterial( rwy_white_lights );
- m->add_name("RWY_WHITE_LIGHTS");
- matlib["RWY_WHITE_LIGHTS"] = m;
- // For backwards compatibility ... remove someday
- m->add_name("RUNWAY_LIGHTS");
- matlib["RUNWAY_LIGHTS"] = m;
- m->add_name("RWY_LIGHTS");
- matlib["RWY_LIGHTS"] = m;
- // end of backwards compatitibilty
-
- // hard coded runway medium intensity white light state
- if ( sprite_lighting ) {
- texture = gen_standard_light_sprite( 235, 235, 195, 205 );
- } else {
- texture = gen_standard_dir_light_map( 235, 235, 195, 205 );
- }
- osg::StateSet *rwy_white_medium_lights = static_cast<osg::StateSet*>(lightStateSet->clone(osg::CopyOp::DEEP_COPY_ALL));
- rwy_white_medium_lights->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
-
- m = new SGMaterial( rwy_white_medium_lights );
- m->add_name("RWY_WHITE_MEDIUM_LIGHTS");
- matlib["RWY_WHITE_MEDIUM_LIGHTS"] = m;
-
- // hard coded runway low intensity white light state
- if ( sprite_lighting ) {
- texture = gen_standard_light_sprite( 235, 235, 195, 155 );
- } else {
- texture = gen_standard_dir_light_map( 235, 235, 195, 155 );
- }
- osg::StateSet *rwy_white_low_lights = static_cast<osg::StateSet*>(lightStateSet->clone(osg::CopyOp::DEEP_COPY_ALL));
- rwy_white_medium_lights->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
- m = new SGMaterial( rwy_white_low_lights );
- m->add_name("RWY_WHITE_LOW_LIGHTS");
- matlib["RWY_WHITE_LOW_LIGHTS"] = m;
-
- // hard coded runway yellow light state
- if ( sprite_lighting ) {
- texture = gen_standard_light_sprite( 235, 215, 20, 255 );
- } else {
- texture = gen_standard_dir_light_map( 235, 215, 20, 255 );
- }
- osg::StateSet *rwy_yellow_lights = static_cast<osg::StateSet*>(lightStateSet->clone(osg::CopyOp::DEEP_COPY_ALL));
- rwy_yellow_lights->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
- m = new SGMaterial( rwy_yellow_lights );
- m->add_name("RWY_YELLOW_LIGHTS");
- matlib["RWY_YELLOW_LIGHTS"] = m;
-
- // hard coded runway medium intensity yellow light state
- if ( sprite_lighting ) {
- texture = gen_standard_light_sprite( 235, 215, 20, 205 );
- } else {
- texture = gen_standard_dir_light_map( 235, 215, 20, 205 );
- }
- osg::StateSet *rwy_yellow_medium_lights = static_cast<osg::StateSet*>(lightStateSet->clone(osg::CopyOp::DEEP_COPY_ALL));
- rwy_yellow_medium_lights->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
- m = new SGMaterial( rwy_yellow_medium_lights );
- m->add_name("RWY_YELLOW_MEDIUM_LIGHTS");
- matlib["RWY_YELLOW_MEDIUM_LIGHTS"] = m;
-
- // hard coded runway low intensity yellow light state
- if ( sprite_lighting ) {
- texture = gen_standard_light_sprite( 235, 215, 20, 155 );
- } else {
- texture = gen_standard_dir_light_map( 235, 215, 20, 155 );
- }
- osg::StateSet *rwy_yellow_low_lights = static_cast<osg::StateSet*>(lightStateSet->clone(osg::CopyOp::DEEP_COPY_ALL));
- rwy_yellow_low_lights->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
- m = new SGMaterial( rwy_yellow_low_lights );
- m->add_name("RWY_YELLOW_LOW_LIGHTS");
- matlib["RWY_YELLOW_LOW_LIGHTS"] = m;
-
- // hard coded runway red light state
- if ( sprite_lighting ) {
- texture = gen_standard_light_sprite( 235, 90, 90, 255 );
- } else {
- texture = gen_standard_dir_light_map( 235, 90, 90, 255 );
- }
- osg::StateSet *rwy_red_lights = static_cast<osg::StateSet*>(lightStateSet->clone(osg::CopyOp::DEEP_COPY_ALL));
- rwy_red_lights->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
- m = new SGMaterial( rwy_red_lights );
- m->add_name("RWY_RED_LIGHTS");
- matlib["RWY_RED_LIGHTS"] = m;
-
- // hard coded medium intensity runway red light state
- if ( sprite_lighting ) {
- texture = gen_standard_light_sprite( 235, 90, 90, 205 );
- } else {
- texture = gen_standard_dir_light_map( 235, 90, 90, 205 );
- }
- osg::StateSet *rwy_red_medium_lights = static_cast<osg::StateSet*>(lightStateSet->clone(osg::CopyOp::DEEP_COPY_ALL));
- rwy_red_medium_lights->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
- m = new SGMaterial( rwy_red_medium_lights );
- m->add_name("RWY_RED_MEDIUM_LIGHTS");
- matlib["RWY_RED_MEDIUM_LIGHTS"] = m;
-
- // hard coded low intensity runway red light state
- if ( sprite_lighting ) {
- texture = gen_standard_light_sprite( 235, 90, 90, 155 );
- } else {
- texture = gen_standard_dir_light_map( 235, 90, 90, 155 );
- }
- osg::StateSet *rwy_red_low_lights = static_cast<osg::StateSet*>(lightStateSet->clone(osg::CopyOp::DEEP_COPY_ALL));
- rwy_red_low_lights->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
- m = new SGMaterial( rwy_red_low_lights );
- m->add_name("RWY_RED_LOW_LIGHTS");
- matlib["RWY_RED_LOW_LIGHTS"] = m;
-
- // hard coded runway green light state
- if ( sprite_lighting ) {
- texture = gen_standard_light_sprite( 20, 235, 20, 255 );
- } else {
- texture = gen_standard_dir_light_map( 20, 235, 20, 255 );
- }
- osg::StateSet *rwy_green_lights = static_cast<osg::StateSet*>(lightStateSet->clone(osg::CopyOp::DEEP_COPY_ALL));
- rwy_green_lights->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
- m = new SGMaterial( rwy_green_lights );
- m->add_name("RWY_GREEN_LIGHTS");
- matlib["RWY_GREEN_LIGHTS"] = m;
-
- // hard coded medium intensity runway green light state
- if ( sprite_lighting ) {
- texture = gen_standard_light_sprite( 20, 235, 20, 205 );
- } else {
- texture = gen_standard_dir_light_map( 20, 235, 20, 205 );
- }
- osg::StateSet *rwy_green_medium_lights = static_cast<osg::StateSet*>(lightStateSet->clone(osg::CopyOp::DEEP_COPY_ALL));
- rwy_green_medium_lights->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
- m = new SGMaterial( rwy_green_medium_lights );
- m->add_name("RWY_GREEN_MEDIUM_LIGHTS");
- matlib["RWY_GREEN_MEDIUM_LIGHTS"] = m;
-
- // hard coded low intensity runway green light state
- if ( sprite_lighting ) {
- texture = gen_standard_light_sprite( 20, 235, 20, 155 );
- } else {
- texture = gen_standard_dir_light_map( 20, 235, 20, 155 );
- }
- osg::StateSet *rwy_green_low_lights = static_cast<osg::StateSet*>(lightStateSet->clone(osg::CopyOp::DEEP_COPY_ALL));
- rwy_green_low_lights->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
- m = new SGMaterial( rwy_green_low_lights );
- m->add_name("RWY_GREEN_LOW_LIGHTS");
- matlib["RWY_GREEN_LOW_LIGHTS"] = m;
- m->add_name("RWY_GREEN_TAXIWAY_LIGHTS");
- matlib["RWY_GREEN_TAXIWAY_LIGHTS"] = m;
-
- // hard coded low intensity taxiway blue light state
- if ( sprite_lighting ) {
- texture = gen_standard_light_sprite( 90, 90, 235, 205 );
- } else {
- texture = gen_taxiway_dir_light_map( 90, 90, 235, 205 );
- }
- osg::StateSet *taxiway_blue_low_lights = static_cast<osg::StateSet*>(lightStateSet->clone(osg::CopyOp::DEEP_COPY_ALL));
- taxiway_blue_low_lights->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
- m = new SGMaterial( taxiway_blue_low_lights );
- m->add_name("RWY_BLUE_TAXIWAY_LIGHTS");
- matlib["RWY_BLUE_TAXIWAY_LIGHTS"] = m;
-
- // hard coded runway vasi light state
- if ( sprite_lighting ) {
- texture = gen_standard_light_sprite( 235, 235, 195, 255 );
- } else {
- texture = gen_standard_dir_light_map( 235, 235, 195, 255 );
- }
- osg::StateSet *rwy_vasi_lights = static_cast<osg::StateSet*>(lightStateSet->clone(osg::CopyOp::DEEP_COPY_ALL));
-// if (SGPointLightsDistanceAttenuation) {
- point = new osg::Point;
- point->setMinSize(4);
- point->setSize(10);
- point->setDistanceAttenuation(osg::Vec3(1.0, 0.01, 0.0001));
- while (rwy_vasi_lights->getAttribute(osg::StateAttribute::POINT)) {
- rwy_vasi_lights->removeAttribute(osg::StateAttribute::POINT);
- }
- rwy_vasi_lights->setAttribute(point);
-// }
- rwy_vasi_lights->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
- m = new SGMaterial( rwy_vasi_lights );
- m->add_name("RWY_VASI_LIGHTS");
- matlib["RWY_VASI_LIGHTS"] = m;
-
return true;
}
private:
// associative array of materials
- typedef map < string, SGSharedPtr<SGMaterial>, less<string> > material_map;
+ typedef map < string, SGSharedPtr<SGMaterial> > material_map;
typedef material_map::iterator material_map_iterator;
typedef material_map::const_iterator const_material_map_iterator;
persparam.hxx \
placement.hxx \
placementtrans.hxx \
- SGMaterialAnimation.hxx
+ SGMaterialAnimation.hxx \
+ SGOffsetTransform.hxx
libsgmodel_a_SOURCES = \
animation.cxx \
placement.cxx \
placementtrans.cxx \
shadanim.cxx \
- SGMaterialAnimation.cxx
+ SGMaterialAnimation.cxx \
+ SGOffsetTransform.cxx
INCLUDES = -I$(top_srcdir)
--- /dev/null
+/* -*-c++-*-
+ *
+ * Copyright (C) 2006-2007 Mathias Froehlich
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <simgear_config.h>
+#endif
+
+#include "SGOffsetTransform.hxx"
+
+SGOffsetTransform::SGOffsetTransform(double scaleFactor) :
+ _scaleFactor(scaleFactor),
+ _rScaleFactor(1/scaleFactor)
+{
+}
+
+bool
+SGOffsetTransform::computeLocalToWorldMatrix(osg::Matrix& matrix,
+ osg::NodeVisitor* nv) const
+{
+ if (nv && nv->getVisitorType() == osg::NodeVisitor::CULL_VISITOR) {
+ osg::Vec3 center = nv->getEyePoint();
+ osg::Matrix transform;
+ transform(0,0) = _scaleFactor;
+ transform(1,1) = _scaleFactor;
+ transform(2,2) = _scaleFactor;
+ transform(3,0) = center[0]*(1 - _scaleFactor);
+ transform(3,1) = center[1]*(1 - _scaleFactor);
+ transform(3,2) = center[2]*(1 - _scaleFactor);
+ matrix.preMult(transform);
+ }
+ return true;
+}
+
+bool
+SGOffsetTransform::computeWorldToLocalMatrix(osg::Matrix& matrix,
+ osg::NodeVisitor* nv) const
+{
+ if (nv && nv->getVisitorType() == osg::NodeVisitor::CULL_VISITOR) {
+ osg::Vec3 center = nv->getEyePoint();
+ osg::Matrix transform;
+ transform(0,0) = _rScaleFactor;
+ transform(1,1) = _rScaleFactor;
+ transform(2,2) = _rScaleFactor;
+ transform(3,0) = center[0]*(1 - _rScaleFactor);
+ transform(3,1) = center[1]*(1 - _rScaleFactor);
+ transform(3,2) = center[2]*(1 - _rScaleFactor);
+ matrix.postMult(transform);
+ }
+ return true;
+}
--- /dev/null
+/* -*-c++-*-
+ *
+ * Copyright (C) 2006-2007 Mathias Froehlich
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ */
+
+#ifndef SG_OFFSET_TRASNFORM_HXX
+#define SG_OFFSET_TRASNFORM_HXX
+
+#include <osg/Transform>
+
+class SGOffsetTransform : public osg::Transform {
+public:
+ SGOffsetTransform(double scaleFactor);
+ virtual bool computeLocalToWorldMatrix(osg::Matrix& matrix,
+ osg::NodeVisitor* nv) const;
+ virtual bool computeWorldToLocalMatrix(osg::Matrix& matrix,
+ osg::NodeVisitor* nv) const;
+private:
+ double _scaleFactor;
+ double _rScaleFactor;
+};
+
+#endif
include_HEADERS = \
apt_signs.hxx \
- leaf.hxx \
obj.hxx \
pt_lights.hxx \
userdata.hxx \
- vasi.hxx
+ SGOceanTile.hxx \
+ SGVasiDrawable.hxx \
+ SGDirectionalLightBin.hxx \
+ SGLightBin.hxx \
+ SGOceanTile.hxx \
+ SGTexturedTriangleBin.hxx \
+ SGTriangleBin.hxx \
+ SGVertexArrayBin.hxx
libsgtgdb_a_SOURCES = \
apt_signs.cxx \
- leaf.cxx \
obj.cxx \
pt_lights.cxx \
- userdata.cxx
+ userdata.cxx \
+ SGOceanTile.cxx \
+ SGVasiDrawable.cxx
INCLUDES = -I$(top_srcdir)
--- /dev/null
+/* -*-c++-*-
+ *
+ * Copyright (C) 2006-2007 Mathias Froehlich
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ */
+
+#ifndef SG_DIRECTIONAL_LIGHT_BIN_HXX
+#define SG_DIRECTIONAL_LIGHT_BIN_HXX
+
+class SGDirectionalLightBin {
+public:
+ struct Light {
+ Light(const SGVec3f& p, const SGVec3f& n, const SGVec4f& c) :
+ position(p), normal(n), color(c)
+ { }
+ SGVec3f position;
+ SGVec3f normal;
+ SGVec4f color;
+ };
+ typedef std::vector<Light> LightList;
+
+ void insert(const Light& light)
+ { _lights.push_back(light); }
+ void insert(const SGVec3f& p, const SGVec3f& n, const SGVec4f& c)
+ { insert(Light(p, n, c)); }
+
+ unsigned getNumLights() const
+ { return _lights.size(); }
+ const Light& getLight(unsigned i) const
+ { return _lights[i]; }
+
+ // helper for sorting lights back to front ...
+ struct DirectionLess {
+ DirectionLess(const SGVec3f& direction) :
+ _direction(direction)
+ { }
+ inline bool operator() (const Light& l, const Light& r) const
+ { return dot(_direction, l.position) < dot(_direction, r.position); }
+ private:
+ SGVec3f _direction;
+ };
+ typedef std::multiset<Light,DirectionLess> LightSet;
+
+ LightList getSortedLights(const SGVec3f& sortDirection) const
+ {
+ LightSet lightSet = LightSet(DirectionLess(sortDirection));
+ for (unsigned i = 0; i < _lights.size(); ++i)
+ lightSet.insert(_lights[i]);
+
+ LightList sortedLights;
+ sortedLights.reserve(_lights.size());
+ LightSet::const_iterator i;
+ for (i = lightSet.begin(); i != lightSet.end(); ++i)
+ sortedLights.push_back(*i);
+
+ return sortedLights;
+ }
+
+private:
+ LightList _lights;
+};
+
+#endif
--- /dev/null
+/* -*-c++-*-
+ *
+ * Copyright (C) 2006-2007 Mathias Froehlich
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ */
+
+#ifndef SG_LIGHT_BIN_HXX
+#define SG_LIGHT_BIN_HXX
+
+class SGLightBin {
+public:
+ struct Light {
+ Light(const SGVec3f& p, const SGVec4f& c) :
+ position(p), color(c)
+ { }
+ SGVec3f position;
+ SGVec4f color;
+ };
+ typedef std::vector<Light> LightList;
+
+ void insert(const Light& light)
+ { _lights.push_back(light); }
+ void insert(const SGVec3f& p, const SGVec4f& c)
+ { insert(Light(p, c)); }
+
+ unsigned getNumLights() const
+ { return _lights.size(); }
+ const Light& getLight(unsigned i) const
+ { return _lights[i]; }
+
+private:
+ LightList _lights;
+};
+
+#endif
--- /dev/null
+/* -*-c++-*-
+ *
+ * Copyright (C) 2006-2007 Mathias Froehlich
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <simgear_config.h>
+#endif
+
+#include "SGOceanTile.hxx"
+
+#include <simgear/compiler.h>
+
+#include <osg/Geode>
+#include <osg/Geometry>
+#include <osg/StateSet>
+
+#include <simgear/bucket/newbucket.hxx>
+#include <simgear/math/sg_geodesy.hxx>
+#include <simgear/math/sg_types.hxx>
+#include <simgear/misc/texcoord.hxx>
+#include <simgear/scene/material/mat.hxx>
+#include <simgear/scene/material/matlib.hxx>
+
+// Generate an ocean tile
+osg::Node* SGOceanTile(const SGBucket& b, SGMaterialLib *matlib)
+{
+ osg::StateSet *stateSet = 0;
+
+ double tex_width = 1000.0;
+
+ // find Ocean material in the properties list
+ SGMaterial *mat = matlib->find( "Ocean" );
+ if ( mat != NULL ) {
+ // set the texture width and height values for this
+ // material
+ tex_width = mat->get_xsize();
+
+ // set ssgState
+ stateSet = mat->get_state();
+ } else {
+ SG_LOG( SG_TERRAIN, SG_ALERT, "Ack! unknown use material name = Ocean");
+ }
+
+ // 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();
+
+ // Caculate corner vertices
+ SGGeod geod[4];
+ geod[0] = SGGeod::fromDeg( clon - 0.5*width, clat - 0.5*height );
+ geod[1] = SGGeod::fromDeg( clon + 0.5*width, clat - 0.5*height );
+ geod[2] = SGGeod::fromDeg( clon + 0.5*width, clat + 0.5*height );
+ geod[3] = SGGeod::fromDeg( clon - 0.5*width, clat + 0.5*height );
+
+ int i;
+ SGVec3f normals[4];
+ SGVec3d rel[4];
+ for ( i = 0; i < 4; ++i ) {
+ SGVec3d cart = SGVec3d::fromGeod(geod[i]);
+ rel[i] = cart - center.toSGVec3d();
+ normals[i] = toVec3f(normalize(cart));
+ }
+
+ // Calculate texture coordinates
+ point_list geod_nodes;
+ geod_nodes.clear();
+ geod_nodes.reserve(4);
+ int_list rectangle;
+ rectangle.clear();
+ rectangle.reserve(4);
+ for ( i = 0; i < 4; ++i ) {
+ geod_nodes.push_back( Point3D::fromSGGeod(geod[i]) );
+ rectangle.push_back( i );
+ }
+ point_list texs = sgCalcTexCoords( b, geod_nodes, rectangle,
+ 1000.0 / tex_width );
+
+ // Allocate ssg structure
+ osg::Vec3Array *vl = new osg::Vec3Array;
+ osg::Vec3Array *nl = new osg::Vec3Array;
+ osg::Vec2Array *tl = new osg::Vec2Array;
+
+ for ( i = 0; i < 4; ++i ) {
+ vl->push_back(rel[i].osg());
+ nl->push_back(normals[i].osg());
+ tl->push_back(texs[i].toSGVec2f().osg());
+ }
+
+ osg::Vec4Array* cl = new osg::Vec4Array;
+ cl->push_back(osg::Vec4(1, 1, 1, 1));
+
+ osg::Geometry* geometry = new osg::Geometry;
+ geometry->setVertexArray(vl);
+ geometry->setNormalArray(nl);
+ geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
+ geometry->setColorArray(cl);
+ geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
+ geometry->setTexCoordArray(0, tl);
+ osg::DrawArrays* drawArrays;
+ drawArrays = new osg::DrawArrays(GL_TRIANGLE_FAN, 0, vl->size());
+ geometry->addPrimitiveSet(drawArrays);
+
+ osg::Geode* geode = new osg::Geode;
+ geode->setName("Ocean tile");
+ geode->addDrawable(geometry);
+ geode->setStateSet(stateSet);
+
+ return geode;
+}
--- /dev/null
+/* -*-c++-*-
+ *
+ * Copyright (C) 2006-2007 Mathias Froehlich
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ */
+
+#ifndef _SG_OceanTile_HXX
+#define _SG_OceanTile_HXX
+
+#include <osg/Node>
+
+class SGBucket;
+class SGMaterialLib;
+
+// Generate an ocean tile
+osg::Node* SGOceanTile(const SGBucket& b, SGMaterialLib *matlib);
+
+#endif // _SG_OBJ_HXX
--- /dev/null
+/* -*-c++-*-
+ *
+ * Copyright (C) 2006-2007 Mathias Froehlich
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ */
+
+#ifndef SG_TEXTURED_TRIANGLE_BIN_HXX
+#define SG_TEXTURED_TRIANGLE_BIN_HXX
+
+#include <osg/Array>
+#include <osg/Geometry>
+#include <osg/PrimitiveSet>
+
+#include <simgear/math/sg_random.h>
+#include <simgear/math/SGMath.hxx>
+#include "SGTriangleBin.hxx"
+
+struct SGVertNormTex {
+ SGVertNormTex()
+ { }
+ SGVertNormTex(const SGVec3f& v, const SGVec3f& n, const SGVec2f& t) :
+ vertex(v), normal(n), texCoord(t)
+ { }
+ struct less
+ {
+ inline bool operator() (const SGVertNormTex& l,
+ const SGVertNormTex& r) const
+ {
+ if (l.vertex < r.vertex) return true;
+ else if (r.vertex < l.vertex) return false;
+ else if (l.normal < r.normal) return true;
+ else if (r.normal < l.normal) return false;
+ else return l.texCoord < r.texCoord;
+ }
+ };
+
+ SGVec3f vertex;
+ SGVec3f normal;
+ SGVec2f texCoord;
+};
+
+class SGTexturedTriangleBin : public SGTriangleBin<SGVertNormTex> {
+public:
+
+ // Computes and adds random surface points to the points list.
+ // The random points are computed with a density of (coverage points)/1
+ // The points are offsetted away from the triangles in
+ // offset * positive normal direction.
+ void addRandomSurfacePoints(float coverage, float offset,
+ std::vector<SGVec3f>& points) const
+ {
+ unsigned num = getNumTriangles();
+ for (unsigned i = 0; i < num; ++i) {
+ triangle_ref triangleRef = getTriangleRef(i);
+ SGVec3f v0 = getVertex(triangleRef[0]).vertex;
+ SGVec3f v1 = getVertex(triangleRef[1]).vertex;
+ SGVec3f v2 = getVertex(triangleRef[2]).vertex;
+ SGVec3f normal = cross(v1 - v0, v2 - v0);
+
+ // Compute the area
+ float area = 0.5f*length(normal);
+ if (area <= SGLimitsf::min())
+ continue;
+
+ // For partial units of area, use a zombie door method to
+ // create the proper random chance of a light being created
+ // for this triangle
+ float unit = area + sg_random()*coverage;
+
+ SGVec3f offsetVector = offset*normalize(normal);
+ // generate a light point for each unit of area
+ while ( coverage < unit ) {
+ float a = sg_random();
+ float b = sg_random();
+ if ( a + b > 1 ) {
+ a = 1 - a;
+ b = 1 - b;
+ }
+ float c = 1 - a - b;
+ SGVec3f randomPoint = offsetVector + a*v0 + b*v1 + c*v2;
+ points.push_back(randomPoint);
+ unit -= coverage;
+ }
+ }
+ }
+
+ osg::Geometry* buildGeometry(const TriangleVector& triangles) const
+ {
+ // Do not build anything if there is nothing in here ...
+ if (empty() || triangles.empty())
+ return 0;
+
+ // FIXME: do not include all values here ...
+ osg::Vec3Array* vertices = new osg::Vec3Array;
+ osg::Vec3Array* normals = new osg::Vec3Array;
+ osg::Vec2Array* texCoords = new osg::Vec2Array;
+
+ osg::Vec4Array* colors = new osg::Vec4Array;
+ colors->push_back(osg::Vec4(1, 1, 1, 1));
+
+ osg::Geometry* geometry = new osg::Geometry;
+ geometry->setVertexArray(vertices);
+ geometry->setNormalArray(normals);
+ geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
+ geometry->setColorArray(colors);
+ geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
+ geometry->setTexCoordArray(0, texCoords);
+
+ const unsigned invalid = ~unsigned(0);
+ std::vector<unsigned> indexMap(getNumVertices(), invalid);
+
+ osg::DrawElementsUInt* drawElements;
+ drawElements = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES);
+ for (index_type i = 0; i < triangles.size(); ++i) {
+ triangle_ref triangle = triangles[i];
+ if (indexMap[triangle[0]] == invalid) {
+ indexMap[triangle[0]] = vertices->size();
+ vertices->push_back(getVertex(triangle[0]).vertex.osg());
+ normals->push_back(getVertex(triangle[0]).normal.osg());
+ texCoords->push_back(getVertex(triangle[0]).texCoord.osg());
+ }
+ drawElements->push_back(indexMap[triangle[0]]);
+
+ if (indexMap[triangle[1]] == invalid) {
+ indexMap[triangle[1]] = vertices->size();
+ vertices->push_back(getVertex(triangle[1]).vertex.osg());
+ normals->push_back(getVertex(triangle[1]).normal.osg());
+ texCoords->push_back(getVertex(triangle[1]).texCoord.osg());
+ }
+ drawElements->push_back(indexMap[triangle[1]]);
+
+ if (indexMap[triangle[2]] == invalid) {
+ indexMap[triangle[2]] = vertices->size();
+ vertices->push_back(getVertex(triangle[2]).vertex.osg());
+ normals->push_back(getVertex(triangle[2]).normal.osg());
+ texCoords->push_back(getVertex(triangle[2]).texCoord.osg());
+ }
+ drawElements->push_back(indexMap[triangle[2]]);
+ }
+ geometry->addPrimitiveSet(drawElements);
+
+ return geometry;
+ }
+
+ osg::Geometry* buildGeometry() const
+ { return buildGeometry(getTriangles()); }
+};
+
+#endif
--- /dev/null
+/* -*-c++-*-
+ *
+ * Copyright (C) 2006-2007 Mathias Froehlich
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ */
+
+#ifndef SG_TRIANGLE_BIN_HXX
+#define SG_TRIANGLE_BIN_HXX
+
+#include <vector>
+#include <map>
+#include "SGVertexArrayBin.hxx"
+
+template<typename T>
+class SGTriangleBin : public SGVertexArrayBin<T> {
+public:
+#define BUILD_EDGE_MAP
+ typedef typename SGVertexArrayBin<T>::value_type value_type;
+ typedef typename SGVertexArrayBin<T>::index_type index_type;
+ typedef SGVec2<index_type> edge_ref;
+ typedef SGVec3<index_type> triangle_ref;
+ typedef std::vector<triangle_ref> TriangleVector;
+ typedef std::vector<index_type> TriangleList;
+ typedef std::map<edge_ref,TriangleList> EdgeMap;
+
+ void insert(const value_type& v0, const value_type& v1, const value_type& v2)
+ {
+ index_type i0 = SGVertexArrayBin<T>::insert(v0);
+ index_type i1 = SGVertexArrayBin<T>::insert(v1);
+ index_type i2 = SGVertexArrayBin<T>::insert(v2);
+ index_type triangleIndex = _triangleVector.size();
+ _triangleVector.push_back(triangle_ref(i0, i1, i2));
+#ifdef BUILD_EDGE_MAP
+ _edgeMap[edge_ref(i0, i1)].push_back(triangleIndex);
+ _edgeMap[edge_ref(i1, i2)].push_back(triangleIndex);
+ _edgeMap[edge_ref(i2, i0)].push_back(triangleIndex);
+#endif
+ }
+
+ unsigned getNumTriangles() const
+ { return _triangleVector.size(); }
+ const triangle_ref& getTriangleRef(index_type i) const
+ { return _triangleVector[i]; }
+ const TriangleVector& getTriangles() const
+ { return _triangleVector; }
+
+#ifdef BUILD_EDGE_MAP
+// protected: //FIXME
+ void getConnectedSets(std::list<TriangleVector>& connectSets) const
+ {
+ std::vector<bool> processedTriangles(getNumTriangles(), false);
+ for (index_type i = 0; i < getNumTriangles(); ++i) {
+ if (processedTriangles[i])
+ continue;
+
+ TriangleVector currentSet;
+ std::vector<edge_ref> edgeStack;
+
+ {
+ triangle_ref triangleRef = getTriangleRef(i);
+ edgeStack.push_back(edge_ref(triangleRef[0], triangleRef[1]));
+ edgeStack.push_back(edge_ref(triangleRef[1], triangleRef[2]));
+ edgeStack.push_back(edge_ref(triangleRef[2], triangleRef[0]));
+ currentSet.push_back(triangleRef);
+ processedTriangles[i] = true;
+ }
+
+ while (!edgeStack.empty()) {
+ edge_ref edge = edgeStack.back();
+ edgeStack.pop_back();
+
+ typename EdgeMap::const_iterator emiList[2] = {
+ _edgeMap.find(edge),
+ _edgeMap.find(edge_ref(edge[1], edge[0]))
+ };
+ for (unsigned ei = 0; ei < 2; ++ei) {
+ typename EdgeMap::const_iterator emi = emiList[ei];
+ if (emi == _edgeMap.end())
+ continue;
+
+ for (unsigned ti = 0; ti < emi->second.size(); ++ti) {
+ index_type triangleIndex = emi->second[ti];
+ if (processedTriangles[triangleIndex])
+ continue;
+
+ triangle_ref triangleRef = getTriangleRef(triangleIndex);
+ edgeStack.push_back(edge_ref(triangleRef[0], triangleRef[1]));
+ edgeStack.push_back(edge_ref(triangleRef[1], triangleRef[2]));
+ edgeStack.push_back(edge_ref(triangleRef[2], triangleRef[0]));
+ currentSet.push_back(triangleRef);
+ processedTriangles[triangleIndex] = true;
+ }
+ }
+ }
+
+ connectSets.push_back(currentSet);
+ }
+ }
+#endif
+
+private:
+ TriangleVector _triangleVector;
+#ifdef BUILD_EDGE_MAP
+ EdgeMap _edgeMap;
+#endif
+};
+
+#endif
--- /dev/null
+/* -*-c++-*-
+ *
+ * Copyright (C) 2006-2007 Mathias Froehlich
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <simgear_config.h>
+#endif
+
+#include <simgear/compiler.h>
+
+#include "SGVasiDrawable.hxx"
+
+struct SGVasiDrawable::LightData {
+ LightData(const SGVec3f& p, const SGVec3f& n, const SGVec3f& up) :
+ position(p),
+ normal(n),
+ horizontal(normalize(cross(up, n))),
+ normalCrossHorizontal(normalize(cross(n, horizontal)))
+ { }
+
+ void draw(const SGVec4f& color) const
+ {
+ glBegin(GL_POINTS);
+ glColor4fv(color.data());
+ glNormal3fv(normal.data());
+ glVertex3fv(position.data());
+ glEnd();
+ }
+
+ SGVec3f position;
+ SGVec3f normal;
+ SGVec3f horizontal;
+ SGVec3f normalCrossHorizontal;
+};
+
+SGVasiDrawable::SGVasiDrawable(const SGVasiDrawable& vd, const osg::CopyOp&) :
+ _lights(vd._lights),
+ _red(vd._red),
+ _white(vd._white)
+{
+ setUseDisplayList(false);
+ setSupportsDisplayList(false);
+}
+
+SGVasiDrawable::SGVasiDrawable(const SGVec4f& red, const SGVec4f& white) :
+ _red(red),
+ _white(white)
+{
+ setUseDisplayList(false);
+ setSupportsDisplayList(false);
+}
+
+void
+SGVasiDrawable::addLight(const SGVec3f& position, const SGVec3f& normal,
+ const SGVec3f& up, float azimutDeg)
+{
+ SGVec3f horizontal(normalize(cross(up, normal)));
+ SGVec3f zeroGlideSlope = normalize(cross(horizontal, up));
+ SGQuatf rotation = SGQuatf::fromAngleAxisDeg(azimutDeg, horizontal);
+ SGVec3f azimutGlideSlope = rotation.transform(zeroGlideSlope);
+ addLight(position, azimutGlideSlope, up);
+}
+
+void
+SGVasiDrawable::addLight(const SGVec3f& position, const SGVec3f& normal,
+ const SGVec3f& up)
+{
+ _lights.push_back(LightData(position, normal, up));
+}
+
+void
+SGVasiDrawable::drawImplementation(osg::RenderInfo& renderInfo) const
+{
+ // Make sure we have the current state set
+// renderInfo.getState()->apply();
+
+ // Retrieve the eye point in local coords
+ osg::Matrix m;
+ m.invert(renderInfo.getState()->getModelViewMatrix());
+ SGVec3f eyePoint(m.preMult(osg::Vec3(0, 0, 0)));
+
+ // paint the points
+ for (unsigned i = 0; i < _lights.size(); ++i)
+ draw(eyePoint, _lights[i]);
+}
+
+osg::BoundingBox
+SGVasiDrawable::computeBound() const
+{
+ osg::BoundingBox bb;
+ for (unsigned i = 0; i < _lights.size(); ++i)
+ bb.expandBy(_lights[i].position.osg());
+
+ // blow up to avoid being victim to small feature culling ...
+ bb.expandBy(bb._min - osg::Vec3(1, 1, 1));
+ bb.expandBy(bb._max + osg::Vec3(1, 1, 1));
+ return bb;
+}
+
+SGVec4f
+SGVasiDrawable::getColor(float angleDeg) const
+{
+ float transDeg = 0.05f;
+ if (angleDeg < -transDeg) {
+ return _red;
+ } else if (angleDeg < transDeg) {
+ float fac = angleDeg*0.5f/transDeg + 0.5f;
+ return _red + fac*(_white - _red);
+ } else {
+ return _white;
+ }
+}
+
+void
+SGVasiDrawable::draw(const SGVec3f& eyePoint, const LightData& light) const
+{
+ // vector pointing from the light position to the eye
+ SGVec3f lightToEye = eyePoint - light.position;
+
+ // dont' draw, we are behind it
+ if (dot(lightToEye, light.normal) < SGLimitsf::min())
+ return;
+
+ // Now project the eye point vector into the plane defined by the
+ // glideslope direction and the up direction
+ SGVec3f projLightToEye = lightToEye
+ - light.horizontal*dot(lightToEye, light.horizontal);
+
+ // dont' draw, if we are to near, looks like we are already behind
+ float sqrProjLightToEyeLength = dot(projLightToEye, projLightToEye);
+ if (sqrProjLightToEyeLength < 1e-3*1e-3)
+ return;
+
+ // the scalar product of the glide slope up direction with the eye vector
+ float dotProd = dot(projLightToEye, light.normalCrossHorizontal);
+ float sinAngle = dotProd/sqrt(sqrProjLightToEyeLength);
+ if (sinAngle < -1)
+ sinAngle = -1;
+ if (1 < sinAngle)
+ sinAngle = 1;
+
+ float angleDeg = SGMiscf::rad2deg(asin(sinAngle));
+ light.draw(getColor(angleDeg));
+}
+
--- /dev/null
+/* -*-c++-*-
+ *
+ * Copyright (C) 2006-2007 Mathias Froehlich
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ */
+
+#ifndef _SG_VASI_DRAWABLE_HXX
+#define _SG_VASI_DRAWABLE_HXX
+
+#include <simgear/compiler.h>
+
+#include <osg/Drawable>
+#include <simgear/math/SGMath.hxx>
+
+class SGVasiDrawable : public osg::Drawable {
+ struct LightData;
+public:
+ META_Object(SimGear, SGVasiDrawable);
+ SGVasiDrawable(const SGVasiDrawable&, const osg::CopyOp&);
+ SGVasiDrawable(const SGVec4f& red = SGVec4f(1, 0, 0, 1),
+ const SGVec4f& white = SGVec4f(1, 1, 1, 1));
+
+ /// Add a red/white switching light pointing into the direction that
+ /// is computed to point in about the given normal with the given
+ /// azimut angle upwards. The up direction is the world up direction
+ /// that defines the horizontal plane.
+ void addLight(const SGVec3f& position, const SGVec3f& normal,
+ const SGVec3f& up, float azimutDeg);
+
+ /// add a red/white switching light pointing towards normal
+ /// at the given position with the given up vector. The up direction
+ /// is the world up direction that defines the horizontal plane.
+ void addLight(const SGVec3f& position, const SGVec3f& normal,
+ const SGVec3f& up);
+
+ virtual void drawImplementation(osg::RenderInfo& renderInfo) const;
+ virtual osg::BoundingBox computeBound() const;
+
+private:
+ SGVec4f getColor(float angleDeg) const;
+ void draw(const SGVec3f& eyePoint, const LightData& light) const;
+
+ std::vector<LightData> _lights;
+ SGVec4f _red;
+ SGVec4f _white;
+};
+
+#endif // _SG_VASI_LIGHT_HXX
--- /dev/null
+/* -*-c++-*-
+ *
+ * Copyright (C) 2006-2007 Mathias Froehlich
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ */
+
+#ifndef SG_VERTEX_ARRAY_BIN_HXX
+#define SG_VERTEX_ARRAY_BIN_HXX
+
+#include <vector>
+#include <map>
+
+template<typename T>
+class SGVertexArrayBin {
+public:
+ typedef T value_type;
+ typedef typename value_type::less less;
+ typedef std::vector<value_type> ValueVector;
+ typedef typename ValueVector::size_type index_type;
+ typedef std::map<value_type, index_type, less> ValueMap;
+
+ index_type insert(const value_type& t)
+ {
+ typename ValueMap::iterator i = _valueMap.find(t);
+ if (i != _valueMap.end())
+ return i->second;
+
+ index_type index = _values.size();
+ _valueMap[t] = index;
+ _values.push_back(t);
+ return index;
+ }
+
+ const value_type& getVertex(index_type index) const
+ { return _values[index]; }
+
+ index_type getNumVertices() const
+ { return _values.size(); }
+
+ bool empty() const
+ { return _values.empty(); }
+
+private:
+ ValueVector _values;
+ ValueMap _valueMap;
+};
+
+#endif
+++ /dev/null
-// 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 - http://www.flightgear.org/~curt
-//
-// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 <osg/Array>
-#include <osg/Node>
-
-#include <simgear/math/sg_types.hxx>
-
-SG_USING_STD(string);
-
-
-class SGMaterialLib; // forward declaration.
-
-
-// Create a ssg leaf
-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,
- const int_list& normal_index,
- const int_list& tex_index,
- const bool calc_lights, osg::Vec3Array *lights );
-
-#endif // _SG_LEAF_HXX
# include <simgear_config.h>
#endif
-#include <simgear/compiler.h>
-
-#include <list>
+#include "obj.hxx"
-#include STL_STRING
+#include <simgear/compiler.h>
-#include <osg/Depth>
#include <osg/Fog>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/Group>
#include <osg/LOD>
#include <osg/MatrixTransform>
+#include <osg/Point>
#include <osg/StateSet>
+#include <osg/Switch>
-#include <osgUtil/Optimizer>
-#include <osgDB/WriteFile>
-
-#include <simgear/bucket/newbucket.hxx>
+#include <simgear/debug/logstream.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/model/SGOffsetTransform.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>
-
-#include "obj.hxx"
-
-SG_USING_STD(string);
-SG_USING_STD(list);
-
-struct Leaf {
- GLenum type;
- int index;
-};
+#include <simgear/threads/SGThread.hxx>
+#include <simgear/threads/SGGuard.hxx>
+
+#include "SGTexturedTriangleBin.hxx"
+#include "SGLightBin.hxx"
+#include "SGDirectionalLightBin.hxx"
+
+#include "pt_lights.hxx"
+
+typedef std::map<std::string,SGTexturedTriangleBin> SGMaterialTriangleMap;
+typedef std::list<SGLightBin> SGLightListBin;
+typedef std::list<SGDirectionalLightBin> SGDirectionalLightListBin;
+
+struct SGTileGeometryBin {
+ SGMaterialTriangleMap materialTriangleMap;
+ SGLightBin tileLights;
+ SGLightBin randomTileLights;
+ SGDirectionalLightBin runwayLights;
+ SGDirectionalLightBin taxiLights;
+ SGDirectionalLightListBin vasiLights;
+ SGDirectionalLightListBin rabitLights;
+ SGLightListBin odalLights;
+ SGDirectionalLightListBin reilLights;
+
+ static SGVec4f
+ getMaterialLightColor(const SGMaterial* material)
+ {
+ if (!material)
+ return SGVec4f(1, 1, 1, 0.8);
+ return material->get_light_color();
+ }
+ static void
+ addPointGeometry(SGLightBin& lights,
+ const std::vector<SGVec3d>& vertices,
+ const SGVec4f& color,
+ const int_list& pts_v)
+ {
+ for (unsigned i = 0; i < pts_v.size(); ++i)
+ lights.insert(toVec3f(vertices[pts_v[i]]), color);
+ }
-// Generate an ocean tile
-bool SGGenTile( const string& path, const SGBucket& b,
- SGMaterialLib *matlib, osg::Group* group )
-{
- osg::StateSet *state = 0;
-
- double tex_width = 1000.0;
-
- // find Ocean material in the properties list
- SGMaterial *mat = matlib->find( "Ocean" );
- if ( mat != NULL ) {
- // set the texture width and height values for this
- // material
- tex_width = mat->get_xsize();
-
- // set ssgState
- state = mat->get_state();
+ static void
+ addPointGeometry(SGDirectionalLightBin& lights,
+ const std::vector<SGVec3d>& vertices,
+ const std::vector<SGVec3f>& normals,
+ const SGVec4f& color,
+ const int_list& pts_v,
+ const int_list& pts_n)
+ {
+ // If the normal indices match the vertex indices, use seperate
+ // normal indices. Else reuse the vertex indices for the normals.
+ if (pts_v.size() == pts_n.size()) {
+ for (unsigned i = 0; i < pts_v.size(); ++i)
+ lights.insert(toVec3f(vertices[pts_v[i]]), normals[pts_n[i]], color);
} else {
- SG_LOG( SG_TERRAIN, SG_ALERT,
- "Ack! unknown usemtl name = " << "Ocean"
- << " in " << path );
- }
-
- // 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();
-
- // Caculate corner vertices
- Point3D geod[4];
- geod[0] = Point3D( clon - width/2.0, clat - height/2.0, 0.0 );
- geod[1] = Point3D( clon + width/2.0, clat - height/2.0, 0.0 );
- geod[2] = Point3D( clon + width/2.0, clat + height/2.0, 0.0 );
- geod[3] = Point3D( clon - width/2.0, clat + height/2.0, 0.0 );
-
- Point3D rad[4];
- int i;
- for ( i = 0; i < 4; ++i ) {
- rad[i] = Point3D( geod[i].x() * SGD_DEGREES_TO_RADIANS,
- geod[i].y() * SGD_DEGREES_TO_RADIANS,
- geod[i].z() );
- }
-
- Point3D cart[4], rel[4];
- for ( i = 0; i < 4; ++i ) {
- cart[i] = sgGeodToCart(rad[i]);
- rel[i] = cart[i] - center;
- // cout << "corner " << i << " = " << cart[i] << endl;
+ for (unsigned i = 0; i < pts_v.size(); ++i)
+ lights.insert(toVec3f(vertices[pts_v[i]]), normals[pts_v[i]], color);
}
+ }
- // Calculate normals
- Point3D normals[4];
- for ( i = 0; i < 4; ++i ) {
- double length = cart[i].distance3D( Point3D(0.0) );
- normals[i] = cart[i] / length;
- // cout << "normal = " << normals[i] << endl;
+ bool
+ insertPtGeometry(const SGBinObject& obj, SGMaterialLib* matlib)
+ {
+ if (obj.get_pts_v().size() != obj.get_pts_n().size()) {
+ SG_LOG(SG_TERRAIN, SG_ALERT,
+ "Group list sizes for points do not match!");
+ return false;
}
- // Calculate texture coordinates
- point_list geod_nodes;
- geod_nodes.clear();
- geod_nodes.reserve(4);
- int_list rectangle;
- rectangle.clear();
- rectangle.reserve(4);
- for ( i = 0; i < 4; ++i ) {
- geod_nodes.push_back( geod[i] );
- rectangle.push_back( i );
- }
- point_list texs = sgCalcTexCoords( b, geod_nodes, rectangle,
- 1000.0 / tex_width );
-
- // Allocate ssg structure
- osg::Vec3Array *vl = new osg::Vec3Array;
- osg::Vec3Array *nl = new osg::Vec3Array;
- osg::Vec2Array *tl = new osg::Vec2Array;
-
- for ( i = 0; i < 4; ++i ) {
- vl->push_back(osg::Vec3(rel[i].x(), rel[i].y(), rel[i].z()));
- nl->push_back(osg::Vec3(normals[i].x(), normals[i].y(), normals[i].z()));
- tl->push_back(osg::Vec2(texs[i].x(), texs[i].y()));
+ for (unsigned grp = 0; grp < obj.get_pts_v().size(); ++grp) {
+ std::string materialName = obj.get_pt_materials()[grp];
+ SGMaterial* material = matlib->find(materialName);
+ SGVec4f color = getMaterialLightColor(material);
+
+ if (3 <= materialName.size() && materialName.substr(0, 3) != "RWY") {
+ // Just plain lights. Not something for the runway.
+ addPointGeometry(tileLights, obj.get_wgs84_nodes(), color,
+ obj.get_pts_v()[grp]);
+ } else if (materialName == "RWY_BLUE_TAXIWAY_LIGHTS"
+ || materialName == "RWY_GREEN_TAXIWAY_LIGHTS") {
+ addPointGeometry(taxiLights, obj.get_wgs84_nodes(), obj.get_normals(),
+ color, obj.get_pts_v()[grp], obj.get_pts_n()[grp]);
+ } else if (materialName == "RWY_VASI_LIGHTS") {
+ vasiLights.push_back(SGDirectionalLightBin());
+ addPointGeometry(vasiLights.back(), obj.get_wgs84_nodes(),
+ obj.get_normals(), color, obj.get_pts_v()[grp],
+ obj.get_pts_n()[grp]);
+ } else if (materialName == "RWY_SEQUENCED_LIGHTS") {
+ rabitLights.push_back(SGDirectionalLightBin());
+ addPointGeometry(rabitLights.back(), obj.get_wgs84_nodes(),
+ obj.get_normals(), color, obj.get_pts_v()[grp],
+ obj.get_pts_n()[grp]);
+ } else if (materialName == "RWY_ODALS_LIGHTS") {
+ odalLights.push_back(SGLightBin());
+ addPointGeometry(odalLights.back(), obj.get_wgs84_nodes(),
+ color, obj.get_pts_v()[grp]);
+ } else if (materialName == "RWY_REIL_LIGHTS") {
+ reilLights.push_back(SGDirectionalLightBin());
+ addPointGeometry(reilLights.back(), obj.get_wgs84_nodes(),
+ obj.get_normals(), color, obj.get_pts_v()[grp],
+ obj.get_pts_n()[grp]);
+ } else {
+ // what is left must be runway lights
+ addPointGeometry(runwayLights, obj.get_wgs84_nodes(),
+ obj.get_normals(), color, obj.get_pts_v()[grp],
+ obj.get_pts_n()[grp]);
+ }
}
-
- osg::Vec4Array* cl = new osg::Vec4Array;
- cl->push_back(osg::Vec4(1, 1, 1, 1));
-
- osg::Geometry* geometry = new osg::Geometry;
- geometry->setVertexArray(vl);
- geometry->setNormalArray(nl);
- geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
- geometry->setColorArray(cl);
- geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
- geometry->setTexCoordArray(0, tl);
- geometry->addPrimitiveSet(new osg::DrawArrays(GL_TRIANGLE_FAN, 0, vl->size()));
- osg::Geode* geode = new osg::Geode;
- geode->setName(path);
- geode->addDrawable(geometry);
- geode->setStateSet(state);
-
- group->addChild(geode);
return true;
-}
-
-
-/**
- * SSG callback for an in-range leaf of randomly-placed objects.
- *
- * This pretraversal callback is attached to a branch that is
- * traversed only when a leaf is in range. If the leaf is not
- * currently prepared to be populated with randomly-placed objects,
- * this callback will prepare it (actual population is handled by
- * the tri_in_range_callback for individual triangles).
- *
- * @param entity The entity to which the callback is attached (not used).
- * @param mask The entity's traversal mask (not used).
- * @return Always 1, to allow traversal and culling to continue.
- */
-// static int
-// leaf_in_range_callback (ssgEntity * entity, int mask)
-// {
-// SGLeafUserData * data = (SGLeafUserData *)entity->getUserData();
-
-// if (!data->is_filled_in) {
-// // Iterate through all the triangles
-// // and populate them.
-// int num_tris = data->leaf->getNumTriangles();
-// for ( int i = 0; i < num_tris; ++i ) {
-// data->setup_triangle(i);
-// }
-// data->is_filled_in = true;
-// }
-// return 1;
-// }
-
-
-/**
- * SSG callback for an out-of-range leaf of randomly-placed objects.
- *
- * This pretraversal callback is attached to a branch that is
- * traversed only when a leaf is out of range. If the leaf is
- * currently prepared to be populated with randomly-placed objects (or
- * is actually populated), the objects will be removed.
- *
- * @param entity The entity to which the callback is attached (not used).
- * @param mask The entity's traversal mask (not used).
- * @return Always 0, to prevent any further traversal or culling.
- */
-// static int
-// leaf_out_of_range_callback (ssgEntity * entity, int mask)
-// {
-// SGLeafUserData * data = (SGLeafUserData *)entity->getUserData();
-// if (data->is_filled_in) {
-// data->branch->removeAllKids();
-// data->is_filled_in = false;
-// }
-// return 0;
-// }
-
-
-/**
- * Randomly place objects on a surface.
- *
- * The leaf node provides the geometry of the surface, while the
- * material provides the objects and placement density. Latitude
- * and longitude are required so that the objects can be rotated
- * to the world-up vector. This function does not actually add
- * any objects; instead, it attaches an ssgRangeSelector to the
- * branch with callbacks to generate the objects when needed.
- *
- * @param leaf The surface where the objects should be placed.
- * @param branch The branch that will hold the randomly-placed objects.
- * @param center The center of the leaf in FlightGear coordinates.
- * @param material_name The name of the surface's material.
- */
-static void
-gen_random_surface_objects (osg::Drawable *leaf,
- osg::Group *branch,
- Point3D *center,
- SGMaterial *mat )
-{
- // OSGFIXME
-#if 0
- // If the surface has no triangles, return
- // now.
- int num_tris = leaf->getNumTriangles();
- if (num_tris < 1)
- return;
-
- // If the material has no randomly-placed
- // objects, return now.
- if (mat->get_object_group_count() < 1)
- return;
-
- // Calculate the geodetic centre of
- // the tile, for aligning automatic
- // objects.
- double xyz[3], lon_rad, lat_rad, alt_m;
- xyz[0] = center->x(); xyz[1] = center->y(); xyz[2] = center->z();
- sgCartToGeod(xyz, &lat_rad, &lon_rad, &alt_m);
-
- // LOD for the leaf
- // max random object range: 20000m
- osg::LOD * lod = new osg::LOD;
- branch->addChild(lod);
-
- // Create the in-range and out-of-range
- // branches.
- osg::Group * in_range = new osg::Group;
-// osg::Group * out_of_range = new osg::Group;
- lod->addChild(in_range, 0, 20000 /*OSGFIXME hardcoded visibility ???*/);
-// lod->addChild(out_of_range, 20000, 1e30);
-
- SGLeafUserData * data = new SGLeafUserData;
- data->is_filled_in = false;
- data->leaf = leaf;
- data->mat = mat;
- data->branch = in_range;
- data->sin_lat = sin(lat_rad);
- data->cos_lat = cos(lat_rad);
- data->sin_lon = sin(lon_rad);
- data->cos_lon = cos(lon_rad);
-
- in_range->setUserData(data);
- // OSGFIXME: implement random objects to be loaded when in sight
-// in_range->setTravCallback(SSG_CALLBACK_PRETRAV, leaf_in_range_callback);
-
- // OSGFIXME: implement deletion of tiles that are no longer used
-// out_of_range->setUserData(data);
-// out_of_range->setTravCallback(SSG_CALLBACK_PRETRAV,
-// leaf_out_of_range_callback);
-// out_of_range
-// ->addChild(new SGDummyBSphereEntity(leaf->getBSphere()->getRadius()));
-#endif
-}
+ }
-// Ok, somehow polygon offset for lights ...
-// Could never make the polygon offset for our lights get right.
-// So, why not in this way ...
-class SGLightOffsetTransform : public osg::Transform {
-public:
-#define SCALE_FACTOR 0.94
- virtual bool computeLocalToWorldMatrix(osg::Matrix& matrix,
- osg::NodeVisitor* nv) const
+ static SGVec2f
+ getTexCoord(const std::vector<SGVec2f>& texCoords, const int_list& tc,
+ const SGVec2f& tcScale, unsigned i)
{
- if (nv && nv->getVisitorType() == osg::NodeVisitor::CULL_VISITOR) {
- double scaleFactor = SCALE_FACTOR;
- osg::Vec3 center = nv->getEyePoint();
- osg::Matrix transform;
- transform(0,0) = scaleFactor;
- transform(1,1) = scaleFactor;
- transform(2,2) = scaleFactor;
- transform(3,0) = center[0]*(1 - scaleFactor);
- transform(3,1) = center[1]*(1 - scaleFactor);
- transform(3,2) = center[2]*(1 - scaleFactor);
- matrix.preMult(transform);
- }
- return true;
+ if (tc.empty())
+ return tcScale;
+ else if (tc.size() == 1)
+ return mult(texCoords[tc[0]], tcScale);
+ else
+ return mult(texCoords[tc[i]], tcScale);
}
- virtual bool computeWorldToLocalMatrix(osg::Matrix& matrix,
- osg::NodeVisitor* nv) const
+
+ static void
+ addTriangleGeometry(SGTexturedTriangleBin& triangles,
+ const std::vector<SGVec3d>& vertices,
+ const std::vector<SGVec3f>& normals,
+ const std::vector<SGVec2f>& texCoords,
+ const int_list& tris_v,
+ const int_list& tris_n,
+ const int_list& tris_tc,
+ const SGVec2f& tcScale)
{
- if (nv && nv->getVisitorType() == osg::NodeVisitor::CULL_VISITOR) {
- double scaleFactor = 1/SCALE_FACTOR;
- osg::Vec3 center = nv->getEyePoint();
- osg::Matrix transform;
- transform(0,0) = scaleFactor;
- transform(1,1) = scaleFactor;
- transform(2,2) = scaleFactor;
- transform(3,0) = center[0]*(1 - scaleFactor);
- transform(3,1) = center[1]*(1 - scaleFactor);
- transform(3,2) = center[2]*(1 - scaleFactor);
- matrix.postMult(transform);
+ if (tris_v.size() != tris_n.size()) {
+ // If the normal indices do not match, they should be inmplicitly
+ // the same than the vertex indices. So just call ourselves again
+ // with the matching index vector.
+ addTriangleGeometry(triangles, vertices, normals, texCoords,
+ tris_v, tris_v, tris_tc, tcScale);
+ return;
}
- 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 );
+ for (unsigned i = 2; i < tris_v.size(); i += 3) {
+ SGVertNormTex v0;
+ v0.vertex = toVec3f(vertices[tris_v[i-2]]);
+ v0.normal = normals[tris_n[i-2]];
+ v0.texCoord = getTexCoord(texCoords, tris_tc, tcScale, i-2);
+ SGVertNormTex v1;
+ v1.vertex = toVec3f(vertices[tris_v[i-1]]);
+ v1.normal = normals[tris_n[i-1]];
+ v1.texCoord = getTexCoord(texCoords, tris_tc, tcScale, i-1);
+ SGVertNormTex v2;
+ v2.vertex = toVec3f(vertices[tris_v[i]]);
+ v2.normal = normals[tris_n[i]];
+ v2.texCoord = getTexCoord(texCoords, tris_tc, tcScale, i);
+ triangles.insert(v0, v1, v2);
}
}
- return mat;
-}
-
-\f
-////////////////////////////////////////////////////////////////////////
-// Scenery loaders.
-////////////////////////////////////////////////////////////////////////
-
-// Load an Binary obj file
-static bool SGBinObjLoad( const string& path, const bool is_base,
- Point3D& center,
- SGMaterialLib *matlib,
- bool use_random_objects,
- osg::Group *local_terrain,
- osg::Group *vasi_lights,
- osg::Group *rwy_lights,
- osg::Group *taxi_lights,
- osg::Vec3Array *ground_lights )
-{
- SGBinObject obj;
- if ( ! obj.read_bin( path ) ) {
- return false;
+ static void
+ addStripGeometry(SGTexturedTriangleBin& triangles,
+ const std::vector<SGVec3d>& vertices,
+ const std::vector<SGVec3f>& normals,
+ const std::vector<SGVec2f>& texCoords,
+ const int_list& strips_v,
+ const int_list& strips_n,
+ const int_list& strips_tc,
+ const SGVec2f& tcScale)
+ {
+ if (strips_v.size() != strips_n.size()) {
+ // If the normal indices do not match, they should be inmplicitly
+ // the same than the vertex indices. So just call ourselves again
+ // with the matching index vector.
+ addStripGeometry(triangles, vertices, normals, texCoords,
+ strips_v, strips_v, strips_tc, tcScale);
+ return;
}
- // reference point (center offset/bounding sphere)
- center = obj.get_gbs_center();
-
- point_list const& nodes = obj.get_wgs84_nodes();
- point_list const& normals = obj.get_normals();
- point_list const& texcoords = obj.get_texcoords();
-
- string material;
- int_list tex_index;
+ for (unsigned i = 2; i < strips_v.size(); ++i) {
+ SGVertNormTex v0;
+ v0.vertex = toVec3f(vertices[strips_v[i-2]]);
+ v0.normal = normals[strips_n[i-2]];
+ v0.texCoord = getTexCoord(texCoords, strips_tc, tcScale, i-2);
+ SGVertNormTex v1;
+ v1.vertex = toVec3f(vertices[strips_v[i-1]]);
+ v1.normal = normals[strips_n[i-1]];
+ v1.texCoord = getTexCoord(texCoords, strips_tc, tcScale, i-1);
+ SGVertNormTex v2;
+ v2.vertex = toVec3f(vertices[strips_v[i]]);
+ v2.normal = normals[strips_n[i]];
+ v2.texCoord = getTexCoord(texCoords, strips_tc, tcScale, i);
+ if (i%2)
+ triangles.insert(v1, v0, v2);
+ else
+ triangles.insert(v0, v1, v2);
+ }
+ }
+
+ static void
+ addFanGeometry(SGTexturedTriangleBin& triangles,
+ const std::vector<SGVec3d>& vertices,
+ const std::vector<SGVec3f>& normals,
+ const std::vector<SGVec2f>& texCoords,
+ const int_list& fans_v,
+ const int_list& fans_n,
+ const int_list& fans_tc,
+ const SGVec2f& tcScale)
+ {
+ if (fans_v.size() != fans_n.size()) {
+ // If the normal indices do not match, they should be implicitly
+ // the same than the vertex indices. So just call ourselves again
+ // with the matching index vector.
+ addFanGeometry(triangles, vertices, normals, texCoords,
+ fans_v, fans_v, fans_tc, tcScale);
+ return;
+ }
- group_list::size_type i;
+ SGVertNormTex v0;
+ v0.vertex = toVec3f(vertices[fans_v[0]]);
+ v0.normal = normals[fans_n[0]];
+ v0.texCoord = getTexCoord(texCoords, fans_tc, tcScale, 0);
+ SGVertNormTex v1;
+ v1.vertex = toVec3f(vertices[fans_v[1]]);
+ v1.normal = normals[fans_n[1]];
+ v1.texCoord = getTexCoord(texCoords, fans_tc, tcScale, 1);
+ for (unsigned i = 2; i < fans_v.size(); ++i) {
+ SGVertNormTex v2;
+ v2.vertex = toVec3f(vertices[fans_v[i]]);
+ v2.normal = normals[fans_n[i]];
+ v2.texCoord = getTexCoord(texCoords, fans_tc, tcScale, i);
+ triangles.insert(v0, v1, v2);
+ v1 = v2;
+ }
+ }
- 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();
- group_list const& pts_n = obj.get_pts_n();
- for ( i = 0; i < pts_v.size(); ++i ) {
- // 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());
- // returns a transform -> lod -> leaf structure
- osg::Node *branch = SGMakeDirectionalLights( nodes, normals,
- pts_v[i], pts_n[i],
- matlib,
- pt_materials[i], up );
- if ( pt_materials[i] == "RWY_VASI_LIGHTS" ) {
- vasi_lights->addChild( branch );
- } else if ( pt_materials[i] == "RWY_BLUE_TAXIWAY_LIGHTS"
- || pt_materials[i] == "RWY_GREEN_TAXIWAY_LIGHTS" )
- {
- taxi_lights->addChild( branch );
- } else {
- rwy_lights->addChild( branch );
- }
- } else {
- // other geometry
- SGMaterial *mat = findMaterial( pt_materials[i], path, matlib );
- tex_index.clear();
- osg::Drawable *leaf = SGMakeLeaf( path, GL_POINTS, mat,
- nodes, normals, texcoords,
- pts_v[i], pts_n[i], tex_index,
- false, ground_lights );
-
+ SGVec2f getTexCoordScale(const std::string& name, SGMaterialLib* matlib)
+ {
+ if (!matlib)
+ return SGVec2f(1, 1);
+ SGMaterial* material = matlib->find(name);
+ if (!material)
+ return SGVec2f(1, 1);
+ return material->get_tex_coord_scale();
+ }
- geode->addDrawable( leaf );
- }
+ bool
+ insertSurfaceGeometry(const SGBinObject& obj, SGMaterialLib* matlib)
+ {
+ if (obj.get_tris_n().size() < obj.get_tris_v().size() ||
+ obj.get_tris_tc().size() < obj.get_tris_v().size()) {
+ SG_LOG(SG_TERRAIN, SG_ALERT,
+ "Group list sizes for triangles do not match!");
+ return false;
}
- // 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);
-// }
-
- typedef map<string,list<Leaf> > LeafMap;
- LeafMap leafMap;
- Leaf leaf;
- leaf.type = GL_TRIANGLES;
- string_list const& tri_materials = obj.get_tri_materials();
- group_list const& tris_v = obj.get_tris_v();
- group_list const& tris_n = obj.get_tris_n();
- group_list const& tris_tc = obj.get_tris_tc();
- for ( i = 0; i < tris_v.size(); i++ ) {
- leaf.index = i;
- leafMap[ tri_materials[i] ].push_back( leaf );
+ for (unsigned grp = 0; grp < obj.get_tris_v().size(); ++grp) {
+ std::string materialName = obj.get_tri_materials()[grp];
+ SGVec2f tcScale = getTexCoordScale(materialName, matlib);
+ addTriangleGeometry(materialTriangleMap[materialName],
+ obj.get_wgs84_nodes(), obj.get_normals(),
+ obj.get_texcoords(), obj.get_tris_v()[grp],
+ obj.get_tris_n()[grp], obj.get_tris_tc()[grp],
+ tcScale);
}
- leaf.type = GL_TRIANGLE_STRIP;
- string_list const& strip_materials = obj.get_strip_materials();
- group_list const& strips_v = obj.get_strips_v();
- group_list const& strips_n = obj.get_strips_n();
- group_list const& strips_tc = obj.get_strips_tc();
- for ( i = 0; i < strips_v.size(); i++ ) {
- leaf.index = i;
- leafMap[ strip_materials[i] ].push_back( leaf );
+
+ if (obj.get_strips_n().size() < obj.get_strips_v().size() ||
+ obj.get_strips_tc().size() < obj.get_strips_v().size()) {
+ SG_LOG(SG_TERRAIN, SG_ALERT,
+ "Group list sizes for strips do not match!");
+ return false;
}
- leaf.type = GL_TRIANGLE_FAN;
- string_list const& fan_materials = obj.get_fan_materials();
- group_list const& fans_v = obj.get_fans_v();
- group_list const& fans_n = obj.get_fans_n();
- group_list const& fans_tc = obj.get_fans_tc();
- for ( i = 0; i < fans_v.size(); i++ ) {
- leaf.index = i;
- leafMap[ fan_materials[i] ].push_back( leaf );
+ for (unsigned grp = 0; grp < obj.get_strips_v().size(); ++grp) {
+ std::string materialName = obj.get_strip_materials()[grp];
+ SGVec2f tcScale = getTexCoordScale(materialName, matlib);
+ addStripGeometry(materialTriangleMap[materialName],
+ obj.get_wgs84_nodes(), obj.get_normals(),
+ obj.get_texcoords(), obj.get_strips_v()[grp],
+ obj.get_strips_n()[grp], obj.get_strips_tc()[grp],
+ tcScale);
}
- 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::Drawable *leaf = SGMakeLeaf( path, GL_TRIANGLES, mat,
- nodes, normals, texcoords,
- tris_v[ind], tris_n[ind], tris_tc[ind],
- is_base, ground_lights );
- if ( random_object_branch ) {
- if ( mat ) {
- gen_random_surface_objects( leaf, random_object_branch,
- ¢er, mat );
- }
- }
- geode->addDrawable( leaf );
- } else if ( leaf.type == GL_TRIANGLE_STRIP ) {
- 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 ( random_object_branch ) {
- if ( mat ) {
- gen_random_surface_objects( leaf, random_object_branch,
- ¢er, mat );
- }
- }
- geode->addDrawable( leaf );
- } else {
- 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 ( random_object_branch ) {
- if ( mat ) {
- gen_random_surface_objects( leaf, random_object_branch,
- ¢er, mat );
- }
- }
- geode->addDrawable( leaf );
- }
- ++li;
- }
- ++lmi;
+ if (obj.get_fans_n().size() < obj.get_fans_v().size() ||
+ obj.get_fans_tc().size() < obj.get_fans_v().size()) {
+ SG_LOG(SG_TERRAIN, SG_ALERT,
+ "Group list sizes for fans do not match!");
+ return false;
+ }
+ for (unsigned grp = 0; grp < obj.get_fans_v().size(); ++grp) {
+ std::string materialName = obj.get_fan_materials()[grp];
+ SGVec2f tcScale = getTexCoordScale(materialName, matlib);
+ addFanGeometry(materialTriangleMap[materialName],
+ obj.get_wgs84_nodes(), obj.get_normals(),
+ obj.get_texcoords(), obj.get_fans_v()[grp],
+ obj.get_fans_n()[grp], obj.get_fans_tc()[grp],
+ tcScale);
}
-
return true;
-}
-
+ }
+ osg::Node* getSurfaceGeometry(SGMaterialLib* matlib) const
+ {
+ if (materialTriangleMap.empty())
+ return 0;
+ osg::Geode* geode = new osg::Geode;
+ SGMaterialTriangleMap::const_iterator i;
+ for (i = materialTriangleMap.begin(); i != materialTriangleMap.end(); ++i) {
+#define CHUNCKED
+#ifdef CHUNCKED
+ SGMaterial *mat = matlib->find(i->first);
+
+ std::list<SGTexturedTriangleBin::TriangleVector> connectSets;
+ i->second.getConnectedSets(connectSets);
+
+ std::list<SGTexturedTriangleBin::TriangleVector>::iterator j;
+ for (j = connectSets.begin(); j != connectSets.end(); ++j) {
+ osg::Geometry* geometry = i->second.buildGeometry(*j);
+ if (mat)
+ geometry->setStateSet(mat->get_state());
+ geode->addDrawable(geometry);
+ }
+#else
+ osg::Geometry* geometry = i->second.buildGeometry();
+ SGMaterial *mat = matlib->find(i->first);
+ if (mat)
+ geometry->setStateSet(mat->get_state());
+ geode->addDrawable(geometry);
+#endif
+ }
+ return geode;
+ }
-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.
+ void computeRandomSurfaceLights(SGMaterialLib* matlib)
+ {
+ SGMaterialTriangleMap::const_iterator i;
+ for (i = materialTriangleMap.begin(); i != materialTriangleMap.end(); ++i) {
+ SGMaterial *mat = matlib->find(i->first);
+ if (!mat)
+ continue;
+
+ float coverage = mat->get_light_coverage();
+ if (coverage <= 0)
+ continue;
+ if (coverage < 10000.0) {
+ SG_LOG(SG_INPUT, SG_ALERT, "Light coverage is "
+ << coverage << ", pushing up to 10000");
+ coverage = 10000;
+ }
+
+ // generate a repeatable random seed
+ sg_srandom(unsigned(coverage));
+
+ std::vector<SGVec3f> randomPoints;
+ i->second.addRandomSurfacePoints(coverage, 3, randomPoints);
+ std::vector<SGVec3f>::iterator j;
+ for (j = randomPoints.begin(); j != randomPoints.end(); ++j) {
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 );
+ // factor = sg_random() ^ 2, range = 0 .. 1 concentrated towards 0
+ float factor = sg_random();
+ factor *= factor;
+
+ float bright = 1;
+ SGVec4f color;
+ if ( zombie > 0.5 ) {
+ // 50% chance of yellowish
+ color = SGVec4f(0.9f, 0.9f, 0.3f, bright - factor * 0.2f);
+ } else if (zombie > 0.15f) {
+ // 35% chance of whitish
+ color = SGVec4f(0.9, 0.9f, 0.8f, bright - factor * 0.2f);
+ } else if (zombie > 0.05f) {
+ // 10% chance of orangish
+ color = SGVec4f(0.9f, 0.6f, 0.2f, bright - factor * 0.2f);
+ } else {
+ // 5% chance of redish
+ color = SGVec4f(0.9f, 0.2f, 0.2f, bright - factor * 0.2f);
}
+ randomTileLights.insert(*j, 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());
+ bool insertBinObj(const SGBinObject& obj, SGMaterialLib* matlib)
+ {
+ if (!insertPtGeometry(obj, matlib))
+ return false;
+ if (!insertSurfaceGeometry(obj, matlib))
+ return false;
+ return true;
+ }
+};
- return geode;
-}
class SGTileUpdateCallback : public osg::NodeCallback {
public:
}
};
-
osg::Node*
SGLoadBTG(const std::string& path, SGMaterialLib *matlib, bool calc_lights, bool use_random_objects)
{
+ SGBinObject obj;
+ if (!obj.read_bin(path))
+ return false;
+
+ SGTileGeometryBin tileGeometryBin;
+ if (!tileGeometryBin.insertBinObj(obj, matlib))
+ return false;
+
+ SGVec3d center = obj.get_gbs_center2();
+ SGGeod geodPos = SGGeod::fromCart(center);
+ SGQuatd hlOr = SGQuatd::fromLonLat(geodPos);
+ SGVec3f up = toVec3f(hlOr.backTransform(SGVec3d(0, 0, -1)));
+
osg::Group* vasiLights = new osg::Group;
+ vasiLights->setCullCallback(new SGPointSpriteLightCullCallback(osg::Vec3(1, 0.0001, 0.000001), 6));
osg::StateSet* stateSet = vasiLights->getOrCreateStateSet();
osg::Fog* fog = new osg::Fog;
fog->setUpdateCallback(new SGRunwayLightFogUpdateCallback);
stateSet->setAttribute(fog);
osg::Group* rwyLights = new osg::Group;
+ rwyLights->setCullCallback(new SGPointSpriteLightCullCallback);
stateSet = rwyLights->getOrCreateStateSet();
fog = new osg::Fog;
fog->setUpdateCallback(new SGRunwayLightFogUpdateCallback);
stateSet->setAttribute(fog);
osg::Group* taxiLights = new osg::Group;
+ taxiLights->setCullCallback(new SGPointSpriteLightCullCallback);
stateSet = taxiLights->getOrCreateStateSet();
fog = new osg::Fog;
fog->setUpdateCallback(new SGTaxiLightFogUpdateCallback);
lightSwitch->addChild(groundLights1, true);
lightSwitch->addChild(groundLights2, true);
- osg::Group* lightGroup = new SGLightOffsetTransform;
+ osg::Group* lightGroup = new SGOffsetTransform(0.94);
lightGroup->addChild(lightSwitch);
+
+ osg::LOD* lightLOD = new osg::LOD;
+ lightLOD->addChild(lightGroup, 0, 30000);
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);
-
+ lightLOD->setNodeMask(nodeMask);
+
osg::Group* terrainGroup = new osg::Group;
+ osg::Node* node = tileGeometryBin.getSurfaceGeometry(matlib);
+ if (node)
+ terrainGroup->addChild(node);
- 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 (calc_lights) {
+ // FIXME: ugly, has a side effect
+ tileGeometryBin.computeRandomSurfaceLights(matlib);
- 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 );
+ osg::Geode* geode = new osg::Geode;
+ groundLights0->addChild(geode);
+ geode->addDrawable(SGLightFactory::getLights(tileGeometryBin.tileLights));
+
+ groundLights0->addChild(geode);
+ geode->addDrawable(SGLightFactory::getLights(tileGeometryBin.randomTileLights, 4, -0.3f));
+
+ geode = new osg::Geode;
+ groundLights1->addChild(geode);
+ geode->addDrawable(SGLightFactory::getLights(tileGeometryBin.randomTileLights, 2, -0.15f));
+
+ geode = new osg::Geode;
+ groundLights2->addChild(geode);
+ geode->addDrawable(SGLightFactory::getLights(tileGeometryBin.randomTileLights));
+ }
+
+ {
+ SGVec4f red(1, 0, 0, 1);
+ SGMaterial* mat = matlib->find("RWY_RED_LIGHTS");
+ if (mat)
+ red = mat->get_light_color();
+ SGVec4f white(1, 1, 1, 1);
+ mat = matlib->find("RWY_WHITE_LIGHTS");
+ if (mat)
+ white = mat->get_light_color();
+ osg::Geode* geode;
+ geode = new osg::Geode;
+ vasiLights->addChild(geode);
+ SGDirectionalLightListBin::const_iterator i;
+ for (i = tileGeometryBin.vasiLights.begin();
+ i != tileGeometryBin.vasiLights.end(); ++i) {
+ geode->addDrawable(SGLightFactory::getVasi(up, *i, red, white));
+ }
- lights = gen_lights( matlib, light_pts.get(), 1, 1.0 );
- groundLights2->addChild( lights );
+ geode = new osg::Geode;
+ rwyLights->addChild(geode);
+ geode->addDrawable(SGLightFactory::getLights(tileGeometryBin.runwayLights));
+ for (i = tileGeometryBin.rabitLights.begin();
+ i != tileGeometryBin.rabitLights.end(); ++i) {
+ rwyLights->addChild(SGLightFactory::getSequenced(*i));
+ }
+ for (i = tileGeometryBin.reilLights.begin();
+ i != tileGeometryBin.reilLights.end(); ++i) {
+ rwyLights->addChild(SGLightFactory::getSequenced(*i));
+ }
+
+ SGLightListBin::const_iterator j;
+ for (j = tileGeometryBin.odalLights.begin();
+ j != tileGeometryBin.odalLights.end(); ++j) {
+ rwyLights->addChild(SGLightFactory::getOdal(*j));
+ }
+
+ geode = new osg::Geode;
+ taxiLights->addChild(geode);
+ geode->addDrawable(SGLightFactory::getLights(tileGeometryBin.taxiLights));
}
// 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->setMatrix(osg::Matrix::translate(center.osg()));
transform->addChild(terrainGroup);
- transform->addChild(lightGroup);
+ transform->addChild(lightLOD);
return transform;
}
#ifndef _SG_OBJ_HXX
#define _SG_OBJ_HXX
-
#ifndef __cplusplus
# error This library requires C++
#endif
-
#include <simgear/compiler.h>
#include STL_STRING
-#include <osg/Array>
+#include <osg/Node>
#include <osg/Group>
-#include <simgear/math/point3d.hxx>
+#include "SGOceanTile.hxx"
SG_USING_STD(string);
class SGMaterialLib;
// Generate an ocean tile
-bool SGGenTile( const string& path, const SGBucket& b,
- SGMaterialLib *matlib, osg::Group *geometry );
+inline bool SGGenTile( const std::string&, const SGBucket& b,
+ SGMaterialLib *matlib, osg::Group* group )
+{
+ // Generate an ocean tile
+ osg::Node* node = SGOceanTile(b, matlib);
+ if (!node)
+ return false;
+ group->addChild(node);
+ return true;
+}
osg::Node*
SGLoadBTG(const std::string& path, SGMaterialLib *matlib, bool calc_lights, bool use_random_objects);
-
#endif // _SG_OBJ_HXX
# include <simgear_config.h>
#endif
+#include "pt_lights.hxx"
+
#include <osg/Array>
#include <osg/Geometry>
+#include <osg/CullFace>
#include <osg/Geode>
-#include <osg/LOD>
#include <osg/MatrixTransform>
#include <osg/NodeCallback>
#include <osg/NodeVisitor>
-#include <osg/Switch>
+#include <osg/Texture2D>
+#include <osg/AlphaFunc>
+#include <osg/BlendFunc>
+#include <osg/TexEnv>
+#include <osg/Sequence>
+#include <osg/PolygonMode>
+#include <osg/Fog>
+#include <osg/FragmentProgram>
+#include <osg/VertexProgram>
+#include <osg/Point>
+#include <osg/PointSprite>
+#include <osg/Material>
+#include <osg/Group>
+#include <osg/StateSet>
+
+#include <osgUtil/CullVisitor>
-#include <simgear/scene/material/mat.hxx>
-#include <simgear/screen/extensions.hxx>
#include <simgear/math/sg_random.h>
+#include <simgear/debug/logstream.hxx>
+#include <simgear/threads/SGThread.hxx>
+#include <simgear/threads/SGGuard.hxx>
+#include <simgear/scene/util/SGEnlargeBoundingBox.hxx>
-#include "vasi.hxx"
-
-#include "pt_lights.hxx"
-
-// static variables for use in ssg callbacks
-bool SGPointLightsUseSprites = false;
-bool SGPointLightsEnhancedLighting = false;
-bool SGPointLightsDistanceAttenuation = false;
-
-
-// Specify the way we want to draw directional point lights (assuming the
-// appropriate extensions are available.)
+#include "SGVasiDrawable.hxx"
-void SGConfigureDirectionalLights( bool use_point_sprites,
- bool enhanced_lighting,
- bool distance_attenuation ) {
- SGPointLightsUseSprites = use_point_sprites;
- SGPointLightsEnhancedLighting = enhanced_lighting;
- SGPointLightsDistanceAttenuation = distance_attenuation;
-}
-
-static void calc_center_point( const point_list &nodes,
- const int_list &pnt_i,
- Point3D& result ) {
- double minx = nodes[pnt_i[0]][0];
- double maxx = nodes[pnt_i[0]][0];
- double miny = nodes[pnt_i[0]][1];
- double maxy = nodes[pnt_i[0]][1];
- double minz = nodes[pnt_i[0]][2];
- double maxz = nodes[pnt_i[0]][2];
-
- for ( unsigned int i = 0; i < pnt_i.size(); ++i ) {
- Point3D pt = nodes[pnt_i[i]];
- 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]; }
+static void
+setPointSpriteImage(unsigned char* data, unsigned log2resolution,
+ unsigned charsPerPixel)
+{
+ int env_tex_res = (1 << log2resolution);
+ for (int i = 0; i < env_tex_res; ++i) {
+ for (int j = 0; j < env_tex_res; ++j) {
+ int xi = 2*i + 1 - env_tex_res;
+ int yi = 2*j + 1 - env_tex_res;
+ if (xi < 0)
+ xi = -xi;
+ if (yi < 0)
+ yi = -yi;
+
+ xi -= 1;
+ yi -= 1;
+
+ if (xi < 0)
+ xi = 0;
+ if (yi < 0)
+ yi = 0;
+
+ float x = 1.5*xi/(float)(env_tex_res);
+ float y = 1.5*yi/(float)(env_tex_res);
+ // float x = 2*xi/(float)(env_tex_res);
+ // float y = 2*yi/(float)(env_tex_res);
+ float dist = sqrt(x*x + y*y);
+ float bright = SGMiscf::clip(255*(1-dist), 0, 255);
+ for (unsigned l = 0; l < charsPerPixel; ++l)
+ data[charsPerPixel*(i*env_tex_res + j) + l] = (unsigned char)bright;
}
-
- result = Point3D((minx + maxx) / 2.0, (miny + maxy) / 2.0,
- (minz + maxz) / 2.0);
+ }
}
-
-static osg::Node*
-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,
- const osg::Vec3& up, bool vertical, bool vasi )
+static osg::Image*
+getPointSpriteImage(int logResolution)
{
- Point3D center;
- calc_center_point( nodes, pnt_i, center );
- // cout << center[0] << "," << center[1] << "," << center[2] << endl;
-
-
- // find a vector perpendicular to the normal.
- osg::Vec3 perp1;
- if ( !vertical ) {
- // normal isn't vertical so we can use up as our first vector
- perp1 = up;
- } else {
- // normal is vertical so we have to work a bit harder to
- // determine our first vector
- osg::Vec3 pt1(nodes[pnt_i[0]][0], nodes[pnt_i[0]][1],
- nodes[pnt_i[0]][2] );
- osg::Vec3 pt2(nodes[pnt_i[1]][0], nodes[pnt_i[1]][1],
- nodes[pnt_i[1]][2] );
-
- perp1 = pt2 - pt1;
- }
- perp1.normalize();
-
- osg::Vec3Array *vl = new osg::Vec3Array;
- osg::Vec3Array *nl = new osg::Vec3Array;
- osg::Vec4Array *cl = new osg::Vec4Array;
-
- unsigned int i;
- for ( i = 0; i < pnt_i.size(); ++i ) {
- Point3D ppt = nodes[pnt_i[i]] - center;
- osg::Vec3 pt(ppt[0], ppt[1], ppt[2]);
- osg::Vec3 normal(normals[nml_i[i]][0], normals[nml_i[i]][1],
- normals[nml_i[i]][2] );
-
- // calculate a vector perpendicular to dir and up
- osg::Vec3 perp2 = normal^perp1;
-
- // front face
- osg::Vec3 tmp3 = pt;
- vl->push_back( tmp3 );
- tmp3 += perp1;
- vl->push_back( tmp3 );
- tmp3 += perp2;
- vl->push_back( tmp3 );
-
- nl->push_back( normal );
- nl->push_back( normal );
- nl->push_back( normal );
-
- cl->push_back(osg::Vec4(1, 1, 1, 1));
- cl->push_back(osg::Vec4(1, 1, 1, 0));
- cl->push_back(osg::Vec4(1, 1, 1, 0));
- }
-
- osg::Geometry* geometry = new osg::Geometry;
- geometry->setName("Dir Lights " + mat->get_names().front());
- geometry->setVertexArray(vl);
- geometry->setNormalArray(nl);
- geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
- geometry->setColorArray(cl);
- geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
- geometry->addPrimitiveSet(new osg::DrawArrays(GL_TRIANGLES, 0, vl->size()));
- osg::Geode* geode = new osg::Geode;
- geode->addDrawable(geometry);
-
- if (vasi) {
- // this one is dynamic in its colors, so do not bother with dlists
- geometry->setUseDisplayList(false);
- geometry->setUseVertexBufferObjects(false);
- osg::Vec3 dir(normals[nml_i[0]][0], normals[nml_i[0]][1],
- normals[nml_i[0]][2]);
-
- // calculate the reference position of this vasi and use it
- // to init the vasi structure
- Point3D ppt = nodes[pnt_i[0]] - center;
- osg::Vec3 pt(ppt[0], ppt[1], ppt[2]);
- // up is the "up" vector which is also
- // the reference center point of this tile. The reference
- // center + the coordinate of the first light gives the actual
- // location of the first light.
- pt += up;
-
- // Set up the callback
- geode->setCullCallback(new SGVasiUpdateCallback(cl, pt, up, dir));
- }
-
- if ( mat != NULL ) {
- geode->setStateSet(mat->get_state());
- } else {
- SG_LOG( SG_TERRAIN, SG_ALERT, "Warning: material = NULL" );
- }
-
- // put an LOD on each lighting component
- osg::LOD *lod = new osg::LOD;
- lod->addChild( geode, 0, 20000 );
-
- // create the transformation.
- osg::MatrixTransform *trans = new osg::MatrixTransform;
- trans->setMatrix(osg::Matrixd::translate(osg::Vec3d(center[0], center[1], center[2])));
- trans->addChild( lod );
+ osg::Image* image = new osg::Image;
+
+ osg::Image::MipmapDataType mipmapOffsets;
+ unsigned off = 0;
+ for (int i = logResolution; 0 <= i; --i) {
+ unsigned res = 1 << i;
+ off += res*res;
+ mipmapOffsets.push_back(off);
+ }
+
+ int env_tex_res = (1 << logResolution);
+
+ unsigned char* imageData = new unsigned char[off];
+ image->setImage(env_tex_res, env_tex_res, 1,
+ GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, imageData,
+ osg::Image::USE_NEW_DELETE);
+ image->setMipmapLevels(mipmapOffsets);
+
+ for (int k = logResolution; 0 <= k; --k) {
+ setPointSpriteImage(image->getMipmapData(logResolution - k), k, 1);
+ }
+
+ return image;
+}
- return trans;
+static osg::Texture2D*
+gen_standard_light_sprite(void)
+{
+ // double checked locking ...
+ static osg::ref_ptr<osg::Texture2D> texture;
+ if (texture.valid())
+ return texture.get();
+
+ static SGMutex mutex;
+ SGGuard<SGMutex> guard(mutex);
+ if (texture.valid())
+ return texture.get();
+
+ texture = new osg::Texture2D;
+ texture->setImage(getPointSpriteImage(6));
+ texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP);
+ texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP);
+
+ return texture.get();
}
-static osg::Node *gen_reil_lights( const point_list &nodes,
- const point_list &normals,
- const int_list &pnt_i,
- const int_list &nml_i,
- SGMaterialLib *matlib,
- const osg::Vec3& up )
+SGPointSpriteLightCullCallback::SGPointSpriteLightCullCallback(const osg::Vec3& da,
+ float sz) :
+ _pointSpriteStateSet(new osg::StateSet),
+ _distanceAttenuationStateSet(new osg::StateSet)
{
- Point3D center;
- calc_center_point( nodes, pnt_i, center );
- // cout << center[0] << "," << center[1] << "," << center[2] << endl;
-
- osg::Vec3 nup = up;
- nup.normalize();
-
- osg::Vec3Array *vl = new osg::Vec3Array;
- osg::Vec3Array *nl = new osg::Vec3Array;
- osg::Vec4Array *cl = new osg::Vec4Array;
-
- unsigned int i;
- for ( i = 0; i < pnt_i.size(); ++i ) {
- Point3D ppt = nodes[pnt_i[i]] - center;
- osg::Vec3 pt(ppt[0], ppt[1], ppt[2]);
- osg::Vec3 normal(normals[nml_i[i]][0], normals[nml_i[i]][1],
- normals[nml_i[i]][2] );
-
- // calculate a vector perpendicular to dir and up
- osg::Vec3 perp = normal^up;
-
- // front face
- osg::Vec3 tmp3 = pt;
- vl->push_back( tmp3 );
- tmp3 += nup;
- vl->push_back( tmp3 );
- tmp3 += perp;
- vl->push_back( tmp3 );
-
- nl->push_back( normal );
- nl->push_back( normal );
- nl->push_back( normal );
-
- cl->push_back(osg::Vec4(1, 1, 1, 1));
- cl->push_back(osg::Vec4(1, 1, 1, 0));
- cl->push_back(osg::Vec4(1, 1, 1, 0));
- }
+ osg::PointSprite* pointSprite = new osg::PointSprite;
+ _pointSpriteStateSet->setTextureAttributeAndModes(0, pointSprite,
+ osg::StateAttribute::ON);
+ osg::Texture2D* texture = gen_standard_light_sprite();
+ _pointSpriteStateSet->setTextureAttribute(0, texture);
+ _pointSpriteStateSet->setTextureMode(0, GL_TEXTURE_2D,
+ osg::StateAttribute::ON);
+ osg::TexEnv* texEnv = new osg::TexEnv;
+ texEnv->setMode(osg::TexEnv::MODULATE);
+ _pointSpriteStateSet->setTextureAttribute(0, texEnv);
+
+ osg::Point* point = new osg::Point;
+ point->setFadeThresholdSize(1);
+ point->setMinSize(1);
+ point->setMaxSize(sz);
+ point->setSize(sz);
+ point->setDistanceAttenuation(da);
+ _distanceAttenuationStateSet->setAttributeAndModes(point);
+}
- SGMaterial *mat = matlib->find( "RWY_WHITE_LIGHTS" );
-
- osg::Geometry* geometry = new osg::Geometry;
- geometry->setName("Reil Lights " + mat->get_names().front());
- geometry->setVertexArray(vl);
- geometry->setNormalArray(nl);
- geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
- geometry->setColorArray(cl);
- geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
- geometry->addPrimitiveSet(new osg::DrawArrays(GL_TRIANGLES, 0, vl->size()));
- osg::Geode* geode = new osg::Geode;
- geode->addDrawable(geometry);
-
- if ( mat != NULL ) {
- geode->setStateSet( mat->get_state() );
- } else {
- SG_LOG( SG_TERRAIN, SG_ALERT,
- "Warning: can't find material = RWY_WHITE_LIGHTS" );
- }
+// FIXME make state sets static
+SGPointSpriteLightCullCallback::SGPointSpriteLightCullCallback(osg::Point* point) :
+ _pointSpriteStateSet(new osg::StateSet),
+ _distanceAttenuationStateSet(new osg::StateSet)
+{
+ osg::PointSprite* pointSprite = new osg::PointSprite;
+ _pointSpriteStateSet->setTextureAttributeAndModes(0, pointSprite,
+ osg::StateAttribute::ON);
+ osg::Texture2D* texture = gen_standard_light_sprite();
+ _pointSpriteStateSet->setTextureAttribute(0, texture);
+ _pointSpriteStateSet->setTextureMode(0, GL_TEXTURE_2D,
+ osg::StateAttribute::ON);
+ osg::TexEnv* texEnv = new osg::TexEnv;
+ texEnv->setMode(osg::TexEnv::MODULATE);
+ _pointSpriteStateSet->setTextureAttribute(0, texEnv);
+
+ _distanceAttenuationStateSet->setAttributeAndModes(point);
+}
- // OSGFIXME
-// leaf->setCallback( SSG_CALLBACK_PREDRAW, StrobePreDraw );
-// leaf->setCallback( SSG_CALLBACK_POSTDRAW, StrobePostDraw );
-
- // OSGFIXME: implement an update callback that switches on/off
- // based on the osg::FrameStamp
- osg::Switch *reil = new osg::Switch;
-// reil->setDuration( 60 );
-// reil->setLimits( 0, 2 );
-// reil->setMode( SSG_ANIM_SHUTTLE );
-// reil->control( SSG_ANIM_START );
-
- // need to add this twice to work around an ssg bug
- reil->addChild(geode, true);
-
- // put an LOD on each lighting component
- osg::LOD *lod = new osg::LOD;
- lod->addChild( reil, 0, 12000 /*OSGFIXME: hardcoded here?*/);
-
- // create the transformation.
- osg::MatrixTransform *trans = new osg::MatrixTransform;
- trans->setMatrix(osg::Matrixd::translate(osg::Vec3d(center[0], center[1], center[2])));
- trans->addChild( lod );
-
- return trans;
+void
+SGPointSpriteLightCullCallback::operator()(osg::Node* node,
+ osg::NodeVisitor* nv)
+{
+ assert(dynamic_cast<osgUtil::CullVisitor*>(nv));
+ osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>(nv);
+
+ // Test for point sprites and point parameters availibility
+ unsigned contextId = cv->getRenderInfo().getContextID();
+ SGSceneFeatures* features = SGSceneFeatures::instance();
+ bool usePointSprite = features->getEnablePointSpriteLights(contextId);
+ bool usePointParameters = features->getEnableDistanceAttenuationLights(contextId);
+
+ if (usePointSprite)
+ cv->pushStateSet(_pointSpriteStateSet.get());
+
+ if (usePointParameters)
+ cv->pushStateSet(_distanceAttenuationStateSet.get());
+
+ traverse(node, nv);
+
+ if (usePointParameters)
+ cv->popStateSet();
+
+ if (usePointSprite)
+ cv->popStateSet();
}
+osg::Node*
+SGLightFactory::getLight(const SGLightBin::Light& light)
+{
+ osg::Vec3Array* vertices = new osg::Vec3Array;
+ osg::Vec4Array* colors = new osg::Vec4Array;
+
+ vertices->push_back(light.position.osg());
+ colors->push_back(light.color.osg());
+
+ osg::Geometry* geometry = new osg::Geometry;
+ geometry->setVertexArray(vertices);
+ geometry->setNormalBinding(osg::Geometry::BIND_OFF);
+ geometry->setColorArray(colors);
+ geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
+
+ // Enlarge the bounding box to avoid such light nodes being victim to
+ // small feature culling.
+ geometry->setComputeBoundingBoxCallback(new SGEnlargeBoundingBox(1));
+
+ osg::DrawArrays* drawArrays;
+ drawArrays = new osg::DrawArrays(osg::PrimitiveSet::POINTS,
+ 0, vertices->size());
+ geometry->addPrimitiveSet(drawArrays);
+
+ osg::StateSet* stateSet = geometry->getOrCreateStateSet();
+ stateSet->setRenderBinDetails(9, "DepthSortedBin");
+ stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
+
+ osg::BlendFunc* blendFunc = new osg::BlendFunc;
+ stateSet->setAttribute(blendFunc);
+ stateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
+
+ osg::AlphaFunc* alphaFunc;
+ alphaFunc = new osg::AlphaFunc(osg::AlphaFunc::GREATER, 0.01);
+ stateSet->setAttribute(alphaFunc);
+ stateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::ON);
+
+ osg::Geode* geode = new osg::Geode;
+ geode->addDrawable(geometry);
+
+ return geode;
+}
-static osg::Node *gen_odals_lights( const point_list &nodes,
- const point_list &normals,
- const int_list &pnt_i,
- const int_list &nml_i,
- SGMaterialLib *matlib,
- const osg::Vec3& up )
+osg::Node*
+SGLightFactory::getLight(const SGDirectionalLightBin::Light& light)
{
- Point3D center;
- calc_center_point( nodes, pnt_i, center );
- // cout << center[0] << "," << center[1] << "," << center[2] << endl;
-
- // OSGFIXME: implement like above
-// osg::Switch *odals = new osg::Switch;
- osg::Group *odals = new osg::Group;
-
- // 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" );
- }
+ osg::Vec3Array* vertices = new osg::Vec3Array;
+ osg::Vec4Array* colors = new osg::Vec4Array;
+
+ SGVec4f visibleColor(light.color);
+ SGVec4f invisibleColor(visibleColor[0], visibleColor[1],
+ visibleColor[2], 0);
+ SGVec3f normal = normalize(light.normal);
+ SGVec3f perp1 = perpendicular(normal);
+ SGVec3f perp2 = cross(normal, perp1);
+ SGVec3f position = light.position;
+ vertices->push_back(position.osg());
+ vertices->push_back((position + perp1).osg());
+ vertices->push_back((position + perp2).osg());
+ colors->push_back(visibleColor.osg());
+ colors->push_back(invisibleColor.osg());
+ colors->push_back(invisibleColor.osg());
+
+ osg::Geometry* geometry = new osg::Geometry;
+ geometry->setVertexArray(vertices);
+ geometry->setNormalBinding(osg::Geometry::BIND_OFF);
+ geometry->setColorArray(colors);
+ geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
+ // Enlarge the bounding box to avoid such light nodes being victim to
+ // small feature culling.
+ geometry->setComputeBoundingBoxCallback(new SGEnlargeBoundingBox(1));
+
+ osg::DrawArrays* drawArrays;
+ drawArrays = new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES,
+ 0, vertices->size());
+ geometry->addPrimitiveSet(drawArrays);
+
+ osg::StateSet* stateSet = geometry->getOrCreateStateSet();
+ stateSet->setRenderBinDetails(9, "DepthSortedBin");
+
+ osg::Material* material = new osg::Material;
+ material->setColorMode(osg::Material::OFF);
+ stateSet->setAttribute(material);
+
+ osg::CullFace* cullFace = new osg::CullFace;
+ cullFace->setMode(osg::CullFace::BACK);
+ stateSet->setAttribute(cullFace, osg::StateAttribute::ON);
+ stateSet->setMode(GL_CULL_FACE, osg::StateAttribute::ON);
+
+ osg::PolygonMode* polygonMode = new osg::PolygonMode;
+ polygonMode->setMode(osg::PolygonMode::FRONT, osg::PolygonMode::POINT);
+ stateSet->setAttribute(polygonMode);
+
+ stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
+
+ osg::BlendFunc* blendFunc = new osg::BlendFunc;
+ stateSet->setAttribute(blendFunc);
+ stateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
+
+ osg::AlphaFunc* alphaFunc;
+ alphaFunc = new osg::AlphaFunc(osg::AlphaFunc::GREATER, 0.01);
+ stateSet->setAttribute(alphaFunc);
+ stateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::ON);
+
+ osg::Geode* geode = new osg::Geode;
+ geode->addDrawable(geometry);
+
+ return geode;
+}
- osg::Vec3Array *vl = new osg::Vec3Array;
- osg::Vec4Array *cl = new osg::Vec4Array;
-
- cl->push_back(osg::Vec4(1, 1, 1, 1));
+osg::Drawable*
+SGLightFactory::getLights(const SGLightBin& lights, unsigned inc, float alphaOff)
+{
+ if (lights.getNumLights() <= 0)
+ return 0;
+
+ osg::Vec3Array* vertices = new osg::Vec3Array;
+ osg::Vec4Array* colors = new osg::Vec4Array;
+
+ for (unsigned i = 0; i < lights.getNumLights(); i += inc) {
+ vertices->push_back(lights.getLight(i).position.osg());
+ SGVec4f color = lights.getLight(i).color;
+ color[3] = SGMiscf::max(0, SGMiscf::min(1, color[3] + alphaOff));
+ colors->push_back(color.osg());
+ }
+
+ osg::Geometry* geometry = new osg::Geometry;
+
+ geometry->setVertexArray(vertices);
+ geometry->setNormalBinding(osg::Geometry::BIND_OFF);
+ geometry->setColorArray(colors);
+ geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
+
+ osg::DrawArrays* drawArrays;
+ drawArrays = new osg::DrawArrays(osg::PrimitiveSet::POINTS,
+ 0, vertices->size());
+ geometry->addPrimitiveSet(drawArrays);
+
+ osg::StateSet* stateSet = geometry->getOrCreateStateSet();
+ stateSet->setRenderBinDetails(9, "DepthSortedBin");
+
+ stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
+
+ osg::BlendFunc* blendFunc = new osg::BlendFunc;
+ stateSet->setAttribute(blendFunc);
+ stateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
+
+ osg::AlphaFunc* alphaFunc;
+ alphaFunc = new osg::AlphaFunc(osg::AlphaFunc::GREATER, 0.01);
+ stateSet->setAttribute(alphaFunc);
+ stateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::ON);
+
+ return geometry;
+}
- // center line strobes
- for ( unsigned i = pnt_i.size() - 1; i >= 2; --i ) {
- Point3D ppt = nodes[pnt_i[i]] - center;
- osg::Vec3 pt(ppt[0], ppt[1], ppt[2]);
- vl->push_back(pt);
- }
- // runway end strobes
-
- Point3D ppt = nodes[pnt_i[0]] - center;
- osg::Vec3 pt(ppt[0], ppt[1], ppt[2]);
- vl->push_back(pt);
-
- ppt = nodes[pnt_i[1]] - center;
- pt = osg::Vec3(ppt[0], ppt[1], ppt[2]);
- vl->push_back(pt);
-
- osg::Geometry* geometry = new osg::Geometry;
- geometry->setName("Odal Lights " + mat->get_names().front());
- geometry->setVertexArray(vl);
- geometry->setColorArray(cl);
- geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
- geometry->addPrimitiveSet(new osg::DrawArrays(GL_POINTS, 0, vl->size()));
- osg::Geode* geode = new osg::Geode;
- geode->addDrawable(geometry);
-
- geode->setStateSet( mat->get_state() );
- // OSGFIXME
-// leaf->setCallback( SSG_CALLBACK_PREDRAW, StrobePreDraw );
-// leaf->setCallback( SSG_CALLBACK_POSTDRAW, StrobePostDraw );
-
- odals->addChild( geode );
-
- // 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
- osg::LOD *lod = new osg::LOD;
- lod->addChild( odals, 0, 12000 /*OSGFIXME hardcoded visibility*/ );
-
- // create the transformation.
- osg::MatrixTransform *trans = new osg::MatrixTransform;
- trans->setMatrix(osg::Matrixd::translate(osg::Vec3d(center[0], center[1], center[2])));
- trans->addChild(lod);
-
- return trans;
+osg::Drawable*
+SGLightFactory::getLights(const SGDirectionalLightBin& lights)
+{
+ if (lights.getNumLights() <= 0)
+ return 0;
+
+ osg::Vec3Array* vertices = new osg::Vec3Array;
+ osg::Vec4Array* colors = new osg::Vec4Array;
+
+ for (unsigned i = 0; i < lights.getNumLights(); ++i) {
+ SGVec4f visibleColor(lights.getLight(i).color);
+ SGVec4f invisibleColor(visibleColor[0], visibleColor[1],
+ visibleColor[2], 0);
+ SGVec3f normal = normalize(lights.getLight(i).normal);
+ SGVec3f perp1 = perpendicular(normal);
+ SGVec3f perp2 = cross(normal, perp1);
+ SGVec3f position = lights.getLight(i).position;
+ vertices->push_back(position.osg());
+ vertices->push_back((position + perp1).osg());
+ vertices->push_back((position + perp2).osg());
+ colors->push_back(visibleColor.osg());
+ colors->push_back(invisibleColor.osg());
+ colors->push_back(invisibleColor.osg());
+ }
+
+ osg::Geometry* geometry = new osg::Geometry;
+
+ geometry->setVertexArray(vertices);
+ geometry->setNormalBinding(osg::Geometry::BIND_OFF);
+ geometry->setColorArray(colors);
+ geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
+
+ osg::DrawArrays* drawArrays;
+ drawArrays = new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES,
+ 0, vertices->size());
+ geometry->addPrimitiveSet(drawArrays);
+
+ osg::StateSet* stateSet = geometry->getOrCreateStateSet();
+ stateSet->setRenderBinDetails(9, "DepthSortedBin");
+
+ osg::Material* material = new osg::Material;
+ material->setColorMode(osg::Material::OFF);
+ stateSet->setAttribute(material);
+
+ osg::CullFace* cullFace = new osg::CullFace;
+ cullFace->setMode(osg::CullFace::BACK);
+ stateSet->setAttribute(cullFace, osg::StateAttribute::ON);
+ stateSet->setMode(GL_CULL_FACE, osg::StateAttribute::ON);
+
+ osg::PolygonMode* polygonMode = new osg::PolygonMode;
+ polygonMode->setMode(osg::PolygonMode::FRONT, osg::PolygonMode::POINT);
+ stateSet->setAttribute(polygonMode);
+
+ stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
+
+ osg::BlendFunc* blendFunc = new osg::BlendFunc;
+ stateSet->setAttribute(blendFunc);
+ stateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
+
+ osg::AlphaFunc* alphaFunc;
+ alphaFunc = new osg::AlphaFunc(osg::AlphaFunc::GREATER, 0.01);
+ stateSet->setAttribute(alphaFunc);
+ stateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::ON);
+
+ return geometry;
}
-class SGRabbitUpdateCallback : public osg::NodeCallback {
-public:
- SGRabbitUpdateCallback(double duration) :
- mBaseTime(sg_random()), mDuration(duration)
- {
- if (fabs(mDuration) < 1e-3)
- mDuration = 1e-3;
- mBaseTime -= mDuration*floor(mBaseTime/mDuration);
+static SGVasiDrawable*
+buildVasi(const SGDirectionalLightBin& lights, const SGVec3f& up,
+ const SGVec4f& red, const SGVec4f& white)
+{
+ unsigned count = lights.getNumLights();
+ if ( count == 4 ) {
+ SGVasiDrawable* drawable = new SGVasiDrawable(red, white);
+
+ // PAPI configuration
+ // papi D
+ drawable->addLight(lights.getLight(0).position,
+ lights.getLight(0).normal, up, 3.5);
+ // papi C
+ drawable->addLight(lights.getLight(1).position,
+ lights.getLight(1).normal, up, 3.167);
+ // papi B
+ drawable->addLight(lights.getLight(2).position,
+ lights.getLight(2).normal, up, 2.833);
+ // papi A
+ drawable->addLight(lights.getLight(3).position,
+ lights.getLight(3).normal, up, 2.5);
+ return drawable;
}
-
- virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
- {
- assert(dynamic_cast<osg::Switch*>(node));
- osg::Switch* sw = static_cast<osg::Switch*>(node);
- double frameTime = nv->getFrameStamp()->getReferenceTime();
- double timeDiff = (frameTime - mBaseTime)/mDuration;
- double reminder = timeDiff - unsigned(floor(timeDiff));
- unsigned nChildren = sw->getNumChildren();
- unsigned activeChild = unsigned(nChildren*reminder);
- if (nChildren <= activeChild)
- activeChild = nChildren;
- sw->setSingleChildOn(activeChild);
-
- osg::NodeCallback::operator()(node, nv);
+ else if (count == 12) {
+ SGVasiDrawable* drawable = new SGVasiDrawable(red, white);
+
+ // probably vasi, first 6 are downwind bar (2.5 deg)
+ for (unsigned i = 0; i < 6; ++i)
+ drawable->addLight(lights.getLight(i).position,
+ lights.getLight(i).normal, up, 2.5);
+ // last 6 are upwind bar (3.0 deg)
+ for (unsigned i = 6; i < 12; ++i)
+ drawable->addLight(lights.getLight(i).position,
+ lights.getLight(i).normal, up, 3.0);
+
+ return drawable;
+ } else {
+ // fail safe
+ SG_LOG(SG_TERRAIN, SG_ALERT,
+ "unknown vasi/papi configuration, count = " << count);
+ return 0;
}
-public:
- double mBaseTime;
- double mDuration;
-};
-
-
-static osg::Node *gen_rabbit_lights( const point_list &nodes,
- const point_list &normals,
- const int_list &pnt_i,
- const int_list &nml_i,
- SGMaterialLib *matlib,
- const osg::Vec3& up )
-{
- Point3D center;
- calc_center_point( nodes, pnt_i, center );
- // cout << center[0] << "," << center[1] << "," << center[2] << endl;
-
- osg::Vec3 nup = up;
- nup.normalize();
-
- // OSGFIXME: implement like above ...
- osg::Switch *rabbit = new osg::Switch;
- rabbit->setUpdateCallback(new SGRabbitUpdateCallback(10));
-
- SGMaterial *mat = matlib->find( "RWY_WHITE_LIGHTS" );
- if ( mat == NULL ) {
- SG_LOG( SG_TERRAIN, SG_ALERT,
- "Warning: can't material = RWY_WHITE_LIGHTS" );
- }
-
- for ( int i = pnt_i.size() - 1; i >= 0; --i ) {
- osg::Vec3Array *vl = new osg::Vec3Array;
- osg::Vec3Array *nl = new osg::Vec3Array;
- osg::Vec4Array *cl = new osg::Vec4Array;
-
-
- Point3D ppt = nodes[pnt_i[i]] - center;
- osg::Vec3 pt(ppt[0], ppt[1], ppt[2]);
- osg::Vec3 normal(normals[nml_i[i]][0], normals[nml_i[i]][1],
- normals[nml_i[i]][2] );
-
- // calculate a vector perpendicular to dir and up
- osg::Vec3 perp = normal^nup;
-
- // front face
- osg::Vec3 tmp3 = pt;
- vl->push_back( tmp3 );
- tmp3 += nup;
- vl->push_back( tmp3 );
- tmp3 += perp;
- vl->push_back( tmp3 );
-
- nl->push_back(normal);
-
- cl->push_back(osg::Vec4(1, 1, 1, 1));
- cl->push_back(osg::Vec4(1, 1, 1, 0));
- cl->push_back(osg::Vec4(1, 1, 1, 0));
-
- osg::Geometry* geometry = new osg::Geometry;
- geometry->setName("Rabbit Lights " + mat->get_names().front());
- geometry->setVertexArray(vl);
- geometry->setNormalArray(nl);
- geometry->setNormalBinding(osg::Geometry::BIND_OVERALL);
- geometry->setColorArray(cl);
- geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
- geometry->addPrimitiveSet(new osg::DrawArrays(GL_TRIANGLES, 0, vl->size()));
- osg::Geode* geode = new osg::Geode;
- geode->addDrawable(geometry);
-
- geode->setStateSet( mat->get_state() );
-
- // OSGFIXME
-// leaf->setCallback( SSG_CALLBACK_PREDRAW, StrobePreDraw );
-// leaf->setCallback( SSG_CALLBACK_POSTDRAW, StrobePostDraw );
-
- rabbit->addChild( geode );
- }
-
-// 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
- osg::LOD *lod = new osg::LOD;
- lod->addChild( rabbit, 0, 12000 /*OSGFIXME: hadcoded*/ );
-
- // create the transformation.
- osg::MatrixTransform *trans = new osg::MatrixTransform;
- trans->setMatrix(osg::Matrixd::translate(osg::Vec3d(center[0], center[1], center[2])));
- trans->addChild(lod);
-
- return trans;
}
+osg::Drawable*
+SGLightFactory::getVasi(const SGVec3f& up, const SGDirectionalLightBin& lights,
+ const SGVec4f& red, const SGVec4f& white)
+{
+ SGVasiDrawable* drawable = buildVasi(lights, up, red, white);
+ if (!drawable)
+ return 0;
+
+ osg::StateSet* stateSet = drawable->getOrCreateStateSet();
+ stateSet->setRenderBinDetails(9, "DepthSortedBin");
+ stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
+
+ osg::BlendFunc* blendFunc = new osg::BlendFunc;
+ stateSet->setAttribute(blendFunc);
+ stateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
+
+ osg::AlphaFunc* alphaFunc;
+ alphaFunc = new osg::AlphaFunc(osg::AlphaFunc::GREATER, 0.01);
+ stateSet->setAttribute(alphaFunc);
+ stateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::ON);
+
+ return drawable;
+}
-osg::Node *SGMakeDirectionalLights( const point_list &nodes,
- const point_list &normals,
- const int_list &pnt_i,
- const int_list &nml_i,
- SGMaterialLib *matlib,
- const string &material,
- const SGVec3d& dup )
+osg::Node*
+SGLightFactory::getSequenced(const SGDirectionalLightBin& lights)
{
- osg::Vec3 nup = toVec3f(dup).osg();
- nup.normalize();
-
- SGMaterial *mat = matlib->find( material );
-
- if ( material == "RWY_REIL_LIGHTS" ) {
- // cout << "found a reil" << endl;
- return gen_reil_lights( nodes, normals, pnt_i, nml_i,
- matlib, nup );
- } else if ( material == "RWY_ODALS_LIGHTS" ) {
- // cout << "found a odals" << endl;
- return gen_odals_lights( nodes, normals, pnt_i, nml_i,
- matlib, nup );
- } else if ( material == "RWY_SEQUENCED_LIGHTS" ) {
- // cout << "found a rabbit" << endl;
- return gen_rabbit_lights( nodes, normals, pnt_i, nml_i,
- matlib, nup );
- } else if ( material == "RWY_VASI_LIGHTS" ) {
- return gen_dir_light_group( nodes, normals, pnt_i,
- nml_i, mat, nup, false, true );
- } else if ( material == "RWY_BLUE_TAXIWAY_LIGHTS" ) {
- return gen_dir_light_group( nodes, normals, pnt_i, nml_i, mat, nup,
- true, false );
- } else {
- return gen_dir_light_group( nodes, normals, pnt_i, nml_i, mat, nup,
- false, false );
- }
+ if (lights.getNumLights() <= 0)
+ return 0;
+
+ // generate a repeatable random seed
+ sg_srandom(unsigned(lights.getLight(0).position[0]));
+ float flashTime = 2e-2 + 5e-3*sg_random();
+ osg::Sequence* sequence = new osg::Sequence;
+ sequence->setDefaultTime(flashTime);
+
+ for (int i = lights.getNumLights() - 1; 0 <= i; --i)
+ sequence->addChild(getLight(lights.getLight(i)), flashTime);
+ sequence->addChild(new osg::Group, 1 + 1e-1*sg_random());
+ sequence->setInterval(osg::Sequence::LOOP, 0, -1);
+ sequence->setDuration(1.0f, -1);
+ sequence->setMode(osg::Sequence::START);
+ sequence->setSync(true);
+
+ osg::StateSet* stateSet = sequence->getOrCreateStateSet();
+ stateSet->setRenderBinDetails(9, "DepthSortedBin");
+ stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
+
+ osg::BlendFunc* blendFunc = new osg::BlendFunc;
+ stateSet->setAttribute(blendFunc);
+ stateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
+
+ osg::AlphaFunc* alphaFunc;
+ alphaFunc = new osg::AlphaFunc(osg::AlphaFunc::GREATER, 0.01);
+ stateSet->setAttribute(alphaFunc);
+ stateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::ON);
+
+ osg::Point* point = new osg::Point;
+ point->setMinSize(6);
+ point->setMaxSize(10);
+ point->setSize(10);
+ point->setDistanceAttenuation(osg::Vec3(1.0, 0.0001, 0.00000001));
+ sequence->setCullCallback(new SGPointSpriteLightCullCallback(point));
+
+ return sequence;
+}
- return NULL;
+osg::Node*
+SGLightFactory::getOdal(const SGLightBin& lights)
+{
+ if (lights.getNumLights() < 2)
+ return 0;
+
+ // generate a repeatable random seed
+ sg_srandom(unsigned(lights.getLight(0).position[0]));
+ float flashTime = 2e-2 + 5e-3*sg_random();
+ osg::Sequence* sequence = new osg::Sequence;
+ sequence->setDefaultTime(flashTime);
+
+ // centerline lights
+ for (int i = lights.getNumLights() - 1; 2 <= i; --i)
+ sequence->addChild(getLight(lights.getLight(i)), flashTime);
+
+ // runway end lights
+ osg::Group* group = new osg::Group;
+ for (unsigned i = 0; i < 2; ++i)
+ group->addChild(getLight(lights.getLight(i)));
+ sequence->addChild(group, flashTime);
+
+ // add an extra empty group for a break
+ sequence->addChild(new osg::Group, 9 + 1e-1*sg_random());
+ sequence->setInterval(osg::Sequence::LOOP, 0, -1);
+ sequence->setDuration(1.0f, -1);
+ sequence->setMode(osg::Sequence::START);
+ sequence->setSync(true);
+
+ osg::StateSet* stateSet = sequence->getOrCreateStateSet();
+ stateSet->setRenderBinDetails(9, "DepthSortedBin");
+ stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
+
+ osg::BlendFunc* blendFunc = new osg::BlendFunc;
+ stateSet->setAttribute(blendFunc);
+ stateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
+
+ osg::AlphaFunc* alphaFunc;
+ alphaFunc = new osg::AlphaFunc(osg::AlphaFunc::GREATER, 0.01);
+ stateSet->setAttribute(alphaFunc);
+ stateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::ON);
+
+ osg::Point* point = new osg::Point;
+ point->setMinSize(6);
+ point->setMaxSize(10);
+ point->setSize(10);
+ point->setDistanceAttenuation(osg::Vec3(1.0, 0.0001, 0.00000001));
+ sequence->setCullCallback(new SGPointSpriteLightCullCallback(point));
+
+ return sequence;
}
# error This library requires C++
#endif
-
#include <simgear/compiler.h>
#include STL_STRING
#include <vector> // STL
+#include <osg/Drawable>
+#include <osg/Node>
+#include <osg/Point>
+
#include <simgear/math/sg_types.hxx>
#include <simgear/scene/material/matlib.hxx>
+#include <simgear/scene/util/SGSceneFeatures.hxx>
+
+#include "SGLightBin.hxx"
+#include "SGDirectionalLightBin.hxx"
SG_USING_STD(string);
SG_USING_STD(vector);
+// Specify the way we want to draw directional point lights (assuming the
+// appropriate extensions are available.)
-typedef vector < int > int_list;
-typedef int_list::iterator int_list_iterator;
-typedef int_list::const_iterator int_point_list_iterator;
-
+inline void SGConfigureDirectionalLights( bool use_point_sprites,
+ bool enhanced_lighting,
+ bool distance_attenuation ) {
+ static SGSceneFeatures* sceneFeatures = SGSceneFeatures::instance();
+ sceneFeatures->setEnablePointSpriteLights(use_point_sprites);
+ sceneFeatures->setEnableDistanceAttenuationLights(distance_attenuation);
+}
-// Generate a directional light. This routines creates a
-// 'directional' light that can only be viewed from within 90 degrees
-// of the specified dir vector.
+class SGPointSpriteLightCullCallback : public osg::NodeCallback {
+public:
+ SGPointSpriteLightCullCallback(const osg::Vec3& da = osg::Vec3(1, 0.001, 0.0002),
+ float sz = 4);
+ SGPointSpriteLightCullCallback(osg::Point* point);
-// 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.
+ virtual void operator()(osg::Node* node, osg::NodeVisitor* nv);
-// If the triangle is drawn in glPolygonMode(GL_FRONT, GL_POINT) mode,
-// then two important things happen:
+private:
+ osg::ref_ptr<osg::StateSet> _pointSpriteStateSet;
+ osg::ref_ptr<osg::StateSet> _distanceAttenuationStateSet;
+};
-// 1) Only the 3 vertex points are drawn, the 2nd two with an alpha of
-// 0 so actually only the desired point is rendered.
+class SGLightFactory {
+public:
-// 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.
+ static osg::Node*
+ getLight(const SGLightBin::Light& light);
-// 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.)
+ static osg::Node*
+ getLight(const SGDirectionalLightBin::Light& light);
-// Yes this get's to be long and convoluted. If you can suggest a
-// simpler way, please do! :-)
+ static osg::Drawable*
+ getLights(const SGLightBin& lights, unsigned inc = 1, float alphaOff = 0);
-osg::Node *SGMakeDirectionalLights( const point_list &nodes,
- const point_list &normals,
- const int_list &pnt_i,
- const int_list &nml_i,
- SGMaterialLib *matlib,
- const string &material,
- const SGVec3d& dup );
+ static osg::Drawable*
+ getLights(const SGDirectionalLightBin& lights);
-// Specify the way we want to draw directional point lights (assuming the
-// appropriate extensions are available.)
+ static osg::Drawable*
+ getVasi(const SGVec3f& up, const SGDirectionalLightBin& lights,
+ const SGVec4f& red, const SGVec4f& white);
-void SGConfigureDirectionalLights( bool use_point_sprites,
- bool enhanced_lighting,
- bool distance_attenuation );
+ static osg::Node*
+ getSequenced(const SGDirectionalLightBin& lights);
+ static osg::Node*
+ getOdal(const SGLightBin& lights);
+};
#endif // _SG_PT_LIGHTS_HXX
+++ /dev/null
-// vasi.hxx -- a class to hold some critical vasi data
-//
-// Written by Curtis Olson, started December 2003.
-//
-// Copyright (C) 2003 Curtis L. Olson - http://www.flightgear.org/~curt
-//
-// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-//
-// $Id$
-
-
-#ifndef _SG_VASI_HXX
-#define _SG_VASI_HXX
-
-#ifndef __cplusplus
-# error This library requires C++
-#endif
-
-#include <simgear/compiler.h>
-
-#include <osg/io_utils>
-#include <osg/ref_ptr>
-#include <osg/Array>
-#include <osg/NodeCallback>
-#include <osg/NodeVisitor>
-#include <osg/Vec3>
-
-/// Callback that updates the colors of a VASI according to the view direction
-/// Notet that we need the eyepoint which is only available during culling
-/// So this will be a cull callback ...
-class SGVasiUpdateCallback : public osg::NodeCallback {
-public:
- SGVasiUpdateCallback(osg::Vec4Array* vasiColorArray,
- const osg::Vec3& referencePoint,
- const osg::Vec3& glideSlopeUp,
- const osg::Vec3& glideSlopeDir) :
- mVasiColorArray(vasiColorArray),
- mReferencePoint(referencePoint),
- mGlideSlopeUp(glideSlopeUp),
- mGlideSlopeDir(glideSlopeDir)
- {
- mGlideSlopeUp.normalize();
- mGlideSlopeDir.normalize();
- }
- virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
- {
- // Rerieve the eye point relative to the vasi reference point
- osg::Vec3 eyePoint = nv->getEyePoint() - mReferencePoint;
- // Now project the eye point vector into the plane defined by the
- // glideslope direction and the up direction
- osg::Vec3 normal = mGlideSlopeUp^mGlideSlopeDir;
- normal.normalize();
- osg::Vec3 projEyePoint = eyePoint - normal * (eyePoint*normal);
-
- double projEyePointLength = projEyePoint.length();
- if (fabs(projEyePointLength) < 1e-3)
- set_color(3);
- else {
- double aSinAngle = projEyePoint*mGlideSlopeUp/projEyePointLength;
- if (aSinAngle < -1)
- aSinAngle = -1;
- if (1 < aSinAngle)
- aSinAngle = 1;
-
- double angle = asin(aSinAngle)*SGD_RADIANS_TO_DEGREES;
- set_color(angle);
- }
-
- // call the base implementation
- osg::NodeCallback::operator()(node, nv);
- }
-
- // color the vasi/papi correctly based on angle in degree
- void set_color( double angle_deg ) {
- unsigned count = mVasiColorArray->size();
- double trans = 0.05;
- double color = 1;
- double ref;
-
- if ( count == 12 ) {
- // PAPI configuration
-
- // papi D
- ref = 3.5;
- if ( angle_deg < ref - trans ) {
- color = 0.0;
- } else if ( angle_deg < ref + trans ) {
- color = 1.0 - (ref + trans - angle_deg) * (1 / (2 * trans) );
- } else {
- color = 1.0;
- }
- for ( unsigned i = 0; i < 3; ++i ) {
- (*mVasiColorArray)[i][1] = color;
- (*mVasiColorArray)[i][2] = color;
- }
-
- // papi C
- ref = 3.167;
- if ( angle_deg < ref - trans ) {
- color = 0.0;
- } else if ( angle_deg < ref + trans ) {
- color = 1.0 - (ref + trans - angle_deg) * (1 / (2 * trans) );
- } else {
- color = 1.0;
- }
- for ( unsigned i = 3; i < 6; ++i ) {
- (*mVasiColorArray)[i][1] = color;
- (*mVasiColorArray)[i][2] = color;
- }
-
- // papi B
- ref = 2.833;
- if ( angle_deg < ref - trans ) {
- color = 0.0;
- } else if ( angle_deg < ref + trans ) {
- color = 1.0 - (ref + trans - angle_deg) * (1 / (2 * trans) );
- } else {
- color = 1.0;
- }
- for ( unsigned i = 6; i < 9; ++i ) {
- (*mVasiColorArray)[i][1] = color;
- (*mVasiColorArray)[i][2] = color;
- }
-
- // papi A
- ref = 2.5;
- if ( angle_deg < ref - trans ) {
- color = 0.0;
- } else if ( angle_deg < ref + trans ) {
- color = 1.0 - (ref + trans - angle_deg) * (1 / (2 * trans) );
- } else {
- color = 1.0;
- }
- for ( unsigned i = 9; i < 12; ++i ) {
- (*mVasiColorArray)[i][1] = color;
- (*mVasiColorArray)[i][2] = color;
- }
- } else if ( count == 36 ) {
- // probably vasi, first 18 are downwind bar (2.5 deg)
- ref = 2.5;
- if ( angle_deg < ref - trans ) {
- color = 0.0;
- } else if ( angle_deg < ref + trans ) {
- color = 1.0 - (ref + trans - angle_deg) * (1 / (2 * trans) );
- } else {
- color = 1.0;
- }
- for ( unsigned i = 0; i < 18; ++i ) {
- (*mVasiColorArray)[i][1] = color;
- (*mVasiColorArray)[i][2] = color;
- }
-
- // last 6 are upwind bar (3.0 deg)
- ref = 3.0;
- if ( angle_deg < ref - trans ) {
- color = 0.0;
- } else if ( angle_deg < ref + trans ) {
- color = 1.0 - (ref + trans - angle_deg) * (1 / (2 * trans) );
- } else {
- color = 1.0;
- }
- for ( unsigned i = 18; i < 36; ++i ) {
- (*mVasiColorArray)[i][1] = color;
- (*mVasiColorArray)[i][2] = color;
- }
- } else {
- // fail safe
- cout << "unknown vasi/papi configuration, count = " << count << endl;
- for ( unsigned i = 0; i < count; ++i ) {
- (*mVasiColorArray)[i][1] = color;
- (*mVasiColorArray)[i][2] = color;
- }
- }
- // Finally mark the color array dirty
- mVasiColorArray->dirty();
- }
-
-private:
- osg::ref_ptr<osg::Vec4Array> mVasiColorArray;
- osg::Vec3 mReferencePoint;
- osg::Vec3 mGlideSlopeUp;
- osg::Vec3 mGlideSlopeDir;
-};
-
-#endif // _SG_VASI_HXX
include_HEADERS = \
SGNodeMasks.hxx \
SGUpdateVisitor.hxx \
+ SGEnlargeBoundingBox.hxx \
SGDebugDrawCallback.hxx \
SGPickCallback.hxx \
+ SGSceneFeatures.hxx \
SGSceneUserData.hxx \
SGStateAttributeVisitor.hxx \
SGTextureStateAttributeVisitor.hxx
libsgutil_a_SOURCES = \
+ SGEnlargeBoundingBox.cxx \
+ SGSceneFeatures.cxx \
SGSceneUserData.cxx \
SGStateAttributeVisitor.cxx \
SGTextureStateAttributeVisitor.cxx
--- /dev/null
+/* -*-c++-*-
+ *
+ * Copyright (C) 2006-2007 Mathias Froehlich
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <simgear_config.h>
+#endif
+
+#include "SGEnlargeBoundingBox.hxx"
+#include <osg/Drawable>
+
+SGEnlargeBoundingBox::SGEnlargeBoundingBox(float offset) :
+ _offset(offset)
+{
+}
+
+SGEnlargeBoundingBox::SGEnlargeBoundingBox(const SGEnlargeBoundingBox& cb,
+ const osg::CopyOp& copyOp) :
+ osg::Drawable::ComputeBoundingBoxCallback(cb, copyOp),
+ _offset(cb._offset)
+{
+}
+
+osg::BoundingBox
+SGEnlargeBoundingBox::computeBound(const osg::Drawable& drawable) const
+{
+ osg::BoundingBox bound = drawable.computeBound();
+ if (!bound.valid())
+ return bound;
+ return osg::BoundingBox(bound._min - osg::Vec3(_offset, _offset, _offset),
+ bound._max + osg::Vec3(_offset, _offset, _offset));
+}
--- /dev/null
+/* -*-c++-*-
+ *
+ * Copyright (C) 2006-2007 Mathias Froehlich
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ */
+
+#ifndef SG_ENLARGE_BOUNDING_BOX_HXX
+#define SG_ENLARGE_BOUNDING_BOX_HXX
+
+#include <osg/Drawable>
+
+// Helper class to enlarge a bounding box of a drawable.
+// Is usefull to enlarge the mounding box of single point lights that would
+// be victim to small feature culling otherwise.
+class SGEnlargeBoundingBox : public osg::Drawable::ComputeBoundingBoxCallback {
+public:
+ SGEnlargeBoundingBox(float offset = 0);
+ SGEnlargeBoundingBox(const SGEnlargeBoundingBox& cb, const osg::CopyOp&);
+ META_Object(osg, SGEnlargeBoundingBox);
+ virtual osg::BoundingBox computeBound(const osg::Drawable& drawable) const;
+
+private:
+ float _offset;
+};
+
+#endif
/// If set, the node is pickable
#define SG_NODEMASK_PICK_BIT (1<<4)
+/// If set, the node is a gui element
+#define SG_NODEMASK_GUI_BIT (1<<5)
+
#endif
--- /dev/null
+/* -*-c++-*-
+ *
+ * Copyright (C) 2006-2007 Mathias Froehlich
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <simgear_config.h>
+#endif
+
+#include "SGSceneFeatures.hxx"
+
+#include <osg/FragmentProgram>
+#include <osg/VertexProgram>
+#include <osg/Point>
+#include <osg/PointSprite>
+
+#include <simgear/structure/SGSharedPtr.hxx>
+#include <simgear/threads/SGThread.hxx>
+#include <simgear/threads/SGGuard.hxx>
+
+SGSceneFeatures::SGSceneFeatures() :
+ _shaderLights(true),
+ _pointSpriteLights(true),
+ _distanceAttenuationLights(true)
+{
+}
+
+SGSceneFeatures*
+SGSceneFeatures::instance()
+{
+ static SGSharedPtr<SGSceneFeatures> sceneFeatures;
+ if (sceneFeatures)
+ return sceneFeatures;
+ static SGMutex mutex;
+ SGGuard<SGMutex> guard(mutex);
+ if (sceneFeatures)
+ return sceneFeatures;
+ sceneFeatures = new SGSceneFeatures;
+ return sceneFeatures;
+}
+
+bool
+SGSceneFeatures::getHavePointSprites(unsigned contextId) const
+{
+ return osg::PointSprite::isPointSpriteSupported(contextId);
+}
+
+bool
+SGSceneFeatures::getHaveFragmentPrograms(unsigned contextId) const
+{
+ const osg::FragmentProgram::Extensions* fpe;
+ fpe = osg::FragmentProgram::getExtensions(contextId, true);
+ if (!fpe)
+ return false;
+ if (!fpe->isFragmentProgramSupported())
+ return false;
+
+ return true;
+}
+
+bool
+SGSceneFeatures::getHaveVertexPrograms(unsigned contextId) const
+{
+ const osg::VertexProgram::Extensions* vpe;
+ vpe = osg::VertexProgram::getExtensions(contextId, true);
+ if (!vpe)
+ return false;
+ if (!vpe->isVertexProgramSupported())
+ return false;
+
+ return true;
+}
+
+bool
+SGSceneFeatures::getHaveShaderPrograms(unsigned contextId) const
+{
+ if (!getHaveFragmentPrograms(contextId))
+ return false;
+ return getHaveVertexPrograms(contextId);
+}
+
+bool
+SGSceneFeatures::getHavePointParameters(unsigned contextId) const
+{
+ const osg::Point::Extensions* pe;
+ pe = osg::Point::getExtensions(contextId, true);
+ if (!pe)
+ return false;
+ if (!pe->isPointParametersSupported())
+ return false;
+ return true;
+}
+
--- /dev/null
+/* -*-c++-*-
+ *
+ * Copyright (C) 2006-2007 Mathias Froehlich
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ */
+
+#ifndef SG_SCENE_FEATURES_HXX
+#define SG_SCENE_FEATURES_HXX
+
+#include <simgear/structure/SGReferenced.hxx>
+
+class SGSceneFeatures : public SGReferenced {
+public:
+ static SGSceneFeatures* instance();
+
+ void setEnablePointSpriteLights(bool enable)
+ { _pointSpriteLights = enable; }
+ bool getEnablePointSpriteLights(unsigned contextId) const
+ {
+ if (!_pointSpriteLights)
+ return false;
+ return getHavePointSprites(contextId);
+ }
+
+ void setEnableDistanceAttenuationLights(bool enable)
+ { _distanceAttenuationLights = enable; }
+ bool getEnableDistanceAttenuationLights(unsigned contextId) const
+ {
+ if (!_distanceAttenuationLights)
+ return false;
+ return getHavePointParameters(contextId);
+ }
+
+ void setEnableShaderLights(bool enable)
+ { _shaderLights = enable; }
+ bool getEnableShaderLights(unsigned contextId) const
+ {
+ if (!_shaderLights)
+ return false;
+ return getHaveShaderPrograms(contextId);
+ }
+
+protected:
+ bool getHavePointSprites(unsigned contextId) const;
+ bool getHaveFragmentPrograms(unsigned contextId) const;
+ bool getHaveVertexPrograms(unsigned contextId) const;
+ bool getHaveShaderPrograms(unsigned contextId) const;
+ bool getHavePointParameters(unsigned contextId) const;
+
+private:
+ SGSceneFeatures();
+ SGSceneFeatures(const SGSceneFeatures&);
+ SGSceneFeatures& operator=(const SGSceneFeatures&);
+
+ bool _shaderLights;
+ bool _pointSpriteLights;
+ bool _distanceAttenuationLights;
+};
+
+#endif
*
*/
+#ifdef HAVE_CONFIG_H
+# include <simgear_config.h>
+#endif
+
#include "SGTextureStateAttributeVisitor.hxx"
SGTextureStateAttributeVisitor::SGTextureStateAttributeVisitor() :