Generate a set of ground lights when loading a scenery tile.
This commit is contained in:
parent
45564beba8
commit
90d30b023e
2 changed files with 102 additions and 31 deletions
|
@ -267,40 +267,84 @@ ssgBranch *fgGenTile( const string& path, FGTileEntry *t) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void gen_random_surface_points( ssgLeaf *leaf, ssgVertexArray *lights ) {
|
static double triangle_area_3d( float *p1, float *p2, float *p3 ) {
|
||||||
int num = leaf->getNumVertices();
|
// Heron's formula: A^2 = s(s-a)(s-b)(s-c) where A is the area,
|
||||||
float *n1, *n2, *n3;
|
// a,b,c are the side lengths, s=(a+b+c)/2. In R^3 you can compute
|
||||||
|
// the lengths of the sides with the distance formula, of course.
|
||||||
|
|
||||||
|
double a = sgDistanceVec3( p1, p2 );
|
||||||
|
double b = sgDistanceVec3( p2, p3 );
|
||||||
|
double c = sgDistanceVec3( p3, p1 );
|
||||||
|
|
||||||
|
double s = (a + b + c) / 2.0;
|
||||||
|
|
||||||
|
return sqrt( s * ( s - a ) * ( s - b ) * ( s - c ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void random_pt_inside_tri( float *res,
|
||||||
|
float *n1, float *n2, float *n3 )
|
||||||
|
{
|
||||||
sgVec3 p1, p2, p3;
|
sgVec3 p1, p2, p3;
|
||||||
|
|
||||||
|
double a = sg_random();
|
||||||
|
double b = sg_random();
|
||||||
|
if ( a + b > 1.0 ) {
|
||||||
|
a = 1.0 - a;
|
||||||
|
b = 1.0 - b;
|
||||||
|
}
|
||||||
|
double c = 1 - a - b;
|
||||||
|
|
||||||
|
sgScaleVec3( p1, n1, a );
|
||||||
|
sgScaleVec3( p2, n2, b );
|
||||||
|
sgScaleVec3( p3, n3, c );
|
||||||
|
|
||||||
|
sgAddVec3( res, p1, p2 );
|
||||||
|
sgAddVec3( res, p3 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void gen_random_surface_points( ssgLeaf *leaf, ssgVertexArray *lights,
|
||||||
|
double factor ) {
|
||||||
|
int num = leaf->getNumTriangles();
|
||||||
|
short int n1, n2, n3;
|
||||||
|
float *p1, *p2, *p3;
|
||||||
sgVec3 result;
|
sgVec3 result;
|
||||||
float remainder = 1.0;
|
|
||||||
float weight;
|
|
||||||
|
|
||||||
n1 = leaf->getVertex( 1 );
|
for ( int i = 0; i < num; ++i ) {
|
||||||
n2 = leaf->getVertex( 2 );
|
leaf->getTriangle( i, &n1, &n2, &n3 );
|
||||||
for ( int i = 3; i < num; ++i ) {
|
p1 = leaf->getVertex(n1);
|
||||||
n3 = leaf->getVertex( i );
|
p2 = leaf->getVertex(n2);
|
||||||
weight = sg_random();
|
p3 = leaf->getVertex(n3);
|
||||||
remainder -= weight;
|
double area = triangle_area_3d( p1, p2, p3 );
|
||||||
sgScaleVec3( p1, n1, weight );
|
double num = area / factor;
|
||||||
|
|
||||||
weight = sg_random() * remainder;
|
// generate a light point for each unit of area
|
||||||
remainder -= weight;
|
while ( num > 1.0 ) {
|
||||||
sgScaleVec3( p2, n2, weight );
|
random_pt_inside_tri( result, p1, p2, p3 );
|
||||||
|
|
||||||
sgScaleVec3( p3, n3, remainder );
|
|
||||||
|
|
||||||
sgAddVec3( result, p1, p2 );
|
|
||||||
sgAddVec3( result, p3 );
|
|
||||||
|
|
||||||
sgScaleVec3( result, 1.0 / 3.0 );
|
|
||||||
lights->add( result );
|
lights->add( result );
|
||||||
|
num -= 1.0;
|
||||||
|
}
|
||||||
|
// for partial units of area, use a zombie door method to
|
||||||
|
// create the proper random chance of a light being created
|
||||||
|
// for this triangle
|
||||||
|
if ( num > 0.0 ) {
|
||||||
|
if ( sg_random() <= num ) {
|
||||||
|
// a zombie made it through our door
|
||||||
|
random_pt_inside_tri( result, p1, p2, p3 );
|
||||||
|
lights->add( result );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Load a .obj file
|
// Load a .obj file
|
||||||
ssgBranch *fgObjLoad( const string& path, FGTileEntry *t, const bool is_base) {
|
ssgBranch *fgObjLoad( const string& path, FGTileEntry *t,
|
||||||
|
ssgVertexArray *lights, const bool is_base)
|
||||||
|
{
|
||||||
FGNewMat *newmat;
|
FGNewMat *newmat;
|
||||||
|
string material;
|
||||||
Point3D pp;
|
Point3D pp;
|
||||||
// sgVec3 approx_normal;
|
// sgVec3 approx_normal;
|
||||||
// double normal[3], scale = 0.0;
|
// double normal[3], scale = 0.0;
|
||||||
|
@ -451,7 +495,6 @@ ssgBranch *fgObjLoad( const string& path, FGTileEntry *t, const bool is_base) {
|
||||||
in_faces = false;
|
in_faces = false;
|
||||||
|
|
||||||
// scan the material line
|
// scan the material line
|
||||||
string material;
|
|
||||||
in >> material;
|
in >> material;
|
||||||
|
|
||||||
// find this material in the properties list
|
// find this material in the properties list
|
||||||
|
@ -699,14 +742,41 @@ ssgBranch *fgObjLoad( const string& path, FGTileEntry *t, const bool is_base) {
|
||||||
|
|
||||||
tile->addKid( leaf );
|
tile->addKid( leaf );
|
||||||
|
|
||||||
/*
|
|
||||||
ssgVertexArray *lights = NULL;
|
|
||||||
if ( is_base ) {
|
if ( is_base ) {
|
||||||
// generate lighting
|
// generate lighting
|
||||||
lights = new ssgVertexArray( size );
|
if ( material == "Urban" || material == "BuiltUpCover" ) {
|
||||||
gen_random_surface_points( leaf, lights );
|
gen_random_surface_points( leaf, lights, 100000.0 );
|
||||||
|
} else if ( material == "EvergreenBroadCover" ||
|
||||||
|
material == "Default" || material == "Island" ||
|
||||||
|
material == "SomeSort" ||
|
||||||
|
material == "DeciduousBroadCover" ||
|
||||||
|
material == "EvergreenNeedleCover" ||
|
||||||
|
material == "DeciduousNeedleCover" ) {
|
||||||
|
gen_random_surface_points( leaf, lights, 10000000.0 );
|
||||||
|
} else if ( material == "MixedForestCover" ) {
|
||||||
|
gen_random_surface_points( leaf, lights, 5000000.0 );
|
||||||
|
} else if ( material == "WoodedTundraCover" ||
|
||||||
|
material == "BareTundraCover" ||
|
||||||
|
material == "HerbTundraCover" ||
|
||||||
|
material == "MixedTundraCover" ||
|
||||||
|
material == "Marsh" ||
|
||||||
|
material == "HerbWetlandCover" ||
|
||||||
|
material == "WoodedWetlandCover" ) {
|
||||||
|
gen_random_surface_points( leaf, lights, 20000000.0 );
|
||||||
|
} else if ( material == "ShrubCover" ||
|
||||||
|
material == "ShrubGrassCover" ) {
|
||||||
|
gen_random_surface_points( leaf, lights, 4000000.0 );
|
||||||
|
} else if ( material == "GrassCover" ||
|
||||||
|
material == "SavannaCover" ) {
|
||||||
|
gen_random_surface_points( leaf, lights, 4000000.0 );
|
||||||
|
} else if ( material == "MixedCropPastureCover" ||
|
||||||
|
material == "IrrCropPastureCover" ||
|
||||||
|
material == "DryCropPastureCover" ||
|
||||||
|
material == "CropGrassCover" ||
|
||||||
|
material == "CropWoodCover" ) {
|
||||||
|
gen_random_surface_points( leaf, lights, 2000000.0 );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
} else {
|
} else {
|
||||||
FG_LOG( FG_TERRAIN, FG_WARN, "Unknown token in "
|
FG_LOG( FG_TERRAIN, FG_WARN, "Unknown token in "
|
||||||
<< path << " = " << token );
|
<< path << " = " << token );
|
||||||
|
|
|
@ -56,7 +56,8 @@ FG_USING_STD(string);
|
||||||
|
|
||||||
|
|
||||||
// Load a .obj file
|
// Load a .obj file
|
||||||
ssgBranch *fgObjLoad(const string& path, FGTileEntry *tile, const bool is_base);
|
ssgBranch *fgObjLoad(const string& path, FGTileEntry *tile,
|
||||||
|
ssgVertexArray *lights, const bool is_base);
|
||||||
|
|
||||||
|
|
||||||
#endif // _OBJ_HXX
|
#endif // _OBJ_HXX
|
||||||
|
|
Loading…
Reference in a new issue