X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fscene%2Ftgdb%2FSGBuildingBin.cxx;h=3000079e52f577a62e4c60ae509a8e4149a1fde7;hb=4838a9690e1a9492db6741f4950976b63868200d;hp=8c8d4bc5aeae47e94e4320e246743ef6a9c8527f;hpb=2d174d0b1456fd11af5c2675857271ee7da91941;p=simgear.git diff --git a/simgear/scene/tgdb/SGBuildingBin.cxx b/simgear/scene/tgdb/SGBuildingBin.cxx index 8c8d4bc5..3000079e 100644 --- a/simgear/scene/tgdb/SGBuildingBin.cxx +++ b/simgear/scene/tgdb/SGBuildingBin.cxx @@ -59,8 +59,8 @@ #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; @@ -69,6 +69,7 @@ namespace simgear typedef std::map > BuildingStateSetMap; static BuildingStateSetMap statesetmap; +static int numBuildings; void addBuildingToLeafGeode(Geode* geode, const SGBuildingBin::Building& building) { @@ -78,10 +79,10 @@ void addBuildingToLeafGeode(Geode* geode, const SGBuildingBin::Building& buildin // Get or create geometry. osg::ref_ptr 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; @@ -132,80 +133,79 @@ void addBuildingToLeafGeode(Geode* geode, const SGBuildingBin::Building& buildin 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 @@ -214,46 +214,46 @@ void addBuildingToLeafGeode(Geode* geode, const SGBuildingBin::Building& buildin 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 @@ -269,8 +269,8 @@ void addBuildingToLeafGeode(Geode* geode, const SGBuildingBin::Building& buildin 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); @@ -307,8 +307,8 @@ void addBuildingToLeafGeode(Geode* geode, const SGBuildingBin::Building& buildin 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; @@ -337,8 +337,8 @@ void addBuildingToLeafGeode(Geode* geode, const SGBuildingBin::Building& buildin 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; @@ -355,8 +355,8 @@ void addBuildingToLeafGeode(Geode* geode, const SGBuildingBin::Building& buildin 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++) { @@ -394,6 +394,7 @@ void addBuildingToLeafGeode(Geode* geode, const SGBuildingBin::Building& buildin 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 @@ -421,7 +422,8 @@ void addBuildingToLeafGeode(Geode* geode, const SGBuildingBin::Building& buildin // 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 @@ -435,8 +437,8 @@ void addBuildingToLeafGeode(Geode* geode, const SGBuildingBin::Building& buildin 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++) { @@ -517,6 +519,10 @@ void addBuildingToLeafGeode(Geode* geode, const SGBuildingBin::Building& buildin geode->setDrawable(0, geom); } +typedef std::map > EffectMap; + +static EffectMap buildingEffectMap; + // Helper classes for creating the quad tree namespace { @@ -536,17 +542,16 @@ struct MakeBuildingLeaf // 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 geode = new EffectGeode(); - //geode->setEffect(_effect); - osg::ref_ptr 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; }; struct AddBuildingLeafObject @@ -593,12 +598,38 @@ osg::Group* createRandomBuildings(SGBuildingBinList buildings, const osg::Matrix 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; + 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(), @@ -615,36 +646,12 @@ osg::Group* createRandomBuildings(SGBuildingBinList buildings, const osg::Matrix BuildingTransformer(transInv)); quadbuilding.buildQuadTree(rotatedBuildings.begin(), rotatedBuildings.end()); - ref_ptr 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 = quadbuilding.getRoot(); + mt->addChild(group); + delete bin; + } + + buildings.clear(); return mt; }