3 * Copyright (C) 2006-2007 Mathias Froehlich
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
23 # include <simgear_config.h>
26 #include "SGOceanTile.hxx"
28 #include <simgear/compiler.h>
31 #include <osg/Geometry>
32 #include <osg/MatrixTransform>
33 #include <osg/StateSet>
35 #include <simgear/bucket/newbucket.hxx>
36 #include <simgear/math/sg_geodesy.hxx>
37 #include <simgear/math/sg_types.hxx>
38 #include <simgear/misc/texcoord.hxx>
39 #include <simgear/scene/material/mat.hxx>
40 #include <simgear/scene/material/matlib.hxx>
42 void fillDrawElements(int width, int height,
43 osg::DrawElementsUShort::vector_type::iterator elements)
45 for (int j = 0; j < height - 1; j++) {
46 for (int i = 0; i < width - 1; i++) {
47 *elements++ = j * width + i;
48 *elements++ = j * width + i + 1;
49 *elements++ = (j + 1) * width + i;
50 *elements++ = (j + 1) * width + i;
51 *elements++ = j * width + i + 1;
52 *elements++ = (j + 1) * width + i + 1;
57 // Generate an ocean tile
58 osg::Node* SGOceanTile(const SGBucket& b, SGMaterialLib *matlib)
60 osg::StateSet *stateSet = 0;
62 double tex_width = 1000.0;
64 // find Ocean material in the properties list
65 SGMaterial *mat = matlib->find( "Ocean" );
67 // set the texture width and height values for this
69 tex_width = mat->get_xsize();
72 stateSet = mat->get_state();
74 SG_LOG( SG_TERRAIN, SG_ALERT, "Ack! unknown use material name = Ocean");
77 // Calculate center point
78 SGVec3d cartCenter = SGVec3d::fromGeod(b.get_center());
80 double clon = b.get_center_lon();
81 double clat = b.get_center_lat();
82 double height = b.get_height();
83 double width = b.get_width();
85 // Calculate vertices. By splitting the tile up into 4 quads on a
86 // side we avoid curvature-of-the-earth problems; the error should
87 // be less than .5 meters.
89 SGVec3f normals[5][5];
91 double longInc = width * .25;
92 double latInc = height * .25;
93 double startLat = clat - height * .5;
94 double startLon = clon - width * .5;
95 for (int j = 0; j < 5; j++) {
96 double lat = startLat + j * latInc;
97 for (int i = 0; i < 5; i++) {
98 geod[i][j] = SGGeod::fromDeg(startLon + i * longInc, lat);
99 SGVec3d cart = SGVec3d::fromGeod(geod[i][j]);
100 rel[i][j] = cart - cartCenter;
101 normals[i][j] = toVec3f(normalize(cart));
105 // Calculate texture coordinates
106 point_list geod_nodes;
107 geod_nodes.reserve(5 * 5);
109 rectangle.reserve(5 * 5);
110 for (int j = 0; j < 5; j++) {
111 for (int i = 0; i < 5; ++i) {
112 geod_nodes.push_back(Point3D(geod[i][j].getLongitudeDeg(),
113 geod[i][j].getLatitudeDeg(),
114 geod[i][j].getElevationM()));
115 rectangle.push_back(j * 5 + i);
118 point_list texs = sgCalcTexCoords( b, geod_nodes, rectangle,
119 1000.0 / tex_width );
121 // Allocate osg structures
122 osg::Vec3Array *vl = new osg::Vec3Array;
123 osg::Vec3Array *nl = new osg::Vec3Array;
124 osg::Vec2Array *tl = new osg::Vec2Array;
126 for (int j = 0; j < 5; j++) {
127 for (int i = 0; i < 5; ++i) {
128 vl->push_back(rel[i][j].osg());
129 nl->push_back(normals[i][j].osg());
130 tl->push_back(texs[j * 5 + i].toSGVec2f().osg());
134 osg::Vec4Array* cl = new osg::Vec4Array;
135 cl->push_back(osg::Vec4(1, 1, 1, 1));
137 osg::Geometry* geometry = new osg::Geometry;
138 geometry->setVertexArray(vl);
139 geometry->setNormalArray(nl);
140 geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
141 geometry->setColorArray(cl);
142 geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
143 geometry->setTexCoordArray(0, tl);
145 osg::DrawElementsUShort* drawElements
146 = new osg::DrawElementsUShort(GL_TRIANGLES, 32 * 3);
147 fillDrawElements(5, 5, drawElements->begin());
148 geometry->addPrimitiveSet(drawElements);
150 osg::Geode* geode = new osg::Geode;
151 geode->setName("Ocean tile");
152 geode->addDrawable(geometry);
153 geode->setStateSet(stateSet);
155 osg::MatrixTransform* transform = new osg::MatrixTransform;
156 transform->setName("Ocean");
157 transform->setMatrix(osg::Matrix::translate(cartCenter.osg()));
158 transform->addChild(geode);