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