#include "ShaderGeometry.hxx"
#include "SGBuildingBin.hxx"
-#define SG_BUILDING_QUAD_TREE_DEPTH 3
-#define SG_BUILDING_FADE_OUT_LEVELS 10
+#define SG_BUILDING_QUAD_TREE_DEPTH 2
+#define SG_BUILDING_FADE_OUT_LEVELS 4
using namespace osg;
typedef std::map<std::string, osg::observer_ptr<osg::StateSet> > BuildingStateSetMap;
static BuildingStateSetMap statesetmap;
+static int numBuildings;
void addBuildingToLeafGeode(Geode* geode, const SGBuildingBin::Building& building)
{
// Get or create geometry.
osg::ref_ptr<osg::Geometry> geom;
- osg::Vec3Array* v = new osg::Vec3Array;
- osg::Vec2Array* t = new osg::Vec2Array;
- osg::Vec4Array* c = new osg::Vec4Array; // single value
- osg::Vec3Array* n = new osg::Vec3Array;
+ osg::Vec3Array* v;
+ osg::Vec2Array* t;
+ osg::Vec4Array* c;
+ osg::Vec3Array* n;
if (geode->getNumDrawables() == 0) {
geom = new osg::Geometry;
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
- v->push_back( osg::Vec3( 0, cw, -10) * transformMat ); // bottom right
- v->push_back( osg::Vec3( 0, -cw, -10) * transformMat ); // bottom left
- v->push_back( osg::Vec3( 0, -cw, 0) * transformMat ); // top left
- v->push_back( osg::Vec3( 0, cw, 0) * transformMat ); // top right
+ v->push_back( osg::Vec3( 0, -cw, -10) * transformMat ); // bottom right
+ v->push_back( osg::Vec3( 0, cw, -10) * transformMat ); // bottom left
+ v->push_back( osg::Vec3( 0, cw, 0) * transformMat ); // top left
+ v->push_back( osg::Vec3( 0, -cw, 0) * transformMat ); // top right
for (int i=0; i<4; ++i)
- n->push_back( osg::Vec3(-1, 0, 0) * rotationMat ); // normal
+ n->push_back( osg::Vec3(1, 0, 0) * rotationMat ); // normal
// Left face
- v->push_back( osg::Vec3( 0, -cw, -10) * transformMat ); // bottom right
- v->push_back( osg::Vec3( cd, -cw, -10) * transformMat ); // bottom left
- v->push_back( osg::Vec3( cd, -cw, 0) * transformMat ); // top left
- v->push_back( osg::Vec3( 0, -cw, 0) * transformMat ); // top right
+ v->push_back( osg::Vec3( -cd, -cw, -10) * transformMat ); // bottom right
+ v->push_back( osg::Vec3( 0, -cw, -10) * transformMat ); // bottom left
+ v->push_back( osg::Vec3( 0, -cw, 0) * transformMat ); // top left
+ v->push_back( osg::Vec3( -cd, -cw, 0) * transformMat ); // top right
for (int i=0; i<4; ++i)
n->push_back( osg::Vec3(0, -1, 0) * rotationMat ); // normal
// Back face
- v->push_back( osg::Vec3( cd, -cw, -10) * transformMat ); // bottom right
- v->push_back( osg::Vec3( cd, cw, -10) * transformMat ); // bottom left
- v->push_back( osg::Vec3( cd, cw, 0) * transformMat ); // top left
- v->push_back( osg::Vec3( cd, -cw, 0) * transformMat ); // top right
+ v->push_back( osg::Vec3( -cd, cw, -10) * transformMat ); // bottom right
+ v->push_back( osg::Vec3( -cd, -cw, -10) * transformMat ); // bottom left
+ v->push_back( osg::Vec3( -cd, -cw, 0) * transformMat ); // top left
+ v->push_back( osg::Vec3( -cd, cw, 0) * transformMat ); // top right
for (int i=0; i<4; ++i)
- n->push_back( osg::Vec3(1, 0, 0) * rotationMat ); // normal
+ n->push_back( osg::Vec3(-1, 0, 0) * rotationMat ); // normal
// Right face
- v->push_back( osg::Vec3( cd, cw, -10) * transformMat ); // bottom right
- v->push_back( osg::Vec3( 0, cw, -10) * transformMat ); // bottom left
- v->push_back( osg::Vec3( 0, cw, 0) * transformMat ); // top left
- v->push_back( osg::Vec3( cd, cw, 0) * transformMat ); // top right
+ v->push_back( osg::Vec3( 0, cw, -10) * transformMat ); // bottom right
+ v->push_back( osg::Vec3( -cd, cw, -10) * transformMat ); // bottom left
+ v->push_back( osg::Vec3( -cd, cw, 0) * transformMat ); // top left
+ v->push_back( osg::Vec3( 0, cw, 0) * transformMat ); // top right
for (int i=0; i<4; ++i)
n->push_back( osg::Vec3(0, 1, 0) * rotationMat ); // normal
// MAIN BODY
// Front face
- v->push_back( osg::Vec3( 0, cw, 0) * transformMat ); // bottom right
- v->push_back( osg::Vec3( 0, -cw, 0) * transformMat ); // bottom left
- v->push_back( osg::Vec3( 0, -cw, ch) * transformMat ); // top left
- v->push_back( osg::Vec3( 0, cw, ch) * transformMat ); // top right
+ v->push_back( osg::Vec3( 0, -cw, 0) * transformMat ); // bottom right
+ v->push_back( osg::Vec3( 0, cw, 0) * transformMat ); // bottom left
+ v->push_back( osg::Vec3( 0, cw, ch) * transformMat ); // top left
+ v->push_back( osg::Vec3( 0, -cw, ch) * transformMat ); // top right
for (int i=0; i<4; ++i)
- n->push_back( osg::Vec3(-1, 0, 0) * rotationMat ); // normal
+ n->push_back( osg::Vec3(1, 0, 0) * rotationMat ); // normal
// Left face
- v->push_back( osg::Vec3( 0, -cw, 0) * transformMat ); // bottom right
- v->push_back( osg::Vec3( cd, -cw, 0) * transformMat ); // bottom left
- v->push_back( osg::Vec3( cd, -cw, ch) * transformMat ); // top left
- v->push_back( osg::Vec3( 0, -cw, ch) * transformMat ); // top right
+ v->push_back( osg::Vec3( -cd, -cw, 0) * transformMat ); // bottom right
+ v->push_back( osg::Vec3( 0, -cw, 0) * transformMat ); // bottom left
+ v->push_back( osg::Vec3( 0, -cw, ch) * transformMat ); // top left
+ v->push_back( osg::Vec3( -cd, -cw, ch) * transformMat ); // top right
for (int i=0; i<4; ++i)
n->push_back( osg::Vec3(0, -1, 0) * rotationMat ); // normal
// Back face
- v->push_back( osg::Vec3( cd, -cw, 0) * transformMat ); // bottom right
- v->push_back( osg::Vec3( cd, cw, 0) * transformMat ); // bottom left
- v->push_back( osg::Vec3( cd, cw, ch) * transformMat ); // top left
- v->push_back( osg::Vec3( cd, -cw, ch) * transformMat ); // top right
+ v->push_back( osg::Vec3( -cd, cw, 0) * transformMat ); // bottom right
+ v->push_back( osg::Vec3( -cd, -cw, 0) * transformMat ); // bottom left
+ v->push_back( osg::Vec3( -cd, -cw, ch) * transformMat ); // top left
+ v->push_back( osg::Vec3( -cd, cw, ch) * transformMat ); // top right
for (int i=0; i<4; ++i)
- n->push_back( osg::Vec3(1, 0, 0) * rotationMat ); // normal
+ n->push_back( osg::Vec3(-1, 0, 0) * rotationMat ); // normal
// Right face
- v->push_back( osg::Vec3( cd, cw, 0) * transformMat ); // bottom right
- v->push_back( osg::Vec3( 0, cw, 0) * transformMat ); // bottom left
- v->push_back( osg::Vec3( 0, cw, ch) * transformMat ); // top left
- v->push_back( osg::Vec3( cd, cw, ch) * transformMat ); // top right
+ v->push_back( osg::Vec3( 0, cw, 0) * transformMat ); // bottom right
+ v->push_back( osg::Vec3( -cd, cw, 0) * transformMat ); // bottom left
+ v->push_back( osg::Vec3( -cd, cw, ch) * transformMat ); // top left
+ v->push_back( osg::Vec3( 0, cw, ch) * transformMat ); // top right
for (int i=0; i<4; ++i)
n->push_back( osg::Vec3(0, 1, 0) * rotationMat ); // normal
if (building.pitched) {
// Front pitched roof
- v->push_back( osg::Vec3( 0, cw, ch) * transformMat ); // bottom right
- v->push_back( osg::Vec3( 0, -cw, ch) * transformMat ); // bottom left
- v->push_back( osg::Vec3(0.5*cd, -cw, ch+3) * transformMat ); // top left
- v->push_back( osg::Vec3(0.5*cd, cw, ch+3) * transformMat ); // top right
+ v->push_back( osg::Vec3( 0, -cw, ch) * transformMat ); // bottom right
+ v->push_back( osg::Vec3( 0, cw, ch) * transformMat ); // bottom left
+ v->push_back( osg::Vec3(-0.5*cd, cw, ch+3) * transformMat ); // top left
+ v->push_back( osg::Vec3(-0.5*cd, -cw, ch+3) * transformMat ); // top right
for (int i=0; i<4; ++i)
- n->push_back( osg::Vec3(-0.707, 0, 0.707) * rotationMat ); // normal
+ n->push_back( osg::Vec3(0.707, 0, 0.707) * rotationMat ); // normal
// Left pitched roof
- v->push_back( osg::Vec3( 0, -cw, ch) * transformMat ); // bottom right
- v->push_back( osg::Vec3( cd, -cw, ch) * transformMat ); // bottom left
- v->push_back( osg::Vec3(0.5*cd, -cw, ch+3) * transformMat ); // top left
- v->push_back( osg::Vec3(0.5*cd, -cw, ch+3) * transformMat ); // top right
+ v->push_back( osg::Vec3( -cd, -cw, ch) * transformMat ); // bottom right
+ v->push_back( osg::Vec3( 0, -cw, ch) * transformMat ); // bottom left
+ v->push_back( osg::Vec3(-0.5*cd, -cw, ch+3) * transformMat ); // top left
+ v->push_back( osg::Vec3(-0.5*cd, -cw, ch+3) * transformMat ); // top right
for (int i=0; i<4; ++i)
n->push_back( osg::Vec3(0, -1, 0) * rotationMat ); // normal
// Back pitched roof
- v->push_back( osg::Vec3( cd, -cw, ch) * transformMat ); // bottom right
- v->push_back( osg::Vec3( cd, cw, ch) * transformMat ); // bottom left
- v->push_back( osg::Vec3(0.5*cd, cw, ch+3) * transformMat ); // top left
- v->push_back( osg::Vec3(0.5*cd, -cw, ch+3) * transformMat ); // top right
+ v->push_back( osg::Vec3( -cd, cw, ch) * transformMat ); // bottom right
+ v->push_back( osg::Vec3( -cd, -cw, ch) * transformMat ); // bottom left
+ v->push_back( osg::Vec3(-0.5*cd, -cw, ch+3) * transformMat ); // top left
+ v->push_back( osg::Vec3(-0.5*cd, cw, ch+3) * transformMat ); // top right
for (int i=0; i<4; ++i)
- n->push_back( osg::Vec3(0.707, 0, 0.707) * rotationMat ); // normal
+ n->push_back( osg::Vec3(-0.707, 0, 0.707) * rotationMat ); // normal
// Right pitched roof
- v->push_back( osg::Vec3( cd, cw, ch) * transformMat ); // bottom right
- v->push_back( osg::Vec3( 0, cw, ch) * transformMat ); // bottom left
- v->push_back( osg::Vec3(0.5*cd, cw, ch+3) * transformMat ); // top left
- v->push_back( osg::Vec3(0.5*cd, cw, ch+3) * transformMat ); // top right
+ v->push_back( osg::Vec3( 0, cw, ch) * transformMat ); // bottom right
+ v->push_back( osg::Vec3( -cd, cw, ch) * transformMat ); // bottom left
+ v->push_back( osg::Vec3(-0.5*cd, cw, ch+3) * transformMat ); // top left
+ v->push_back( osg::Vec3(-0.5*cd, cw, ch+3) * transformMat ); // top right
for (int i=0; i<4; ++i)
n->push_back( osg::Vec3(0, 1, 0) * rotationMat ); // normal
} else {
// Top face
- v->push_back( osg::Vec3( 0, cw, ch) * transformMat ); // bottom right
- v->push_back( osg::Vec3( 0, -cw, ch) * transformMat ); // bottom left
- v->push_back( osg::Vec3( cd, -cw, ch) * transformMat ); // top left
- v->push_back( osg::Vec3( cd, cw, ch) * transformMat ); // top right
+ v->push_back( osg::Vec3( 0, -cw, ch) * transformMat ); // bottom right
+ v->push_back( osg::Vec3( 0, cw, ch) * transformMat ); // bottom left
+ v->push_back( osg::Vec3( -cd, cw, ch) * transformMat ); // top left
+ v->push_back( osg::Vec3( -cd, -cw, ch) * transformMat ); // top right
for (int i=0; i<4; ++i)
n->push_back( osg::Vec3( 0, 0, 1) * rotationMat ); // normal
int row = ((int) (mt_rand(&seed) * 1000)) % 5;
float base_y = (float) row * 16.0 * 3.0 / 1024.0;
float top_y = base_y + 16.0 * (float) building.floors / 1024.0;
- float left_x = 0.0f;
- float right_x = 32.0 / 1024.0 * round((float) building.width / 6.0f);
+ float left_x = 32.0 / 1024.0 * round((float) building.width / 6.0f);
+ float right_x = 0.0f;
float front_x = 384.0/1024.0;
float back_x = 384.0/1024.0 + 32.0 / 1024.0 * round((float) building.depth/ 6.0f);
if (building.pitched) {
// Use the entire height of the roof texture
top_y = base_y + 16.0 * 3.0 / 1024.0;
- left_x = 512/1024.0;
- right_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;
front_x = 480.0/1024.0;
back_x = 512.0/1024.0;
t->push_back( osg::Vec2( front_x, top_y ) ); // top right
} else {
// Flat roof
- left_x = 512.0/1024.0;
- right_x = 640.0/1024.0;
+ 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;
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;
- float right_x = left_x + 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;
// BASEMENT - uses the baseline texture
for (unsigned int i = 0; i < 16; i++) {
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
// Flat roof
base_y = 416/1024.0;
top_y = 576.0/1024.0;
- right_x = left_x + 32.0 / 1024.0 * 6.0;
+ left_x = column * 192.0 /1024.0;
+ right_x = (column + 1)* 192.0 /1024.0;
t->push_back( osg::Vec2( right_x, base_y) ); // bottom right
t->push_back( osg::Vec2( left_x, base_y) ); // bottom left
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;
- float right_x = left_x + 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;
// BASEMENT - uses the baseline texture
for (unsigned int i = 0; i < 16; i++) {
geode->setDrawable(0, geom);
}
+typedef std::map<std::string, osg::observer_ptr<Effect> > EffectMap;
+
+static EffectMap buildingEffectMap;
+
// Helper classes for creating the quad tree
namespace
{
// Create a series of LOD nodes so trees cover decreases slightly
// gradually with distance from _range to 2*_range
for (float i = 0.0; i < SG_BUILDING_FADE_OUT_LEVELS; i++)
- {
- //osg::ref_ptr<EffectGeode> geode = new EffectGeode();
- //geode->setEffect(_effect);
- osg::ref_ptr<osg::Geode> geode = new osg::Geode();
- result->addChild(geode, 0, _range * (1.0 + i / (SG_BUILDING_FADE_OUT_LEVELS - 1.0)));
+ {
+ EffectGeode* geode = new EffectGeode;
+ geode->setEffect(_effect.get());
+ result->addChild(geode, 0, _range * (1.0 + i / (SG_BUILDING_FADE_OUT_LEVELS - 1.0)));
}
return result;
}
float _range;
- Effect* _effect;
+ ref_ptr<Effect> _effect;
};
struct AddBuildingLeafObject
static Matrix ident;
// Set up some shared structures.
MatrixTransform* mt = new MatrixTransform(transform);
- Effect* effect = makeEffect("Effects/model-default", true);
SGBuildingBin* bin = NULL;
BOOST_FOREACH(bin, buildings)
{
+ numBuildings = numBuildings + bin->getNumBuildings();
+ SG_LOG(SG_TERRAIN, SG_DEBUG, "Total random buildings generated: " << numBuildings);
+
+ ref_ptr<Effect> effect;
+ EffectMap::iterator iter = buildingEffectMap.find(bin->texture);
+
+ if ((iter == buildingEffectMap.end())||
+ (!iter->second.lock(effect)))
+ {
+ SGPropertyNode_ptr effectProp = new SGPropertyNode;
+ makeChild(effectProp, "inherits-from")->setStringValue("Effects/building");
+ SGPropertyNode* params = makeChild(effectProp, "parameters");
+ // Main texture - n=0
+ params->getChild("texture", 0, true)->getChild("image", 0, true)
+ ->setStringValue(bin->texture);
+
+ // Light map - n=1
+ params->getChild("texture", 1, true)->getChild("image", 0, true)
+ ->setStringValue(bin->lightMap);
+
+ effect = makeEffect(effectProp, true, options);
+ if (iter == buildingEffectMap.end())
+ buildingEffectMap.insert(EffectMap::value_type(bin->texture, effect));
+ else
+ iter->second = effect; // update existing, but empty observer
+ }
+
// Now, create a quadbuilding for the buildings.
BuildingGeometryQuadtree
quadbuilding(GetBuildingCoord(), AddBuildingLeafObject(),
BuildingTransformer(transInv));
quadbuilding.buildQuadTree(rotatedBuildings.begin(), rotatedBuildings.end());
- ref_ptr<Group> group = quadbuilding.getRoot();
-
- // Set up the stateset for this building bin and the texture to use.
- osg::StateSet* stateSet = group->getOrCreateStateSet();
- const std::string texturename = bin->texture;
- osg::Texture2D* texture = SGLoadTexture2D(texturename);
- texture->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::CLAMP_TO_EDGE);
- texture->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::CLAMP_TO_EDGE);
- stateSet->setTextureAttributeAndModes(0, texture);
-
- osg::ShadeModel* shadeModel = new osg::ShadeModel;
- shadeModel->setMode(osg::ShadeModel::FLAT);
- stateSet->setAttributeAndModes(shadeModel);
- stateSet->setMode(GL_LIGHTING, osg::StateAttribute::ON);
- stateSet->setMode(GL_FOG, osg::StateAttribute::ON);
- stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON);
- stateSet->setMode(GL_CULL_FACE, osg::StateAttribute::ON);
- stateSet->setMode(GL_BLEND, osg::StateAttribute::OFF);
- stateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::OFF);
- stateSet->setAttribute(new osg::CullFace(osg::CullFace::BACK));
-
- osg::Material* material = new osg::Material;
- material->setAmbient(osg::Material::FRONT, osg::Vec4(0.3,0.3,0.3,1.0));
- material->setDiffuse(osg::Material::FRONT, osg::Vec4(1.0,1.0,1.0,1.0));
- material->setSpecular(osg::Material::FRONT, osg::Vec4(0,0,0,1.0));
- material->setShininess(osg::Material::FRONT, 0.0);
- material->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE);
- stateSet->setAttribute(material);
- mt->addChild(group);
- }
+ ref_ptr<Group> group = quadbuilding.getRoot();
+ mt->addChild(group);
+ delete bin;
+ }
+
+ buildings.clear();
return mt;
}