#include <simgear/scene/material/mat.hxx>
#include <simgear/scene/material/matlib.hxx>
+void fillDrawElements(int width, int height,
+ osg::DrawElementsUShort::vector_type::iterator elements)
+{
+ for (int j = 0; j < height - 1; j++) {
+ for (int i = 0; i < width - 1; i++) {
+ *elements++ = j * width + i;
+ *elements++ = j * width + i + 1;
+ *elements++ = (j + 1) * width + i;
+ *elements++ = (j + 1) * width + i;
+ *elements++ = j * width + i + 1;
+ *elements++ = (j + 1) * width + i + 1;
+ }
+ }
+}
+
// Generate an ocean tile
osg::Node* SGOceanTile(const SGBucket& b, SGMaterialLib *matlib)
{
// Calculate center point
SGVec3d cartCenter = SGVec3d::fromGeod(b.get_center());
- Point3D center = Point3D(cartCenter[0], cartCenter[1], cartCenter[2]);
double clon = b.get_center_lon();
double clat = b.get_center_lat();
double height = b.get_height();
double width = b.get_width();
-
- // Caculate corner vertices
- SGGeod geod[4];
- geod[0] = SGGeod::fromDeg( clon - 0.5*width, clat - 0.5*height );
- geod[1] = SGGeod::fromDeg( clon + 0.5*width, clat - 0.5*height );
- geod[2] = SGGeod::fromDeg( clon + 0.5*width, clat + 0.5*height );
- geod[3] = SGGeod::fromDeg( clon - 0.5*width, clat + 0.5*height );
-
- int i;
- SGVec3f normals[4];
- SGVec3d rel[4];
- for ( i = 0; i < 4; ++i ) {
- SGVec3d cart = SGVec3d::fromGeod(geod[i]);
- rel[i] = cart - center.toSGVec3d();
- normals[i] = toVec3f(normalize(cart));
+
+ // Calculate vertices. By splitting the tile up into 4 quads on a
+ // side we avoid curvature-of-the-earth problems; the error should
+ // be less than .5 meters.
+ SGGeod geod[5][5];
+ SGVec3f normals[5][5];
+ SGVec3d rel[5][5];
+ double longInc = width * .25;
+ double latInc = height * .25;
+ double startLat = clat - height * .5;
+ double startLon = clon - width * .5;
+ for (int j = 0; j < 5; j++) {
+ double lat = startLat + j * latInc;
+ for (int i = 0; i < 5; i++) {
+ geod[i][j] = SGGeod::fromDeg(startLon + i * longInc, lat);
+ SGVec3d cart = SGVec3d::fromGeod(geod[i][j]);
+ rel[i][j] = cart - cartCenter;
+ normals[i][j] = toVec3f(normalize(cart));
+ }
}
-
+
// Calculate texture coordinates
point_list geod_nodes;
- geod_nodes.clear();
- geod_nodes.reserve(4);
+ geod_nodes.reserve(5 * 5);
int_list rectangle;
- rectangle.clear();
- rectangle.reserve(4);
- for ( i = 0; i < 4; ++i ) {
- geod_nodes.push_back(Point3D(geod[i].getLongitudeDeg(),
- geod[i].getLatitudeDeg(),
- geod[i].getElevationM()));
- rectangle.push_back( i );
+ rectangle.reserve(5 * 5);
+ for (int j = 0; j < 5; j++) {
+ for (int i = 0; i < 5; ++i) {
+ geod_nodes.push_back(Point3D(geod[i][j].getLongitudeDeg(),
+ geod[i][j].getLatitudeDeg(),
+ geod[i][j].getElevationM()));
+ rectangle.push_back(j * 5 + i);
+ }
}
point_list texs = sgCalcTexCoords( b, geod_nodes, rectangle,
1000.0 / tex_width );
- // Allocate ssg structure
+ // Allocate osg structures
osg::Vec3Array *vl = new osg::Vec3Array;
osg::Vec3Array *nl = new osg::Vec3Array;
osg::Vec2Array *tl = new osg::Vec2Array;
-
- for ( i = 0; i < 4; ++i ) {
- vl->push_back(rel[i].osg());
- nl->push_back(normals[i].osg());
- tl->push_back(texs[i].toSGVec2f().osg());
+
+ for (int j = 0; j < 5; j++) {
+ for (int i = 0; i < 5; ++i) {
+ vl->push_back(rel[i][j].osg());
+ nl->push_back(normals[i][j].osg());
+ tl->push_back(texs[j * 5 + i].toSGVec2f().osg());
+ }
}
osg::Vec4Array* cl = new osg::Vec4Array;
geometry->setColorArray(cl);
geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
geometry->setTexCoordArray(0, tl);
- osg::DrawArrays* drawArrays;
- drawArrays = new osg::DrawArrays(GL_TRIANGLE_FAN, 0, vl->size());
- geometry->addPrimitiveSet(drawArrays);
+
+ osg::DrawElementsUShort* drawElements
+ = new osg::DrawElementsUShort(GL_TRIANGLES, 32 * 3);
+ fillDrawElements(5, 5, drawElements->begin());
+ geometry->addPrimitiveSet(drawElements);
osg::Geode* geode = new osg::Geode;
geode->setName("Ocean tile");