3 # include <simgear_config.h>
8 #include <simgear/scene/material/EffectGeode.hxx>
9 #include <simgear/scene/material/matlib.hxx>
10 #include <simgear/scene/material/mat.hxx>
12 #include "SGTexturedTriangleBin.hxx"
14 using namespace simgear;
16 typedef std::map<std::string,SGTexturedTriangleBin> SGMaterialTriangleMap;
18 // Class handling the initial BTG loading : should probably be in its own file
19 // it is very closely coupled with SGTexturedTriangleBin.hxx
20 // it was used to load fans, strips, and triangles.
21 // WS2.0 no longer uses fans or strips, but people still use ws1.0, so we need
22 // to keep this functionality.
23 class SGTileGeometryBin : public osg::Referenced {
25 SGMaterialTriangleMap materialTriangleMap;
27 SGTileGeometryBin() {}
30 getTexCoord(const std::vector<SGVec2f>& texCoords, const int_list& tc,
31 const SGVec2f& tcScale, unsigned i)
35 else if (tc.size() == 1)
36 return mult(texCoords[tc[0]], tcScale);
38 return mult(texCoords[tc[i]], tcScale);
41 SGVec2f getTexCoordScale(const std::string& name, SGMaterialCache* matcache)
45 SGMaterial* material = matcache->find(name);
49 return material->get_tex_coord_scale();
53 addTriangleGeometry(SGTexturedTriangleBin& triangles,
54 const SGBinObject& obj, unsigned grp,
55 const SGVec2f& tc0Scale,
56 const SGVec2f& tc1Scale)
58 const std::vector<SGVec3d>& vertices(obj.get_wgs84_nodes());
59 const std::vector<SGVec3f>& normals(obj.get_normals());
60 const std::vector<SGVec2f>& texCoords(obj.get_texcoords());
61 const int_list& tris_v(obj.get_tris_v()[grp]);
62 const int_list& tris_n(obj.get_tris_n()[grp]);
63 const tci_list& tris_tc(obj.get_tris_tcs()[grp]);
64 bool num_norms_is_num_verts = true;
66 if (tris_v.size() != tris_n.size()) {
67 // If the normal indices do not match, they should be inmplicitly
68 // the same than the vertex indices.
69 num_norms_is_num_verts = false;
72 if ( !tris_tc[1].empty() ) {
73 triangles.hasSecondaryTexCoord(true);
76 for (unsigned i = 2; i < tris_v.size(); i += 3) {
78 v0.SetVertex( toVec3f(vertices[tris_v[i-2]]) );
79 v0.SetNormal( num_norms_is_num_verts ? normals[tris_n[i-2]] :
80 normals[tris_v[i-2]] );
81 v0.SetTexCoord( 0, getTexCoord(texCoords, tris_tc[0], tc0Scale, i-2) );
82 if (!tris_tc[1].empty()) {
83 v0.SetTexCoord( 1, getTexCoord(texCoords, tris_tc[1], tc1Scale, i-2) );
86 v1.SetVertex( toVec3f(vertices[tris_v[i-1]]) );
87 v1.SetNormal( num_norms_is_num_verts ? normals[tris_n[i-1]] :
88 normals[tris_v[i-1]] );
89 v1.SetTexCoord( 0, getTexCoord(texCoords, tris_tc[0], tc0Scale, i-1) );
90 if (!tris_tc[1].empty()) {
91 v1.SetTexCoord( 1, getTexCoord(texCoords, tris_tc[1], tc1Scale, i-1) );
94 v2.SetVertex( toVec3f(vertices[tris_v[i]]) );
95 v2.SetNormal( num_norms_is_num_verts ? normals[tris_n[i]] :
97 v2.SetTexCoord( 0, getTexCoord(texCoords, tris_tc[0], tc0Scale, i) );
98 if (!tris_tc[1].empty()) {
99 v2.SetTexCoord( 1, getTexCoord(texCoords, tris_tc[1], tc1Scale, i) );
102 triangles.insert(v0, v1, v2);
107 addStripGeometry(SGTexturedTriangleBin& triangles,
108 const SGBinObject& obj, unsigned grp,
109 const SGVec2f& tc0Scale,
110 const SGVec2f& tc1Scale)
112 const std::vector<SGVec3d>& vertices(obj.get_wgs84_nodes());
113 const std::vector<SGVec3f>& normals(obj.get_normals());
114 const std::vector<SGVec2f>& texCoords(obj.get_texcoords());
115 const int_list& strips_v(obj.get_strips_v()[grp]);
116 const int_list& strips_n(obj.get_strips_n()[grp]);
117 const tci_list& strips_tc(obj.get_strips_tcs()[grp]);
118 bool num_norms_is_num_verts = true;
120 if (strips_v.size() != strips_n.size()) {
121 // If the normal indices do not match, they should be inmplicitly
122 // the same than the vertex indices.
123 num_norms_is_num_verts = false;
126 if ( !strips_tc[1].empty() ) {
127 triangles.hasSecondaryTexCoord(true);
130 for (unsigned i = 2; i < strips_v.size(); ++i) {
132 v0.SetVertex( toVec3f(vertices[strips_v[i-2]]) );
133 v0.SetNormal( num_norms_is_num_verts ? normals[strips_n[i-2]] :
134 normals[strips_v[i-2]] );
135 v0.SetTexCoord( 0, getTexCoord(texCoords, strips_tc[0], tc0Scale, i-2) );
136 if (!strips_tc[1].empty()) {
137 v0.SetTexCoord( 1, getTexCoord(texCoords, strips_tc[1], tc1Scale, i-2) );
140 v1.SetVertex( toVec3f(vertices[strips_v[i-1]]) );
141 v1.SetNormal( num_norms_is_num_verts ? normals[strips_n[i-1]] :
142 normals[strips_v[i-1]] );
143 v1.SetTexCoord( 0, getTexCoord(texCoords, strips_tc[1], tc0Scale, i-1) );
144 if (!strips_tc[1].empty()) {
145 v1.SetTexCoord( 1, getTexCoord(texCoords, strips_tc[1], tc1Scale, i-1) );
148 v2.SetVertex( toVec3f(vertices[strips_v[i]]) );
149 v2.SetNormal( num_norms_is_num_verts ? normals[strips_n[i]] :
150 normals[strips_v[i]] );
151 v2.SetTexCoord( 0, getTexCoord(texCoords, strips_tc[0], tc0Scale, i) );
152 if (!strips_tc[1].empty()) {
153 v2.SetTexCoord( 1, getTexCoord(texCoords, strips_tc[1], tc1Scale, i) );
156 triangles.insert(v1, v0, v2);
158 triangles.insert(v0, v1, v2);
163 addFanGeometry(SGTexturedTriangleBin& triangles,
164 const SGBinObject& obj, unsigned grp,
165 const SGVec2f& tc0Scale,
166 const SGVec2f& tc1Scale)
168 const std::vector<SGVec3d>& vertices(obj.get_wgs84_nodes());
169 const std::vector<SGVec3f>& normals(obj.get_normals());
170 const std::vector<SGVec2f>& texCoords(obj.get_texcoords());
171 const int_list& fans_v(obj.get_fans_v()[grp]);
172 const int_list& fans_n(obj.get_fans_n()[grp]);
173 const tci_list& fans_tc(obj.get_fans_tcs()[grp]);
174 bool num_norms_is_num_verts = true;
176 if (fans_v.size() != fans_n.size()) {
177 // If the normal indices do not match, they should be inmplicitly
178 // the same than the vertex indices.
179 num_norms_is_num_verts = false;
182 if ( !fans_tc[1].empty() ) {
183 triangles.hasSecondaryTexCoord(true);
187 v0.SetVertex( toVec3f(vertices[fans_v[0]]) );
188 v0.SetNormal( num_norms_is_num_verts ? normals[fans_n[0]] :
189 normals[fans_v[0]] );
190 v0.SetTexCoord( 0, getTexCoord(texCoords, fans_tc[0], tc0Scale, 0) );
191 if (!fans_tc[1].empty()) {
192 v0.SetTexCoord( 1, getTexCoord(texCoords, fans_tc[1], tc1Scale, 0) );
195 v1.SetVertex( toVec3f(vertices[fans_v[1]]) );
196 v1.SetNormal( num_norms_is_num_verts ? normals[fans_n[1]] :
197 normals[fans_v[1]] );
198 v1.SetTexCoord( 0, getTexCoord(texCoords, fans_tc[0], tc0Scale, 1) );
199 if (!fans_tc[1].empty()) {
200 v1.SetTexCoord( 1, getTexCoord(texCoords, fans_tc[1], tc1Scale, 1) );
202 for (unsigned i = 2; i < fans_v.size(); ++i) {
204 v2.SetVertex( toVec3f(vertices[fans_v[i]]) );
205 v2.SetNormal( num_norms_is_num_verts ? normals[fans_n[i]] :
206 normals[fans_v[i]] );
207 v2.SetTexCoord( 0, getTexCoord(texCoords, fans_tc[0], tc0Scale, i) );
208 if (!fans_tc[1].empty()) {
209 v2.SetTexCoord( 1, getTexCoord(texCoords, fans_tc[1], tc1Scale, i) );
211 triangles.insert(v0, v1, v2);
217 insertSurfaceGeometry(const SGBinObject& obj, SGMaterialCache* matcache)
219 if (obj.get_tris_n().size() < obj.get_tris_v().size() ||
220 obj.get_tris_tcs().size() < obj.get_tris_v().size()) {
221 SG_LOG(SG_TERRAIN, SG_ALERT,
222 "Group list sizes for triangles do not match!");
226 for (unsigned grp = 0; grp < obj.get_tris_v().size(); ++grp) {
227 std::string materialName = obj.get_tri_materials()[grp];
228 SGVec2f tc0Scale = getTexCoordScale(materialName, matcache);
229 SGVec2f tc1Scale(1.0, 1.0);
230 addTriangleGeometry(materialTriangleMap[materialName],
231 obj, grp, tc0Scale, tc1Scale );
234 if (obj.get_strips_n().size() < obj.get_strips_v().size() ||
235 obj.get_strips_tcs().size() < obj.get_strips_v().size()) {
236 SG_LOG(SG_TERRAIN, SG_ALERT,
237 "Group list sizes for strips do not match!");
240 for (unsigned grp = 0; grp < obj.get_strips_v().size(); ++grp) {
241 std::string materialName = obj.get_strip_materials()[grp];
242 SGVec2f tc0Scale = getTexCoordScale(materialName, matcache);
243 SGVec2f tc1Scale(1.0, 1.0);
244 addStripGeometry(materialTriangleMap[materialName],
245 obj, grp, tc0Scale, tc1Scale);
248 if (obj.get_fans_n().size() < obj.get_fans_v().size() ||
249 obj.get_fans_tcs().size() < obj.get_fans_v().size()) {
250 SG_LOG(SG_TERRAIN, SG_ALERT,
251 "Group list sizes for fans do not match!");
254 for (unsigned grp = 0; grp < obj.get_fans_v().size(); ++grp) {
255 std::string materialName = obj.get_fan_materials()[grp];
256 SGVec2f tc0Scale = getTexCoordScale(materialName, matcache);
257 SGVec2f tc1Scale(1.0, 1.0);
258 addFanGeometry(materialTriangleMap[materialName],
259 obj, grp, tc0Scale, tc1Scale );
264 osg::Node* getSurfaceGeometry(SGMaterialCache* matcache, bool useVBOs) const
266 if (materialTriangleMap.empty())
269 EffectGeode* eg = NULL;
270 osg::Group* group = (materialTriangleMap.size() > 1 ? new osg::Group : NULL);
272 group->setName("surfaceGeometryGroup");
275 //osg::Geode* geode = new osg::Geode;
276 SGMaterialTriangleMap::const_iterator i;
277 for (i = materialTriangleMap.begin(); i != materialTriangleMap.end(); ++i) {
278 osg::Geometry* geometry = i->second.buildGeometry(useVBOs);
279 SGMaterial *mat = NULL;
281 mat = matcache->find(i->first);
283 eg = new EffectGeode;
284 eg->setName("EffectGeode");
286 eg->setMaterial(mat);
287 eg->setEffect(mat->get_one_effect(i->second.getTextureIndex()));
289 eg->setMaterial(NULL);
291 eg->addDrawable(geometry);
292 eg->runGenerators(geometry); // Generate extra data needed by effect