]> git.mxchange.org Git - simgear.git/blob - simgear/scene/tgdb/SGTileGeometryBin.hxx
Fix #1783: repeated error message on console
[simgear.git] / simgear / scene / tgdb / SGTileGeometryBin.hxx
1
2 #ifdef HAVE_CONFIG_H
3 #  include <simgear_config.h>
4 #endif
5
6 #include "obj.hxx"
7
8 #include <simgear/scene/material/EffectGeode.hxx>
9 #include <simgear/scene/material/matlib.hxx>
10 #include <simgear/scene/material/mat.hxx>
11
12 #include "SGTexturedTriangleBin.hxx"
13
14 using namespace simgear;
15
16 typedef std::map<std::string,SGTexturedTriangleBin> SGMaterialTriangleMap;
17
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 {
24 public:
25   SGMaterialTriangleMap materialTriangleMap;
26
27   SGTileGeometryBin() {}
28
29   static SGVec2f
30   getTexCoord(const std::vector<SGVec2f>& texCoords, const int_list& tc,
31               const SGVec2f& tcScale, unsigned i)
32   {
33     if (tc.empty())
34       return tcScale;
35     else if (tc.size() == 1)
36       return mult(texCoords[tc[0]], tcScale);
37     else
38       return mult(texCoords[tc[i]], tcScale);
39   }
40
41   SGVec2f getTexCoordScale(const std::string& name, SGMaterialCache* matcache)
42   {
43     if (!matcache)
44       return SGVec2f(1, 1);
45     SGMaterial* material = matcache->find(name);
46     if (!material)
47       return SGVec2f(1, 1);
48
49     return material->get_tex_coord_scale();
50   }
51   
52   static void
53   addTriangleGeometry(SGTexturedTriangleBin& triangles,
54                       const SGBinObject& obj, unsigned grp,
55                       const SGVec2f& tc0Scale, 
56                       const SGVec2f& tc1Scale)
57   {
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;  
65     
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;
70     }
71
72     if ( !tris_tc[1].empty() ) {
73         triangles.hasSecondaryTexCoord(true);
74     }
75     
76     for (unsigned i = 2; i < tris_v.size(); i += 3) {
77         SGVertNormTex v0;
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) );
84         }
85         SGVertNormTex v1;
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) );
92         }
93         SGVertNormTex v2;
94         v2.SetVertex( toVec3f(vertices[tris_v[i]]) );
95         v2.SetNormal( num_norms_is_num_verts ? normals[tris_n[i]] : 
96                                                normals[tris_v[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) );
100         }
101         
102         triangles.insert(v0, v1, v2);
103     }
104   }
105
106   static void
107   addStripGeometry(SGTexturedTriangleBin& triangles,
108                    const SGBinObject& obj, unsigned grp,
109                    const SGVec2f& tc0Scale, 
110                    const SGVec2f& tc1Scale)
111   {
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;  
119       
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;
124       }
125       
126       if ( !strips_tc[1].empty() ) {
127           triangles.hasSecondaryTexCoord(true);
128       }
129       
130     for (unsigned i = 2; i < strips_v.size(); ++i) {
131       SGVertNormTex v0;
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) );
138       }
139       SGVertNormTex v1;
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) );
146       }
147       SGVertNormTex v2;
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) );
154       }
155       if (i%2)
156         triangles.insert(v1, v0, v2);
157       else
158         triangles.insert(v0, v1, v2);
159     }
160   }
161
162   static void
163   addFanGeometry(SGTexturedTriangleBin& triangles,
164                  const SGBinObject& obj, unsigned grp,
165                  const SGVec2f& tc0Scale, 
166                  const SGVec2f& tc1Scale)
167   {
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;  
175       
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;
180       }
181       
182       if ( !fans_tc[1].empty() ) {
183           triangles.hasSecondaryTexCoord(true);
184       }
185       
186     SGVertNormTex v0;
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) );
193     }
194     SGVertNormTex v1;
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) );
201     }
202     for (unsigned i = 2; i < fans_v.size(); ++i) {
203       SGVertNormTex v2;
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) );
210       }
211       triangles.insert(v0, v1, v2);
212       v1 = v2;
213     }
214   }
215
216   bool
217   insertSurfaceGeometry(const SGBinObject& obj, SGMaterialCache* matcache)
218   {
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!");
223       return false;
224     }
225
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 );
232     }
233
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!");
238       return false;
239     }
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);
246     }
247
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!");
252       return false;
253     }
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 );
260     }
261     return true;
262   }
263
264   osg::Node* getSurfaceGeometry(SGMaterialCache* matcache, bool useVBOs) const
265   {
266     if (materialTriangleMap.empty())
267       return 0;
268
269     EffectGeode* eg = NULL;
270     osg::Group* group = (materialTriangleMap.size() > 1 ? new osg::Group : NULL);
271     if (group) {
272         group->setName("surfaceGeometryGroup");
273     }
274     
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;
280       if (matcache) {
281         mat = matcache->find(i->first);
282       }
283       eg = new EffectGeode;
284       eg->setName("EffectGeode");
285       if (mat) {
286         eg->setMaterial(mat);
287         eg->setEffect(mat->get_one_effect(i->second.getTextureIndex()));
288       } else {
289         eg->setMaterial(NULL);
290       }
291       eg->addDrawable(geometry);
292       eg->runGenerators(geometry);  // Generate extra data needed by effect
293       if (group) {
294         group->addChild(eg);
295       }
296     }
297     
298     if (group) {
299         return group;
300     } else {
301         return eg;
302     }
303   }
304 };