PagedLOD for random trees, buildings and objects.
This commit is contained in:
parent
3ec9c7ae6e
commit
5bc535a8d2
@ -61,13 +61,13 @@ using namespace osg;
|
||||
|
||||
namespace simgear
|
||||
{
|
||||
|
||||
|
||||
typedef std::map<std::string, osg::observer_ptr<osg::StateSet> > BuildingStateSetMap;
|
||||
static BuildingStateSetMap statesetmap;
|
||||
|
||||
typedef std::map<std::string, osg::observer_ptr<Effect> > EffectMap;
|
||||
static EffectMap buildingEffectMap;
|
||||
|
||||
|
||||
// Building instance scheme:
|
||||
// vertex - local position of vertices, with 0,0,0 being the center front.
|
||||
// fog coord - rotation
|
||||
@ -88,7 +88,7 @@ BuildingBoundingBoxCallback::computeBound(const Drawable& drawable) const
|
||||
const Geometry* geom = static_cast<const Geometry*>(&drawable);
|
||||
const Vec3Array* v = static_cast<const Vec3Array*>(geom->getVertexArray());
|
||||
const Vec4Array* pos = static_cast<const Vec4Array*>(geom->getColorArray());
|
||||
|
||||
|
||||
Geometry::PrimitiveSetList primSets = geom->getPrimitiveSetList();
|
||||
for (Geometry::PrimitiveSetList::const_iterator psitr = primSets.begin(), psend = primSets.end();
|
||||
psitr != psend;
|
||||
@ -104,132 +104,132 @@ BuildingBoundingBoxCallback::computeBound(const Drawable& drawable) const
|
||||
bb.expandBy(pt);
|
||||
}
|
||||
}
|
||||
return bb;
|
||||
return bb;
|
||||
}
|
||||
|
||||
// Set up the building set based on the material definitions
|
||||
SGBuildingBin::SGBuildingBin(const SGMaterial *mat) {
|
||||
|
||||
material_name = mat->get_names()[0];
|
||||
|
||||
material_name = new std::string(mat->get_names()[0]);
|
||||
SG_LOG(SG_TERRAIN, SG_DEBUG, "Building material " << material_name);
|
||||
texture = mat->get_building_texture();
|
||||
lightMap = mat->get_building_lightmap();
|
||||
texture = new std::string(mat->get_building_texture());
|
||||
lightMap = new std::string(mat->get_building_lightmap());
|
||||
SG_LOG(SG_TERRAIN, SG_DEBUG, "Building texture " << texture);
|
||||
|
||||
|
||||
// Generate a random seed for the building generation.
|
||||
mt seed;
|
||||
mt_init(&seed, unsigned(123));
|
||||
|
||||
|
||||
smallSharedGeometry = new osg::Geometry();
|
||||
mediumSharedGeometry = new osg::Geometry();
|
||||
largeSharedGeometry = new osg::Geometry();
|
||||
|
||||
|
||||
smallBuildingMaxRadius = std::max(mat->get_building_small_max_depth() * 0.5, mat->get_building_small_max_width() * 0.5);
|
||||
mediumBuildingMaxRadius = std::max(mat->get_building_medium_max_depth() * 0.5, mat->get_building_medium_max_width() * 0.5);
|
||||
largeBuildingMaxRadius = std::max(mat->get_building_large_max_depth() * 0.5, mat->get_building_large_max_width() * 0.5);
|
||||
|
||||
|
||||
smallBuildingMaxDepth = mat->get_building_small_max_depth();
|
||||
mediumBuildingMaxDepth = mat->get_building_medium_max_depth();
|
||||
largeBuildingMaxDepth = mat->get_building_large_max_depth();
|
||||
|
||||
largeBuildingMaxDepth = mat->get_building_large_max_depth();
|
||||
|
||||
smallBuildingFraction = mat->get_building_small_fraction();
|
||||
mediumBuildingFraction = mat->get_building_medium_fraction();
|
||||
|
||||
|
||||
buildingRange = mat->get_building_range();
|
||||
|
||||
|
||||
SG_LOG(SG_TERRAIN, SG_DEBUG, "Building fractions " << smallBuildingFraction << " " << mediumBuildingFraction);
|
||||
|
||||
|
||||
|
||||
|
||||
// TODO: Reverse this - otherwise we never get any large buildings!
|
||||
BuildingType types[] = { SGBuildingBin::SMALL, SGBuildingBin::MEDIUM, SGBuildingBin::LARGE };
|
||||
BuildingType types[] = { SGBuildingBin::SMALL, SGBuildingBin::MEDIUM, SGBuildingBin::LARGE };
|
||||
BuildingList lists[] = { SGBuildingBin::smallBuildings, SGBuildingBin::mediumBuildings, SGBuildingBin::largeBuildings };
|
||||
ref_ptr<Geometry> geometries[] = { smallSharedGeometry, mediumSharedGeometry, largeSharedGeometry };
|
||||
|
||||
|
||||
for (int bt=0; bt < 3; bt++) {
|
||||
SGBuildingBin::BuildingType buildingtype = types[bt];
|
||||
ref_ptr<Geometry> sharedGeometry = geometries[bt];
|
||||
BuildingList buildings = lists[bt];
|
||||
|
||||
|
||||
osg::ref_ptr<osg::Vec3Array> v = new osg::Vec3Array;
|
||||
osg::ref_ptr<osg::Vec2Array> t = new osg::Vec2Array;
|
||||
osg::ref_ptr<osg::Vec3Array> n = new osg::Vec3Array;
|
||||
|
||||
|
||||
v->reserve(BUILDING_SET_SIZE * VERTICES_PER_BUILDING);
|
||||
t->reserve(BUILDING_SET_SIZE * VERTICES_PER_BUILDING);
|
||||
n->reserve(BUILDING_SET_SIZE * VERTICES_PER_BUILDING);
|
||||
|
||||
|
||||
sharedGeometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
|
||||
sharedGeometry->setFogCoordBinding(osg::Geometry::BIND_PER_VERTEX);
|
||||
sharedGeometry->setComputeBoundingBoxCallback(new BuildingBoundingBoxCallback);
|
||||
sharedGeometry->setUseDisplayList(false);
|
||||
|
||||
for (unsigned int j = 0; j < BUILDING_SET_SIZE; j++) {
|
||||
|
||||
for (unsigned int j = 0; j < BUILDING_SET_SIZE; j++) {
|
||||
float width;
|
||||
float depth;
|
||||
int floors;
|
||||
float height;
|
||||
bool pitched;
|
||||
|
||||
|
||||
if (buildingtype == SGBuildingBin::SMALL) {
|
||||
// Small building
|
||||
width = mat->get_building_small_min_width() + mt_rand(&seed) * mt_rand(&seed) * (mat->get_building_small_max_width() - mat->get_building_small_min_width());
|
||||
depth = mat->get_building_small_min_depth() + mt_rand(&seed) * mt_rand(&seed) * (mat->get_building_small_max_depth() - mat->get_building_small_min_depth());
|
||||
floors = SGMisc<double>::round(mat->get_building_small_min_floors() + mt_rand(&seed) * (mat->get_building_small_max_floors() - mat->get_building_small_min_floors()));
|
||||
height = floors * (2.8 + mt_rand(&seed));
|
||||
|
||||
|
||||
// Small buildings are never deeper than they are wide.
|
||||
if (depth > width) { depth = width; }
|
||||
|
||||
|
||||
pitched = (mt_rand(&seed) < mat->get_building_small_pitch());
|
||||
} else if (buildingtype == SGBuildingBin::MEDIUM) {
|
||||
width = mat->get_building_medium_min_width() + mt_rand(&seed) * mt_rand(&seed) * (mat->get_building_medium_max_width() - mat->get_building_medium_min_width());
|
||||
depth = mat->get_building_medium_min_depth() + mt_rand(&seed) * mt_rand(&seed) * (mat->get_building_medium_max_depth() - mat->get_building_medium_min_depth());
|
||||
floors = SGMisc<double>::round(mat->get_building_medium_min_floors() + mt_rand(&seed) * (mat->get_building_medium_max_floors() - mat->get_building_medium_min_floors()));
|
||||
height = floors * (2.8 + mt_rand(&seed));
|
||||
|
||||
|
||||
while ((height > width) && (floors > mat->get_building_medium_min_floors())) {
|
||||
// Ensure that medium buildings aren't taller than they are wide
|
||||
floors--;
|
||||
height = floors * (2.8 + mt_rand(&seed));
|
||||
height = floors * (2.8 + mt_rand(&seed));
|
||||
}
|
||||
|
||||
pitched = (mt_rand(&seed) < mat->get_building_medium_pitch());
|
||||
|
||||
pitched = (mt_rand(&seed) < mat->get_building_medium_pitch());
|
||||
} else {
|
||||
width = mat->get_building_large_min_width() + mt_rand(&seed) * (mat->get_building_large_max_width() - mat->get_building_large_min_width());
|
||||
depth = mat->get_building_large_min_depth() + mt_rand(&seed) * (mat->get_building_large_max_depth() - mat->get_building_large_min_depth());
|
||||
floors = SGMisc<double>::round(mat->get_building_large_min_floors() + mt_rand(&seed) * (mat->get_building_large_max_floors() - mat->get_building_large_min_floors()));
|
||||
floors = SGMisc<double>::round(mat->get_building_large_min_floors() + mt_rand(&seed) * (mat->get_building_large_max_floors() - mat->get_building_large_min_floors()));
|
||||
height = floors * (2.8 + mt_rand(&seed));
|
||||
pitched = (mt_rand(&seed) < mat->get_building_large_pitch());
|
||||
pitched = (mt_rand(&seed) < mat->get_building_large_pitch());
|
||||
}
|
||||
|
||||
Building building = Building(buildingtype,
|
||||
width,
|
||||
depth,
|
||||
height,
|
||||
|
||||
Building building = Building(buildingtype,
|
||||
width,
|
||||
depth,
|
||||
height,
|
||||
floors,
|
||||
pitched);
|
||||
|
||||
pitched);
|
||||
|
||||
buildings.push_back(building);
|
||||
|
||||
// Now create an OSG Geometry based on the Building
|
||||
float cw = 0.5f * building.width;
|
||||
float cd = building.depth;
|
||||
float ch = building.height;
|
||||
|
||||
|
||||
// 0,0,0 is the bottom center of the front
|
||||
// face, e.g. where the front door would be
|
||||
|
||||
// face, e.g. where the front door would be
|
||||
|
||||
// BASEMENT
|
||||
// This exteds 10m below the main section
|
||||
// Front face
|
||||
// Front face
|
||||
v->push_back( osg::Vec3( 0, -cw, -10) ); // bottom right
|
||||
v->push_back( osg::Vec3( 0, cw, -10) ); // bottom left
|
||||
v->push_back( osg::Vec3( 0, cw, 0) ); // top left
|
||||
v->push_back( osg::Vec3( 0, -cw, 0) ); // top right
|
||||
|
||||
|
||||
for (int i=0; i<4; ++i)
|
||||
n->push_back( osg::Vec3(1, 0, 0) ); // normal
|
||||
|
||||
|
||||
// Left face
|
||||
v->push_back( osg::Vec3( -cd, -cw, -10) ); // bottom right
|
||||
v->push_back( osg::Vec3( 0, -cw, -10) ); // bottom left
|
||||
@ -244,10 +244,10 @@ BuildingBoundingBoxCallback::computeBound(const Drawable& drawable) const
|
||||
v->push_back( osg::Vec3( -cd, -cw, -10) ); // bottom left
|
||||
v->push_back( osg::Vec3( -cd, -cw, 0) ); // top left
|
||||
v->push_back( osg::Vec3( -cd, cw, 0) ); // top right
|
||||
|
||||
|
||||
for (int i=0; i<4; ++i)
|
||||
n->push_back( osg::Vec3(-1, 0, 0) ); // normal
|
||||
|
||||
|
||||
// Right face
|
||||
v->push_back( osg::Vec3( 0, cw, -10) ); // bottom right
|
||||
v->push_back( osg::Vec3( -cd, cw, -10) ); // bottom left
|
||||
@ -255,18 +255,18 @@ BuildingBoundingBoxCallback::computeBound(const Drawable& drawable) const
|
||||
v->push_back( osg::Vec3( 0, cw, 0) ); // top right
|
||||
|
||||
for (int i=0; i<4; ++i)
|
||||
n->push_back( osg::Vec3(0, 1, 0) ); // normal
|
||||
|
||||
n->push_back( osg::Vec3(0, 1, 0) ); // normal
|
||||
|
||||
// MAIN BODY
|
||||
// Front face
|
||||
// Front face
|
||||
v->push_back( osg::Vec3( 0, -cw, 0) ); // bottom right
|
||||
v->push_back( osg::Vec3( 0, cw, 0) ); // bottom left
|
||||
v->push_back( osg::Vec3( 0, cw, ch) ); // top left
|
||||
v->push_back( osg::Vec3( 0, -cw, ch) ); // top right
|
||||
|
||||
|
||||
for (int i=0; i<4; ++i)
|
||||
n->push_back( osg::Vec3(1, 0, 0) ); // normal
|
||||
|
||||
|
||||
// Left face
|
||||
v->push_back( osg::Vec3( -cd, -cw, 0) ); // bottom right
|
||||
v->push_back( osg::Vec3( 0, -cw, 0) ); // bottom left
|
||||
@ -281,10 +281,10 @@ BuildingBoundingBoxCallback::computeBound(const Drawable& drawable) const
|
||||
v->push_back( osg::Vec3( -cd, -cw, 0) ); // bottom left
|
||||
v->push_back( osg::Vec3( -cd, -cw, ch) ); // top left
|
||||
v->push_back( osg::Vec3( -cd, cw, ch) ); // top right
|
||||
|
||||
|
||||
for (int i=0; i<4; ++i)
|
||||
n->push_back( osg::Vec3(-1, 0, 0) ); // normal
|
||||
|
||||
|
||||
// Right face
|
||||
v->push_back( osg::Vec3( 0, cw, 0) ); // bottom right
|
||||
v->push_back( osg::Vec3( -cd, cw, 0) ); // bottom left
|
||||
@ -293,25 +293,25 @@ BuildingBoundingBoxCallback::computeBound(const Drawable& drawable) const
|
||||
|
||||
for (int i=0; i<4; ++i)
|
||||
n->push_back( osg::Vec3(0, 1, 0) ); // normal
|
||||
|
||||
|
||||
// ROOF
|
||||
if (building.pitched) {
|
||||
|
||||
if (building.pitched) {
|
||||
|
||||
// Front pitched roof
|
||||
v->push_back( osg::Vec3( 0, -cw, ch) ); // bottom right
|
||||
v->push_back( osg::Vec3( 0, cw, ch) ); // bottom left
|
||||
v->push_back( osg::Vec3(-0.5*cd, cw, ch+3) ); // top left
|
||||
v->push_back( osg::Vec3(-0.5*cd, -cw, ch+3) ); // top right
|
||||
|
||||
|
||||
for (int i=0; i<4; ++i)
|
||||
n->push_back( osg::Vec3(0.707, 0, 0.707) ); // normal
|
||||
|
||||
|
||||
// Left pitched roof
|
||||
v->push_back( osg::Vec3( -cd, -cw, ch) ); // bottom right
|
||||
v->push_back( osg::Vec3( 0, -cw, ch) ); // bottom left
|
||||
v->push_back( osg::Vec3(-0.5*cd, -cw, ch+3) ); // top left
|
||||
v->push_back( osg::Vec3(-0.5*cd, -cw, ch+3) ); // top right
|
||||
|
||||
|
||||
for (int i=0; i<4; ++i)
|
||||
n->push_back( osg::Vec3(0, -1, 0) ); // normal
|
||||
|
||||
@ -320,37 +320,37 @@ BuildingBoundingBoxCallback::computeBound(const Drawable& drawable) const
|
||||
v->push_back( osg::Vec3( -cd, -cw, ch) ); // bottom left
|
||||
v->push_back( osg::Vec3(-0.5*cd, -cw, ch+3) ); // top left
|
||||
v->push_back( osg::Vec3(-0.5*cd, cw, ch+3) ); // top right
|
||||
|
||||
|
||||
for (int i=0; i<4; ++i)
|
||||
n->push_back( osg::Vec3(-0.707, 0, 0.707) ); // normal
|
||||
n->push_back( osg::Vec3(-0.707, 0, 0.707) ); // normal
|
||||
|
||||
// Right pitched roof
|
||||
v->push_back( osg::Vec3( 0, cw, ch) ); // bottom right
|
||||
v->push_back( osg::Vec3( -cd, cw, ch) ); // bottom left
|
||||
v->push_back( osg::Vec3(-0.5*cd, cw, ch+3) ); // top left
|
||||
v->push_back( osg::Vec3(-0.5*cd, cw, ch+3) ); // top right
|
||||
|
||||
|
||||
for (int i=0; i<4; ++i)
|
||||
n->push_back( osg::Vec3(0, 1, 0) ); // normal
|
||||
} else {
|
||||
// If the roof isn't pitched, we still generate the
|
||||
} else {
|
||||
// If the roof isn't pitched, we still generate the
|
||||
// vertices for simplicity later.
|
||||
|
||||
|
||||
// Top of the roof
|
||||
v->push_back( osg::Vec3( 0, -cw, ch) ); // bottom right
|
||||
v->push_back( osg::Vec3( 0, cw, ch) ); // bottom left
|
||||
v->push_back( osg::Vec3(-cd, cw, ch) ); // top left
|
||||
v->push_back( osg::Vec3(-cd, -cw, ch) ); // top right
|
||||
|
||||
|
||||
for (int i=0; i<4; ++i)
|
||||
n->push_back( osg::Vec3(0, 0, 1) ); // normal
|
||||
|
||||
|
||||
// Left non-pitched roof
|
||||
v->push_back( osg::Vec3( -cd, -cw, ch) ); // bottom right
|
||||
v->push_back( osg::Vec3( 0, -cw, ch) ); // bottom left
|
||||
v->push_back( osg::Vec3( 0, -cw, ch) ); // top left
|
||||
v->push_back( osg::Vec3( -cd, -cw, ch) ); // top right
|
||||
|
||||
|
||||
for (int i=0; i<4; ++i)
|
||||
n->push_back( osg::Vec3(0, -1, 0) ); // normal
|
||||
|
||||
@ -359,25 +359,25 @@ BuildingBoundingBoxCallback::computeBound(const Drawable& drawable) const
|
||||
v->push_back( osg::Vec3(-cd, -cw, ch) ); // bottom left
|
||||
v->push_back( osg::Vec3(-cd, -cw, ch) ); // top left
|
||||
v->push_back( osg::Vec3(-cd, cw, ch) ); // top right
|
||||
|
||||
|
||||
for (int i=0; i<4; ++i)
|
||||
n->push_back( osg::Vec3(1, 0, 0) ); // normal
|
||||
n->push_back( osg::Vec3(1, 0, 0) ); // normal
|
||||
|
||||
// Right pitched roof
|
||||
v->push_back( osg::Vec3( 0, cw, ch) ); // bottom right
|
||||
v->push_back( osg::Vec3(-cd, cw, ch) ); // bottom left
|
||||
v->push_back( osg::Vec3(-cd, cw, ch) ); // top left
|
||||
v->push_back( osg::Vec3( 0, cw, ch) ); // top right
|
||||
|
||||
|
||||
for (int i=0; i<4; ++i)
|
||||
n->push_back( osg::Vec3(0, 1, 0) ); // normal
|
||||
}
|
||||
|
||||
|
||||
// The 1024x1024 texture is split into 32x16 blocks.
|
||||
// For a small building, each block is 6m wide and 3m high.
|
||||
// For a medium building, each block is 10m wide and 3m high.
|
||||
// For a large building, each block is 20m wide and 3m high
|
||||
|
||||
|
||||
if (building.type == SGBuildingBin::SMALL) {
|
||||
// Small buildings are represented on the bottom 5 rows of 3 floors
|
||||
int row = ((int) (mt_rand(&seed) * 1000)) % 5;
|
||||
@ -389,8 +389,8 @@ BuildingBoundingBoxCallback::computeBound(const Drawable& drawable) const
|
||||
float back_x = 384.0/1024.0 + 32.0 / 1024.0 * round((float) building.depth/ 6.0f);
|
||||
|
||||
// BASEMENT - uses the baseline texture
|
||||
for (unsigned int i = 0; i < 16; i++) {
|
||||
t->push_back( osg::Vec2( left_x, base_y) );
|
||||
for (unsigned int i = 0; i < 16; i++) {
|
||||
t->push_back( osg::Vec2( left_x, base_y) );
|
||||
}
|
||||
// MAIN BODY
|
||||
// Front
|
||||
@ -398,19 +398,19 @@ BuildingBoundingBoxCallback::computeBound(const Drawable& drawable) const
|
||||
t->push_back( osg::Vec2( left_x, base_y) ); // bottom left
|
||||
t->push_back( osg::Vec2( left_x, top_y ) ); // top left
|
||||
t->push_back( osg::Vec2( right_x, top_y ) ); // top right
|
||||
|
||||
|
||||
// Left
|
||||
t->push_back( osg::Vec2( front_x, base_y) ); // bottom right
|
||||
t->push_back( osg::Vec2( back_x, base_y) ); // bottom left
|
||||
t->push_back( osg::Vec2( back_x, top_y ) ); // top left
|
||||
t->push_back( osg::Vec2( front_x, top_y ) ); // top right
|
||||
|
||||
|
||||
// Back (same as front for the moment)
|
||||
t->push_back( osg::Vec2( right_x, base_y) ); // bottom right
|
||||
t->push_back( osg::Vec2( left_x, base_y) ); // bottom left
|
||||
t->push_back( osg::Vec2( left_x, top_y ) ); // top left
|
||||
t->push_back( osg::Vec2( right_x, top_y ) ); // top right
|
||||
|
||||
|
||||
// Right (same as left for the moment)
|
||||
t->push_back( osg::Vec2( front_x, base_y) ); // bottom right
|
||||
t->push_back( osg::Vec2( back_x, base_y) ); // bottom left
|
||||
@ -418,32 +418,32 @@ BuildingBoundingBoxCallback::computeBound(const Drawable& drawable) const
|
||||
t->push_back( osg::Vec2( front_x, top_y ) ); // top right
|
||||
|
||||
// ROOF
|
||||
if (building.pitched) {
|
||||
if (building.pitched) {
|
||||
// Use the entire height of the roof texture
|
||||
top_y = base_y + 16.0 * 3.0 / 1024.0;
|
||||
top_y = base_y + 16.0 * 3.0 / 1024.0;
|
||||
left_x = 512/1024.0 + 32.0 / 1024.0 * round(building.width / 6.0f);
|
||||
right_x = 512/1024.0;
|
||||
front_x = 480.0/1024.0;
|
||||
back_x = 512.0/1024.0;
|
||||
|
||||
|
||||
// Front
|
||||
t->push_back( osg::Vec2( right_x, base_y) ); // bottom right
|
||||
t->push_back( osg::Vec2( left_x, base_y) ); // bottom left
|
||||
t->push_back( osg::Vec2( left_x, top_y ) ); // top left
|
||||
t->push_back( osg::Vec2( right_x, top_y ) ); // top right
|
||||
|
||||
|
||||
// Left
|
||||
t->push_back( osg::Vec2( front_x, base_y) ); // bottom right
|
||||
t->push_back( osg::Vec2( back_x, base_y) ); // bottom left
|
||||
t->push_back( osg::Vec2( back_x, top_y ) ); // top left
|
||||
t->push_back( osg::Vec2( front_x, top_y ) ); // top right
|
||||
|
||||
|
||||
// Back (same as front for the moment)
|
||||
t->push_back( osg::Vec2( right_x, base_y) ); // bottom right
|
||||
t->push_back( osg::Vec2( left_x, base_y) ); // bottom left
|
||||
t->push_back( osg::Vec2( left_x, top_y ) ); // top left
|
||||
t->push_back( osg::Vec2( right_x, top_y ) ); // top right
|
||||
|
||||
|
||||
// Right (same as left for the moment)
|
||||
t->push_back( osg::Vec2( front_x, base_y) ); // bottom right
|
||||
t->push_back( osg::Vec2( back_x, base_y) ); // bottom left
|
||||
@ -454,31 +454,31 @@ BuildingBoundingBoxCallback::computeBound(const Drawable& drawable) const
|
||||
left_x = 640.0/1024.0;
|
||||
right_x = 512.0/1024.0;
|
||||
// Use the entire height of the roof texture
|
||||
top_y = base_y + 16.0 * 3.0 / 1024.0;
|
||||
|
||||
top_y = base_y + 16.0 * 3.0 / 1024.0;
|
||||
|
||||
// Flat roofs still have 4 surfaces, so we need to set the textures
|
||||
for (int i=0; i<4; ++i) {
|
||||
for (int i=0; i<4; ++i) {
|
||||
t->push_back( osg::Vec2( right_x, base_y) ); // bottom right
|
||||
t->push_back( osg::Vec2( left_x, base_y) ); // bottom left
|
||||
t->push_back( osg::Vec2( left_x, top_y ) ); // top left
|
||||
t->push_back( osg::Vec2( right_x, top_y ) ); // top right
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (building.type == SGBuildingBin::MEDIUM)
|
||||
|
||||
if (building.type == SGBuildingBin::MEDIUM)
|
||||
{
|
||||
int column = ((int) (mt_rand(&seed) * 1000)) % 5;
|
||||
int column = ((int) (mt_rand(&seed) * 1000)) % 5;
|
||||
float base_y = 288 / 1024.0;
|
||||
float top_y = base_y + 16.0 * (float) building.floors / 1024.0;
|
||||
float left_x = column * 192.0 /1024.0 + 32.0 / 1024.0 * round((float) building.width / 10.0f);
|
||||
float right_x = column * 192.0 /1024.0;
|
||||
|
||||
// BASEMENT - uses the baseline texture
|
||||
for (unsigned int i = 0; i < 16; i++) {
|
||||
t->push_back( osg::Vec2( left_x, base_y) );
|
||||
}
|
||||
for (unsigned int i = 0; i < 16; i++) {
|
||||
t->push_back( osg::Vec2( left_x, base_y) );
|
||||
}
|
||||
|
||||
// MAIN BODY
|
||||
// Front
|
||||
@ -486,19 +486,19 @@ BuildingBoundingBoxCallback::computeBound(const Drawable& drawable) const
|
||||
t->push_back( osg::Vec2( left_x, base_y) ); // bottom left
|
||||
t->push_back( osg::Vec2( left_x, top_y ) ); // top left
|
||||
t->push_back( osg::Vec2( right_x, top_y ) ); // top right
|
||||
|
||||
|
||||
// Left
|
||||
t->push_back( osg::Vec2( right_x, base_y) ); // bottom right
|
||||
t->push_back( osg::Vec2( left_x, base_y) ); // bottom left
|
||||
t->push_back( osg::Vec2( left_x, top_y ) ); // top left
|
||||
t->push_back( osg::Vec2( right_x, top_y ) ); // top right
|
||||
|
||||
|
||||
// Back (same as front for the moment)
|
||||
t->push_back( osg::Vec2( right_x, base_y) ); // bottom right
|
||||
t->push_back( osg::Vec2( left_x, base_y) ); // bottom left
|
||||
t->push_back( osg::Vec2( left_x, top_y ) ); // top left
|
||||
t->push_back( osg::Vec2( right_x, top_y ) ); // top right
|
||||
|
||||
|
||||
// Right (same as left for the moment)
|
||||
t->push_back( osg::Vec2( right_x, base_y) ); // bottom right
|
||||
t->push_back( osg::Vec2( left_x, base_y) ); // bottom left
|
||||
@ -506,30 +506,30 @@ BuildingBoundingBoxCallback::computeBound(const Drawable& drawable) const
|
||||
t->push_back( osg::Vec2( right_x, top_y ) ); // top right
|
||||
|
||||
// ROOF
|
||||
if (building.pitched) {
|
||||
if (building.pitched) {
|
||||
base_y = 288.0/1024.0;
|
||||
top_y = 576.0/1024.0;
|
||||
left_x = 960.0/1024.0;
|
||||
right_x = 1.0;
|
||||
|
||||
|
||||
// Front
|
||||
t->push_back( osg::Vec2( right_x, base_y) ); // bottom right
|
||||
t->push_back( osg::Vec2( left_x, base_y) ); // bottom left
|
||||
t->push_back( osg::Vec2( left_x, top_y ) ); // top left
|
||||
t->push_back( osg::Vec2( right_x, top_y ) ); // top right
|
||||
|
||||
|
||||
// Left
|
||||
t->push_back( osg::Vec2( right_x, base_y) ); // bottom right
|
||||
t->push_back( osg::Vec2( left_x, base_y) ); // bottom left
|
||||
t->push_back( osg::Vec2( left_x, top_y ) ); // top left
|
||||
t->push_back( osg::Vec2( right_x, top_y ) ); // top right
|
||||
|
||||
|
||||
// Back (same as front for the moment)
|
||||
t->push_back( osg::Vec2( right_x, base_y) ); // bottom right
|
||||
t->push_back( osg::Vec2( left_x, base_y) ); // bottom left
|
||||
t->push_back( osg::Vec2( left_x, top_y ) ); // top left
|
||||
t->push_back( osg::Vec2( right_x, top_y ) ); // top right
|
||||
|
||||
|
||||
// Right (same as left for the moment)
|
||||
t->push_back( osg::Vec2( right_x, base_y) ); // bottom right
|
||||
t->push_back( osg::Vec2( left_x, base_y) ); // bottom left
|
||||
@ -541,9 +541,9 @@ BuildingBoundingBoxCallback::computeBound(const Drawable& drawable) const
|
||||
top_y = 576.0/1024.0;
|
||||
left_x = column * 192.0 /1024.0;
|
||||
right_x = (column + 1)* 192.0 /1024.0;
|
||||
|
||||
|
||||
// Flat roofs still have 4 surfaces
|
||||
for (int i=0; i<4; ++i) {
|
||||
for (int i=0; i<4; ++i) {
|
||||
t->push_back( osg::Vec2( right_x, base_y) ); // bottom right
|
||||
t->push_back( osg::Vec2( left_x, base_y) ); // bottom left
|
||||
t->push_back( osg::Vec2( left_x, top_y ) ); // top left
|
||||
@ -554,16 +554,16 @@ BuildingBoundingBoxCallback::computeBound(const Drawable& drawable) const
|
||||
|
||||
if (building.type == SGBuildingBin::LARGE)
|
||||
{
|
||||
int column = ((int) (mt_rand(&seed) * 1000)) % 8;
|
||||
int column = ((int) (mt_rand(&seed) * 1000)) % 8;
|
||||
float base_y = 576 / 1024.0;
|
||||
float top_y = base_y + 16.0 * (float) building.floors / 1024.0;
|
||||
float left_x = column * 128.0 /1024.0 + 32.0 / 1024.0 * round((float) building.width / 20.0f);
|
||||
float right_x = column * 128.0 /1024.0;
|
||||
float right_x = column * 128.0 /1024.0;
|
||||
|
||||
// BASEMENT - uses the baseline texture
|
||||
for (unsigned int i = 0; i < 16; i++) {
|
||||
t->push_back( osg::Vec2( left_x, base_y) );
|
||||
}
|
||||
for (unsigned int i = 0; i < 16; i++) {
|
||||
t->push_back( osg::Vec2( left_x, base_y) );
|
||||
}
|
||||
|
||||
// MAIN BODY
|
||||
// Front
|
||||
@ -571,19 +571,19 @@ BuildingBoundingBoxCallback::computeBound(const Drawable& drawable) const
|
||||
t->push_back( osg::Vec2( left_x, base_y) ); // bottom left
|
||||
t->push_back( osg::Vec2( left_x, top_y ) ); // top left
|
||||
t->push_back( osg::Vec2( right_x, top_y ) ); // top right
|
||||
|
||||
|
||||
// Left
|
||||
t->push_back( osg::Vec2( right_x, base_y) ); // bottom right
|
||||
t->push_back( osg::Vec2( left_x, base_y) ); // bottom left
|
||||
t->push_back( osg::Vec2( left_x, top_y ) ); // top left
|
||||
t->push_back( osg::Vec2( right_x, top_y ) ); // top right
|
||||
|
||||
|
||||
// Back (same as front for the moment)
|
||||
t->push_back( osg::Vec2( right_x, base_y) ); // bottom right
|
||||
t->push_back( osg::Vec2( left_x, base_y) ); // bottom left
|
||||
t->push_back( osg::Vec2( left_x, top_y ) ); // top left
|
||||
t->push_back( osg::Vec2( right_x, top_y ) ); // top right
|
||||
|
||||
|
||||
// Right (same as left for the moment)
|
||||
t->push_back( osg::Vec2( right_x, base_y) ); // bottom right
|
||||
t->push_back( osg::Vec2( left_x, base_y) ); // bottom left
|
||||
@ -591,7 +591,7 @@ BuildingBoundingBoxCallback::computeBound(const Drawable& drawable) const
|
||||
t->push_back( osg::Vec2( right_x, top_y ) ); // top right
|
||||
|
||||
// ROOF
|
||||
if (building.pitched) {
|
||||
if (building.pitched) {
|
||||
base_y = 896/1024.0;
|
||||
top_y = 1.0;
|
||||
// Front
|
||||
@ -599,19 +599,19 @@ BuildingBoundingBoxCallback::computeBound(const Drawable& drawable) const
|
||||
t->push_back( osg::Vec2( left_x, base_y) ); // bottom left
|
||||
t->push_back( osg::Vec2( left_x, top_y ) ); // top left
|
||||
t->push_back( osg::Vec2( right_x, top_y ) ); // top right
|
||||
|
||||
|
||||
// Left
|
||||
t->push_back( osg::Vec2( right_x, base_y) ); // bottom right
|
||||
t->push_back( osg::Vec2( left_x, base_y) ); // bottom left
|
||||
t->push_back( osg::Vec2( left_x, top_y ) ); // top left
|
||||
t->push_back( osg::Vec2( right_x, top_y ) ); // top right
|
||||
|
||||
|
||||
// Back (same as front for the moment)
|
||||
t->push_back( osg::Vec2( right_x, base_y) ); // bottom right
|
||||
t->push_back( osg::Vec2( left_x, base_y) ); // bottom left
|
||||
t->push_back( osg::Vec2( left_x, top_y ) ); // top left
|
||||
t->push_back( osg::Vec2( right_x, top_y ) ); // top right
|
||||
|
||||
|
||||
// Right (same as left for the moment)
|
||||
t->push_back( osg::Vec2( right_x, base_y) ); // bottom right
|
||||
t->push_back( osg::Vec2( left_x, base_y) ); // bottom left
|
||||
@ -621,9 +621,9 @@ BuildingBoundingBoxCallback::computeBound(const Drawable& drawable) const
|
||||
// Flat roof
|
||||
base_y = 896/1024.0;
|
||||
top_y = 1.0;
|
||||
|
||||
|
||||
// Flat roofs still have 4 surfaces
|
||||
for (int i=0; i<4; ++i) {
|
||||
for (int i=0; i<4; ++i) {
|
||||
t->push_back( osg::Vec2( right_x, base_y) ); // bottom right
|
||||
t->push_back( osg::Vec2( left_x, base_y) ); // bottom left
|
||||
t->push_back( osg::Vec2( left_x, top_y ) ); // top left
|
||||
@ -632,7 +632,7 @@ BuildingBoundingBoxCallback::computeBound(const Drawable& drawable) const
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Set the vertex, texture and normals. Colors will be set per-instance
|
||||
// later.
|
||||
sharedGeometry->setVertexArray(v);
|
||||
@ -640,88 +640,88 @@ BuildingBoundingBoxCallback::computeBound(const Drawable& drawable) const
|
||||
sharedGeometry->setNormalArray(n);
|
||||
}
|
||||
}
|
||||
|
||||
void SGBuildingBin::insert(SGVec3f p, float r, BuildingType type) {
|
||||
|
||||
|
||||
void SGBuildingBin::insert(SGVec3f p, float r, BuildingType type) {
|
||||
|
||||
if (type == SGBuildingBin::SMALL) {
|
||||
smallBuildingLocations.push_back(BuildingInstance(p, r, &smallBuildings, smallSharedGeometry));
|
||||
smallBuildingLocations.push_back(BuildingInstance(p, r, &smallBuildings, smallSharedGeometry));
|
||||
}
|
||||
|
||||
|
||||
if (type == SGBuildingBin::MEDIUM) {
|
||||
mediumBuildingLocations.push_back(BuildingInstance(p, r, &mediumBuildings, mediumSharedGeometry));
|
||||
mediumBuildingLocations.push_back(BuildingInstance(p, r, &mediumBuildings, mediumSharedGeometry));
|
||||
}
|
||||
|
||||
if (type == SGBuildingBin::LARGE) {
|
||||
largeBuildingLocations.push_back(BuildingInstance(p, r, &largeBuildings, largeSharedGeometry));
|
||||
}
|
||||
largeBuildingLocations.push_back(BuildingInstance(p, r, &largeBuildings, largeSharedGeometry));
|
||||
}
|
||||
}
|
||||
|
||||
int SGBuildingBin::getNumBuildings() {
|
||||
return smallBuildingLocations.size() + mediumBuildingLocations.size() + largeBuildingLocations.size();
|
||||
return smallBuildingLocations.size() + mediumBuildingLocations.size() + largeBuildingLocations.size();
|
||||
}
|
||||
|
||||
bool SGBuildingBin::checkMinDist (SGVec3f p, float radius) {
|
||||
|
||||
bool SGBuildingBin::checkMinDist (SGVec3f p, float radius) {
|
||||
BuildingInstanceList::iterator iter;
|
||||
|
||||
|
||||
float r = (radius + smallBuildingMaxRadius) * (radius + smallBuildingMaxRadius);
|
||||
for (iter = smallBuildingLocations.begin(); iter != smallBuildingLocations.end(); ++iter) {
|
||||
if (iter->getDistSqr(p) < r) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
r = (radius + mediumBuildingMaxRadius) * (radius + mediumBuildingMaxRadius);
|
||||
for (iter = mediumBuildingLocations.begin(); iter != mediumBuildingLocations.end(); ++iter) {
|
||||
if (iter->getDistSqr(p) < r) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
r = (radius + largeBuildingMaxRadius) * (radius + largeBuildingMaxRadius);
|
||||
for (iter = largeBuildingLocations.begin(); iter != largeBuildingLocations.end(); ++iter) {
|
||||
if (iter->getDistSqr(p) < r) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
SGBuildingBin::BuildingType SGBuildingBin::getBuildingType(float roll) {
|
||||
|
||||
|
||||
if (roll < smallBuildingFraction) {
|
||||
return SGBuildingBin::SMALL;
|
||||
return SGBuildingBin::SMALL;
|
||||
}
|
||||
|
||||
|
||||
if (roll < (smallBuildingFraction + mediumBuildingFraction)) {
|
||||
return SGBuildingBin::MEDIUM;
|
||||
}
|
||||
|
||||
return SGBuildingBin::LARGE;
|
||||
|
||||
return SGBuildingBin::LARGE;
|
||||
}
|
||||
|
||||
float SGBuildingBin::getBuildingMaxRadius(BuildingType type) {
|
||||
|
||||
|
||||
if (type == SGBuildingBin::SMALL) return smallBuildingMaxRadius;
|
||||
if (type == SGBuildingBin::MEDIUM) return mediumBuildingMaxRadius;
|
||||
if (type == SGBuildingBin::LARGE) return largeBuildingMaxRadius;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
float SGBuildingBin::getBuildingMaxDepth(BuildingType type) {
|
||||
|
||||
|
||||
if (type == SGBuildingBin::SMALL) return smallBuildingMaxDepth;
|
||||
if (type == SGBuildingBin::MEDIUM) return mediumBuildingMaxDepth;
|
||||
if (type == SGBuildingBin::LARGE) return largeBuildingMaxDepth;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
ref_ptr<Group> SGBuildingBin::createBuildingsGroup(Matrix transInv, const SGReaderWriterOptions* options)
|
||||
{
|
||||
ref_ptr<Effect> effect;
|
||||
EffectMap::iterator iter = buildingEffectMap.find(texture);
|
||||
EffectMap::iterator iter = buildingEffectMap.find(*texture);
|
||||
|
||||
if ((iter == buildingEffectMap.end())||
|
||||
(!iter->second.lock(effect)))
|
||||
@ -731,27 +731,27 @@ BuildingBoundingBoxCallback::computeBound(const Drawable& drawable) const
|
||||
SGPropertyNode* params = makeChild(effectProp, "parameters");
|
||||
// Main texture - n=0
|
||||
params->getChild("texture", 0, true)->getChild("image", 0, true)
|
||||
->setStringValue(texture);
|
||||
->setStringValue(*texture);
|
||||
|
||||
// Light map - n=3
|
||||
params->getChild("texture", 3, true)->getChild("image", 0, true)
|
||||
->setStringValue(lightMap);
|
||||
|
||||
->setStringValue(*lightMap);
|
||||
|
||||
effect = makeEffect(effectProp, true, options);
|
||||
if (iter == buildingEffectMap.end())
|
||||
buildingEffectMap.insert(EffectMap::value_type(texture, effect));
|
||||
buildingEffectMap.insert(EffectMap::value_type(*texture, effect));
|
||||
else
|
||||
iter->second = effect; // update existing, but empty observer
|
||||
}
|
||||
|
||||
|
||||
ref_ptr<Group> group = new osg::Group();
|
||||
|
||||
// Now, create a quadbuilding for the buildings.
|
||||
|
||||
BuildingInstanceList locs[] = { smallBuildingLocations,
|
||||
SGBuildingBin::mediumBuildingLocations,
|
||||
|
||||
// Now, create a quadbuilding for the buildings.
|
||||
|
||||
BuildingInstanceList locs[] = { smallBuildingLocations,
|
||||
SGBuildingBin::mediumBuildingLocations,
|
||||
SGBuildingBin::largeBuildingLocations };
|
||||
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
// Create a quad tree. Only small and medium buildings are faded out.
|
||||
@ -759,7 +759,7 @@ BuildingBoundingBoxCallback::computeBound(const Drawable& drawable) const
|
||||
quadbuilding(GetBuildingCoord(), AddBuildingLeafObject(),
|
||||
SG_BUILDING_QUAD_TREE_DEPTH,
|
||||
MakeBuildingLeaf(buildingRange, effect, (i != 2)));
|
||||
|
||||
|
||||
// Transform building positions from the "geocentric" positions we
|
||||
// get from the scenery polys into the local Z-up coordinate
|
||||
// system.
|
||||
@ -773,15 +773,15 @@ BuildingBoundingBoxCallback::computeBound(const Drawable& drawable) const
|
||||
for (size_t j = 0; j < quadbuilding.getRoot()->getNumChildren(); ++j)
|
||||
group->addChild(quadbuilding.getRoot()->getChild(j));
|
||||
}
|
||||
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
|
||||
// We may end up with a quadtree with many empty leaves. One might say
|
||||
// that we should avoid constructing the leaves in the first place,
|
||||
// but this node visitor tries to clean up after the fact.
|
||||
struct QuadTreeCleaner : public osg::NodeVisitor
|
||||
{
|
||||
{
|
||||
QuadTreeCleaner() : NodeVisitor(NodeVisitor::TRAVERSE_ALL_CHILDREN)
|
||||
{
|
||||
}
|
||||
@ -815,31 +815,32 @@ BuildingBoundingBoxCallback::computeBound(const Drawable& drawable) const
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// This actually returns a MatrixTransform node. If we rotate the whole
|
||||
// forest into the local Z-up coordinate system we can reuse the
|
||||
// primitive building geometry for all the forests of the same type.
|
||||
osg::Group* createRandomBuildings(SGBuildingBinList buildings, const osg::Matrix& transform,
|
||||
osg::Group* createRandomBuildings(SGBuildingBinList& buildings, const osg::Matrix& transform,
|
||||
const SGReaderWriterOptions* options)
|
||||
{
|
||||
Matrix transInv = Matrix::inverse(transform);
|
||||
static Matrix ident;
|
||||
// Set up some shared structures.
|
||||
MatrixTransform* mt = new MatrixTransform(transform);
|
||||
SGBuildingBinList::iterator i;
|
||||
|
||||
SGBuildingBin* bin = NULL;
|
||||
|
||||
BOOST_FOREACH(bin, buildings)
|
||||
{
|
||||
for (i = buildings.begin(); i != buildings.end(); ++i) {
|
||||
SGBuildingBin* bin = *i;
|
||||
ref_ptr<Group> group = bin->createBuildingsGroup(transInv, options);
|
||||
|
||||
for (size_t i = 0; i < group->getNumChildren(); ++i)
|
||||
mt->addChild(group->getChild(i));
|
||||
|
||||
delete bin;
|
||||
}
|
||||
|
||||
|
||||
for (size_t j = 0; j < group->getNumChildren(); ++j) {
|
||||
mt->addChild(group->getChild(j));
|
||||
}
|
||||
|
||||
delete bin;
|
||||
}
|
||||
|
||||
buildings.clear();
|
||||
|
||||
QuadTreeCleaner cleaner;
|
||||
mt->accept(cleaner);
|
||||
return mt;
|
||||
|
@ -56,9 +56,9 @@ class SGBuildingBin {
|
||||
public:
|
||||
|
||||
// Number of buildings to auto-generate. Individual
|
||||
// building instances are taken from this set.
|
||||
// building instances are taken from this set.
|
||||
static const unsigned int BUILDING_SET_SIZE = 200;
|
||||
|
||||
|
||||
static const unsigned int QUADS_PER_BUILDING = 12;
|
||||
static const unsigned int VERTICES_PER_BUILDING = 4 * QUADS_PER_BUILDING;
|
||||
static const unsigned int VERTICES_PER_BUILDING_SET = BUILDING_SET_SIZE * VERTICES_PER_BUILDING;
|
||||
@ -66,21 +66,21 @@ public:
|
||||
enum BuildingType {
|
||||
SMALL = 0,
|
||||
MEDIUM,
|
||||
LARGE };
|
||||
|
||||
LARGE };
|
||||
|
||||
private:
|
||||
|
||||
struct Building {
|
||||
Building(BuildingType t, float w, float d, float h, int f, bool pitch) :
|
||||
type(t),
|
||||
width(w),
|
||||
depth(d),
|
||||
height(h),
|
||||
type(t),
|
||||
width(w),
|
||||
depth(d),
|
||||
height(h),
|
||||
floors(f),
|
||||
pitched(pitch),
|
||||
pitched(pitch),
|
||||
radius(std::max(d, 0.5f*w))
|
||||
{ }
|
||||
|
||||
|
||||
BuildingType type;
|
||||
float width;
|
||||
float depth;
|
||||
@ -88,22 +88,22 @@ private:
|
||||
int floors;
|
||||
bool pitched;
|
||||
float radius;
|
||||
|
||||
|
||||
float getFootprint() {
|
||||
return radius;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// The set of buildings that are instantiated
|
||||
typedef std::vector<Building> BuildingList;
|
||||
BuildingList smallBuildings;
|
||||
BuildingList mediumBuildings;
|
||||
BuildingList largeBuildings;
|
||||
|
||||
std::string material_name;
|
||||
std::string texture;
|
||||
std::string lightMap;
|
||||
|
||||
|
||||
std::string* material_name;
|
||||
std::string* texture;
|
||||
std::string* lightMap;
|
||||
|
||||
// Fraction of buildings of this type
|
||||
float smallBuildingFraction;
|
||||
float mediumBuildingFraction;
|
||||
@ -112,20 +112,20 @@ private:
|
||||
float smallBuildingMaxRadius;
|
||||
float mediumBuildingMaxRadius;
|
||||
float largeBuildingMaxRadius;
|
||||
|
||||
|
||||
// The maximum depth of each building type
|
||||
float smallBuildingMaxDepth;
|
||||
float mediumBuildingMaxDepth;
|
||||
float largeBuildingMaxDepth;
|
||||
|
||||
|
||||
// Visibility range for buildings
|
||||
float buildingRange;
|
||||
|
||||
|
||||
// Shared geometries of the building set
|
||||
ref_ptr<Geometry> smallSharedGeometry;
|
||||
ref_ptr<Geometry> mediumSharedGeometry;
|
||||
ref_ptr<Geometry> largeSharedGeometry;
|
||||
|
||||
|
||||
struct BuildingInstance {
|
||||
BuildingInstance(SGVec3f p, float r, const BuildingList* bl, ref_ptr<Geometry> sg) :
|
||||
position(p),
|
||||
@ -133,26 +133,26 @@ private:
|
||||
buildingList(bl),
|
||||
sharedGeometry(sg)
|
||||
{ }
|
||||
|
||||
|
||||
BuildingInstance(SGVec3f p, BuildingInstance b) :
|
||||
position(p),
|
||||
rotation(b.rotation),
|
||||
buildingList(b.buildingList),
|
||||
sharedGeometry(b.sharedGeometry)
|
||||
{ }
|
||||
|
||||
{ }
|
||||
|
||||
SGVec3f position;
|
||||
float rotation;
|
||||
|
||||
|
||||
// References to allow the QuadTreeBuilder to work
|
||||
const BuildingList* buildingList;
|
||||
ref_ptr<Geometry> sharedGeometry;
|
||||
|
||||
ref_ptr<Geometry> sharedGeometry;
|
||||
|
||||
SGVec3f getPosition() { return position; }
|
||||
float getRotation() { return rotation; }
|
||||
|
||||
|
||||
float getDistSqr(SGVec3f p) {
|
||||
return distSqr(p, position);
|
||||
return distSqr(p, position);
|
||||
}
|
||||
|
||||
const osg::Vec4f getColorValue() {
|
||||
@ -161,42 +161,42 @@ private:
|
||||
};
|
||||
|
||||
// Information for an instance of a building - position and orientation
|
||||
typedef std::vector<BuildingInstance> BuildingInstanceList;
|
||||
typedef std::vector<BuildingInstance> BuildingInstanceList;
|
||||
BuildingInstanceList smallBuildingLocations;
|
||||
BuildingInstanceList mediumBuildingLocations;
|
||||
BuildingInstanceList largeBuildingLocations;
|
||||
|
||||
public:
|
||||
|
||||
public:
|
||||
|
||||
SGBuildingBin(const SGMaterial *mat);
|
||||
|
||||
|
||||
~SGBuildingBin() {
|
||||
smallBuildings.clear();
|
||||
smallBuildings.clear();
|
||||
mediumBuildings.clear();
|
||||
largeBuildings.clear();
|
||||
smallBuildingLocations.clear();
|
||||
mediumBuildingLocations.clear();
|
||||
largeBuildingLocations.clear();
|
||||
}
|
||||
|
||||
|
||||
void insert(SGVec3f p, float r, BuildingType type);
|
||||
int getNumBuildings();
|
||||
|
||||
|
||||
bool checkMinDist (SGVec3f p, float radius);
|
||||
|
||||
std::string getMaterialName() { return material_name; }
|
||||
|
||||
|
||||
std::string* getMaterialName() { return material_name; }
|
||||
|
||||
BuildingType getBuildingType(float roll);
|
||||
|
||||
|
||||
float getBuildingMaxRadius(BuildingType);
|
||||
float getBuildingMaxDepth(BuildingType);
|
||||
|
||||
|
||||
// Helper classes for creating the quad tree
|
||||
struct MakeBuildingLeaf
|
||||
{
|
||||
MakeBuildingLeaf(float range, Effect* effect, bool fade) :
|
||||
_range(range), _effect(effect), _fade_out(fade) {}
|
||||
|
||||
|
||||
MakeBuildingLeaf(const MakeBuildingLeaf& rhs) :
|
||||
_range(rhs._range), _effect(rhs._effect), _fade_out(rhs._fade_out)
|
||||
{}
|
||||
@ -204,30 +204,30 @@ public:
|
||||
LOD* operator() () const
|
||||
{
|
||||
LOD* result = new LOD;
|
||||
|
||||
if (_fade_out) {
|
||||
|
||||
if (_fade_out) {
|
||||
// Create a series of LOD nodes so buidling cover decreases
|
||||
// gradually with distance from _range to 2*_range
|
||||
for (float i = 0.0; i < SG_BUILDING_FADE_OUT_LEVELS; i++)
|
||||
{
|
||||
{
|
||||
EffectGeode* geode = new EffectGeode;
|
||||
geode->setEffect(_effect.get());
|
||||
result->addChild(geode, 0, _range * (1.0 + i / (SG_BUILDING_FADE_OUT_LEVELS - 1.0)));
|
||||
result->addChild(geode, 0, _range * (1.0 + i / (SG_BUILDING_FADE_OUT_LEVELS - 1.0)));
|
||||
}
|
||||
} else {
|
||||
// No fade-out, so all are visible for 2X range
|
||||
EffectGeode* geode = new EffectGeode;
|
||||
geode->setEffect(_effect.get());
|
||||
result->addChild(geode, 0, 2.0 * _range);
|
||||
result->addChild(geode, 0, 2.0 * _range);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
float _range;
|
||||
ref_ptr<Effect> _effect;
|
||||
bool _fade_out;
|
||||
};
|
||||
|
||||
|
||||
struct AddBuildingLeafObject
|
||||
{
|
||||
Geometry* createNewBuildingGeometryInstance(const BuildingInstance& building) const
|
||||
@ -237,32 +237,32 @@ public:
|
||||
geom->setColorBinding(Geometry::BIND_PER_VERTEX);
|
||||
geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS));
|
||||
return geom;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void operator() (LOD* lod, const BuildingInstance& building) const
|
||||
{
|
||||
Geode* geode = static_cast<Geode*>(lod->getChild(int(building.position.x() * 10.0f) % lod->getNumChildren()));
|
||||
unsigned int numDrawables = geode->getNumDrawables();
|
||||
|
||||
unsigned int numDrawables = geode->getNumDrawables();
|
||||
|
||||
// Get the last geometry of to be added and check if there is space for
|
||||
// another building instance within it. This is done by checking
|
||||
// if the number of Color values matches the number of vertices.
|
||||
// The color array is used to store the position of a particular
|
||||
// instance.
|
||||
Geometry* geom;
|
||||
|
||||
|
||||
if (numDrawables == 0) {
|
||||
// Create a new copy of the shared geometry to instantiate
|
||||
geom = createNewBuildingGeometryInstance(building);
|
||||
geode->addDrawable(geom);
|
||||
} else {
|
||||
geom = static_cast<Geometry*>(geode->getDrawable(numDrawables - 1));
|
||||
geom = static_cast<Geometry*>(geode->getDrawable(numDrawables - 1));
|
||||
}
|
||||
|
||||
|
||||
// Check if this building is too close to any other others.
|
||||
DrawArrays* primSet = static_cast<DrawArrays*>(geom->getPrimitiveSet(0));
|
||||
Vec4Array* posArray = static_cast<Vec4Array*>(geom->getColorArray());
|
||||
|
||||
|
||||
// Now check if this geometry is full.
|
||||
if (posArray->size() >= static_cast<Vec3Array*>(geom->getVertexArray())->size()) {
|
||||
// This particular geometry is full, so we generate another
|
||||
@ -272,7 +272,7 @@ public:
|
||||
posArray = static_cast<Vec4Array*>(geom->getColorArray());
|
||||
SG_LOG(SG_TERRAIN, SG_DEBUG, "Added new geometry to building geod: " << geode->getNumDrawables());
|
||||
}
|
||||
|
||||
|
||||
// We now have a geometry with space for this new building.
|
||||
// Set the position and rotation
|
||||
osg::Vec4f c = osg::Vec4f(toOsg(building.position), building.rotation);
|
||||
@ -293,7 +293,7 @@ public:
|
||||
|
||||
typedef QuadTreeBuilder<LOD*, BuildingInstance, MakeBuildingLeaf, AddBuildingLeafObject,
|
||||
GetBuildingCoord> BuildingGeometryQuadtree;
|
||||
|
||||
|
||||
struct BuildingInstanceTransformer
|
||||
{
|
||||
BuildingInstanceTransformer(Matrix& mat_) : mat(mat_) {}
|
||||
@ -304,8 +304,8 @@ public:
|
||||
}
|
||||
Matrix mat;
|
||||
};
|
||||
|
||||
ref_ptr<Group> createBuildingsGroup(Matrix transInv, const SGReaderWriterOptions* options);
|
||||
|
||||
ref_ptr<Group> createBuildingsGroup(Matrix transInv, const SGReaderWriterOptions* options);
|
||||
|
||||
};
|
||||
|
||||
@ -313,7 +313,7 @@ public:
|
||||
typedef std::list<SGBuildingBin*> SGBuildingBinList;
|
||||
|
||||
|
||||
osg::Group* createRandomBuildings(SGBuildingBinList buildinglist, const osg::Matrix& transform,
|
||||
osg::Group* createRandomBuildings(SGBuildingBinList& buildinglist, const osg::Matrix& transform,
|
||||
const SGReaderWriterOptions* options);
|
||||
}
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user