diff --git a/simgear/io/sg_binobj.hxx b/simgear/io/sg_binobj.hxx index 7f67264..c77519f 100644 --- a/simgear/io/sg_binobj.hxx +++ b/simgear/io/sg_binobj.hxx @@ -94,6 +94,7 @@ class SGBinObject { std::vector colors; // color list std::vector normals; // normal list std::vector texcoords; // texture coordinate list + std::vector overlaycoords; // overlay texture coordinate list group_list pts_v; // points vertex index group_list pts_n; // points normal index @@ -142,6 +143,9 @@ public: inline const std::vector& get_texcoords() const { return texcoords; } inline void set_texcoords( const std::vector& t ) { texcoords = t; } + + inline const std::vector& get_overlaycoords() const { return overlaycoords; } + inline void set_overlaycoords( const std::vector& t ) { overlaycoords = t; } inline const group_list& get_pts_v() const { return pts_v; } inline void set_pts_v( const group_list& g ) { pts_v = g; } diff --git a/simgear/scene/tgdb/SGTexturedTriangleBin.hxx b/simgear/scene/tgdb/SGTexturedTriangleBin.hxx index 3df4280..3447e35 100644 --- a/simgear/scene/tgdb/SGTexturedTriangleBin.hxx +++ b/simgear/scene/tgdb/SGTexturedTriangleBin.hxx @@ -35,8 +35,8 @@ struct SGVertNormTex { SGVertNormTex() { } - SGVertNormTex(const SGVec3f& v, const SGVec3f& n, const SGVec2f& t) : - vertex(v), normal(n), texCoord(t) + SGVertNormTex(const SGVec3f& v, const SGVec3f& n, const SGVec2f& t, const SGVec2f& o) : + vertex(v), normal(n), texCoord(t), overlayCoord(o) { } struct less { @@ -54,6 +54,7 @@ struct SGVertNormTex { SGVec3f vertex; SGVec3f normal; SGVec2f texCoord; + SGVec2f overlayCoord; }; // Use a DrawElementsUShort if there are few enough vertices, @@ -289,6 +290,7 @@ public: osg::Vec3Array* vertices = new osg::Vec3Array; osg::Vec3Array* normals = new osg::Vec3Array; osg::Vec2Array* texCoords = new osg::Vec2Array; + osg::Vec2Array* overlayCoords = new osg::Vec2Array; osg::Vec4Array* colors = new osg::Vec4Array; colors->push_back(osg::Vec4(1, 1, 1, 1)); @@ -300,6 +302,7 @@ public: geometry->setColorArray(colors); geometry->setColorBinding(osg::Geometry::BIND_OVERALL); geometry->setTexCoordArray(0, texCoords); + geometry->setTexCoordArray(3, overlayCoords); const unsigned invalid = ~unsigned(0); std::vector indexMap(getNumVertices(), invalid); @@ -312,6 +315,7 @@ public: vertices->push_back(toOsg(getVertex(triangle[0]).vertex)); normals->push_back(toOsg(getVertex(triangle[0]).normal)); texCoords->push_back(toOsg(getVertex(triangle[0]).texCoord)); + overlayCoords->push_back(toOsg(getVertex(triangle[0]).overlayCoord)); } deFacade.push_back(indexMap[triangle[0]]); @@ -320,6 +324,7 @@ public: vertices->push_back(toOsg(getVertex(triangle[1]).vertex)); normals->push_back(toOsg(getVertex(triangle[1]).normal)); texCoords->push_back(toOsg(getVertex(triangle[1]).texCoord)); + overlayCoords->push_back(toOsg(getVertex(triangle[1]).overlayCoord)); } deFacade.push_back(indexMap[triangle[1]]); @@ -328,6 +333,7 @@ public: vertices->push_back(toOsg(getVertex(triangle[2]).vertex)); normals->push_back(toOsg(getVertex(triangle[2]).normal)); texCoords->push_back(toOsg(getVertex(triangle[2]).texCoord)); + overlayCoords->push_back(toOsg(getVertex(triangle[2]).overlayCoord)); } deFacade.push_back(indexMap[triangle[2]]); } diff --git a/simgear/scene/tgdb/obj.cxx b/simgear/scene/tgdb/obj.cxx index 4481b83..0f19f75 100644 --- a/simgear/scene/tgdb/obj.cxx +++ b/simgear/scene/tgdb/obj.cxx @@ -40,6 +40,12 @@ #include #include +#include +#include +#include +#include +#include + #include #include #include @@ -267,6 +273,7 @@ struct SGTileGeometryBin { const std::vector& vertices, const std::vector& normals, const std::vector& texCoords, + const std::vector& overlayCoords, const int_list& fans_v, const int_list& fans_n, const int_list& fans_tc, @@ -276,7 +283,7 @@ struct SGTileGeometryBin { // If the normal indices do not match, they should be implicitly // the same than the vertex indices. So just call ourselves again // with the matching index vector. - addFanGeometry(triangles, vertices, normals, texCoords, + addFanGeometry(triangles, vertices, normals, texCoords, overlayCoords, fans_v, fans_v, fans_tc, tcScale); return; } @@ -285,15 +292,18 @@ struct SGTileGeometryBin { v0.vertex = toVec3f(vertices[fans_v[0]]); v0.normal = normals[fans_n[0]]; v0.texCoord = getTexCoord(texCoords, fans_tc, tcScale, 0); + v0.overlayCoord = overlayCoords[fans_v[0]]; SGVertNormTex v1; v1.vertex = toVec3f(vertices[fans_v[1]]); v1.normal = normals[fans_n[1]]; v1.texCoord = getTexCoord(texCoords, fans_tc, tcScale, 1); + v1.overlayCoord = overlayCoords[fans_v[1]]; for (unsigned i = 2; i < fans_v.size(); ++i) { SGVertNormTex v2; v2.vertex = toVec3f(vertices[fans_v[i]]); v2.normal = normals[fans_n[i]]; v2.texCoord = getTexCoord(texCoords, fans_tc, tcScale, i); + v2.overlayCoord = overlayCoords[fans_v[i]]; triangles.insert(v0, v1, v2); v1 = v2; } @@ -357,9 +367,9 @@ struct SGTileGeometryBin { SGVec2f tcScale = getTexCoordScale(materialName, matlib); addFanGeometry(materialTriangleMap[materialName], obj.get_wgs84_nodes(), obj.get_normals(), - obj.get_texcoords(), obj.get_fans_v()[grp], - obj.get_fans_n()[grp], obj.get_fans_tc()[grp], - tcScale); + obj.get_texcoords(), obj.get_overlaycoords(), + obj.get_fans_v()[grp], obj.get_fans_n()[grp], + obj.get_fans_tc()[grp], tcScale); } return true; } @@ -567,12 +577,29 @@ SGLoadBTG(const std::string& path, SGMaterialLib *matlib, bool calc_lights, bool SGGeod geodPos = SGGeod::fromCart(center); SGQuatd hlOr = SGQuatd::fromLonLat(geodPos)*SGQuatd::fromEulerDeg(0, 0, 180); + // Create bucket based on tile name to get the extent + long index = strtol(osgDB::getSimpleFileName(osgDB::getNameLessExtension(path)).c_str(), NULL, 10); + SGBucket b(index); + double lon_min = b.get_center_lon() - 0.5 * b.get_width(); + double lat_max = b.get_center_lat() + 0.5 * b.get_height(); + + // Overlay texture coordinates + std::vector oc; + // rotate the tiles so that the bounding boxes get nearly axis aligned. // this will help the collision tree's bounding boxes a bit ... std::vector nodes = tile.get_wgs84_nodes(); - for (unsigned i = 0; i < nodes.size(); ++i) + for (unsigned i = 0; i < nodes.size(); ++i) { + // Generate TexCoords for Overlay + SGGeod node_deg = SGGeod::fromCart(nodes[i] + center); + float x = (node_deg.getLongitudeDeg() - lon_min) / b.get_width(); + float y = (lat_max - node_deg.getLatitudeDeg()) / b.get_height(); + oc.push_back(SGVec2f(x, y)); + nodes[i] = hlOr.transform(nodes[i]); + } tile.set_wgs84_nodes(nodes); + tile.set_overlaycoords(oc); SGQuatf hlOrf(hlOr[0], hlOr[1], hlOr[2], hlOr[3]); std::vector normals = tile.get_normals(); @@ -593,8 +620,28 @@ SGLoadBTG(const std::string& path, SGMaterialLib *matlib, bool calc_lights, bool osg::Group* terrainGroup = new osg::Group; osg::Node* node = tileGeometryBin.getSurfaceGeometry(matlib); - if (node) + if (node) { + std::string overlayFile = osgDB::getNameLessExtension(path) + ".dds"; + if (osgDB::fileExists(overlayFile)) { + // Get base node stateset + osg::ref_ptr stateSet = node->getOrCreateStateSet(); + + // Load and set overlay texture + osg::ref_ptr overlayImage = osgDB::readImageFile(overlayFile); + osg::ref_ptr overlayTexture = new osg::Texture2D; + overlayTexture->setImage(overlayImage.get()); + stateSet->setTextureAttributeAndModes(3, overlayTexture.get(), osg::StateAttribute::ON); + + // Apply the texture based on the overlay alpha channel + // *** Problem is we loose lighting + osg::ref_ptr overlayTexEnv = new osg::TexEnv(osg::TexEnv::DECAL); + stateSet->setTextureAttributeAndModes(3, overlayTexEnv.get(), osg::StateAttribute::ON); + + SG_LOG(SG_TERRAIN, SG_INFO, + " Adding overlay image " << osgDB::getSimpleFileName(overlayFile)); + } terrainGroup->addChild(node); + } if (use_random_objects || use_random_vegetation) { if (use_random_objects) {