]> git.mxchange.org Git - simgear.git/blob - simgear/scene/tgdb/apt_signs.cxx
175e5c6fa9d60a47b5ff3a5a66ba7e38baf8f597
[simgear.git] / simgear / scene / tgdb / apt_signs.cxx
1 // apt_signs.cxx -- build airport signs on the fly
2 //
3 // Written by Curtis Olson, started July 2001.
4 //
5 // Copyright (C) 2001  Curtis L. Olson  - http://www.flightgear.org/~curt
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 // General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20 //
21 // $Id$
22
23 #ifdef HAVE_CONFIG_H
24 #  include <simgear_config.h>
25 #endif
26
27 #include <simgear/debug/logstream.hxx>
28 #include <simgear/math/sg_types.hxx>
29 #include <simgear/scene/tgdb/leaf.hxx>
30 #include <simgear/scene/material/mat.hxx>
31 #include <simgear/scene/material/matlib.hxx>
32
33 #include "apt_signs.hxx"
34
35 #define TAXI "OBJECT_TAXI_SIGN: "
36 #define RWY "OBJECT_RUNWAY_SIGN: "
37
38
39 // for temporary storage of sign elements
40 struct element_info {
41     element_info(SGMaterial *m, SGMaterialGlyph *g) : material(m), glyph(g) {}
42     SGMaterial *material;
43     SGMaterialGlyph *glyph;
44 };
45
46
47 // translation table for 'command' to glyph name
48 struct pair {
49     const char *keyword;
50     const char *glyph_name;
51 } cmds[] = {
52     {"l",       "left"},
53     {"lu",      "up-left"},
54     {"ld",      "down-left"},
55     {"r",       "right"},
56     {"ru",      "up-right"},
57     {"rd",      "down-right"},
58     {"u",       "up"},
59     {"ul",      "up-left"},
60     {"ur",      "up-right"},
61     {"d",       "down"},
62     {"dl",      "down-left"},
63     {"dr",      "down-right"},
64     {"no-exit", "no-exit"},
65     {0, 0},
66 };
67
68
69 // Y ... black on yellow            -> direction, destination, boundary
70 // R ... white on red               -> mandatory instruction
71 // L ... yellow on black with frame -> runway/taxiway location
72 // B ... white on black             -> runway distance remaining
73 //
74 // u/d/l/r     ... up/down/left/right arrow or two-letter combinations
75 //                 thereof (ur, dl, ...)
76 //
77 // Example: {l}E|{L}[T]|{Y,ur}L|E{r}
78 //
79 ssgBranch *sgMakeTaxiSign( SGMaterialLib *matlib,
80                            const string path, const string content )
81 {
82     const double sign_height = 1.0;   // meter     TODO make configurable
83
84     vector<element_info *> elements;
85     double total_width = 0.0;
86     bool cmd = false;
87     char *newmat = "YellowSign";
88
89     ssgBranch *object = new ssgBranch();
90     object->setName((char *)content.c_str());
91     SGMaterial *material = matlib->find(newmat);
92
93     for (const char *s = content.data(); *s; s++) {
94         string name;
95         const char *newmat = 0;
96
97         if (*s == '{') {
98             if (cmd)
99                 SG_LOG(SG_TERRAIN, SG_ALERT, TAXI "unexpected { in sign contents");
100             cmd = true;
101             continue;
102         } else if (*s == '}') {
103             if (!cmd)
104                 SG_LOG(SG_TERRAIN, SG_ALERT, TAXI "unexpected } in sign contents");
105             cmd = false;
106             continue;
107         } else if (cmd) {
108             if (*s == ',')
109                 continue;
110             else if (*s == 'Y')
111                 newmat = "YellowSign";
112             else if (*s == 'R')
113                 newmat = "RedSign";
114             else if (*s == 'L')
115                 newmat = "FramedSign";
116             else if (*s == 'B')
117                 newmat = "BlackSign";
118             else {
119                 // find longest match of cmds[]
120                 int maxlen = 0, len;
121                 for (int i = 0; cmds[i].keyword; i++) {
122                     len = strlen(cmds[i].keyword);
123                     if (!strncmp(s, cmds[i].keyword, len)) {
124                         maxlen = len;
125                         name = cmds[i].glyph_name;
126                     }
127                 }
128                 if (maxlen)
129                     s += maxlen - 1;
130             }
131             if (s[1] != ',' && s[1] != '}')
132                 SG_LOG(SG_TERRAIN, SG_ALERT, TAXI "garbage after command `" << s << '\'');
133
134             if (newmat) {
135                 material = matlib->find(newmat);
136                 continue;
137             }
138
139             if (name.empty()) {
140                 SG_LOG(SG_TERRAIN, SG_ALERT, TAXI "unknown command `" << s << '\'');
141                 continue;
142             }
143         } else
144             name = *s;
145
146         if (!material) {
147             SG_LOG( SG_TERRAIN, SG_ALERT, TAXI "material doesn't exit");
148             continue;
149         }
150
151         SGMaterialGlyph *glyph = material->get_glyph(name);
152         if (!glyph) {
153             SG_LOG( SG_TERRAIN, SG_ALERT, TAXI "unsupported character `" << *s << '\'');
154             continue;
155         }
156
157         elements.push_back(new element_info(material, glyph));
158         total_width += glyph->get_width() * material->get_xscale();
159     }
160
161     double hpos = -total_width / 2;
162
163     sgVec3 normal;
164     sgSetVec3(normal, 0, -1, 0);
165
166     sgVec4 color;
167     sgSetVec4(color, 1.0, 1.0, 1.0, 1.0);
168
169     for (unsigned int i = 0; i < elements.size(); i++) {
170         element_info *element = elements[i];
171
172         double xoffset = element->glyph->get_left();
173         double width = element->glyph->get_width();
174         double abswidth = width * element->material->get_xscale();
175
176         // vertices
177         ssgVertexArray *vl = new ssgVertexArray(4);
178         vl->add(hpos,            0, 0);
179         vl->add(hpos + abswidth, 0, 0);
180         vl->add(hpos,            0, sign_height);
181         vl->add(hpos + abswidth, 0, sign_height);
182
183         // texture coordinates
184         ssgTexCoordArray *tl = new ssgTexCoordArray(4);
185         tl->add(xoffset,         0);
186         tl->add(xoffset + width, 0);
187         tl->add(xoffset,         1);
188         tl->add(xoffset + width, 1);
189
190         // normals
191         ssgNormalArray *nl = new ssgNormalArray(1);
192         nl->add(normal);
193
194         // colors
195         ssgColourArray *cl = new ssgColourArray(1);
196         cl->add(color);
197
198         ssgLeaf *leaf = new ssgVtxTable(GL_TRIANGLE_STRIP, vl, nl, tl, cl);
199         ssgSimpleState *state = element->material->get_state();
200         //if (!lighted)
201         //    state->setMaterial(GL_EMISSION, 0, 0, 0, 1);
202         leaf->setState(state);
203
204         object->addKid(leaf);
205         hpos += abswidth;
206         delete element;
207     }
208
209     return object;
210 }
211
212
213
214
215
216 ssgBranch *sgMakeRunwaySign( SGMaterialLib *matlib,
217                              const string path, const string name )
218 {
219     // for demo purposes we assume each element (letter) is 1x1 meter.
220     // Sign is placed 0.25 meters above the ground
221
222     ssgBranch *object = new ssgBranch();
223     object->setName( (char *)name.c_str() );
224
225     double width = name.length() / 3.0;
226
227     string material = name;
228
229     point_list nodes;
230     point_list normals;
231     point_list texcoords;
232     int_list vertex_index;
233     int_list normal_index;
234     int_list tex_index;
235
236     nodes.push_back( Point3D( -width, 0, 0.25 ) );
237     nodes.push_back( Point3D( width + 1, 0, 0.25 ) );
238     nodes.push_back( Point3D( -width, 0, 1.25 ) );
239     nodes.push_back( Point3D( width + 1, 0, 1.25 ) );
240
241     normals.push_back( Point3D( 0, -1, 0 ) );
242
243     texcoords.push_back( Point3D( 0, 0, 0 ) );
244     texcoords.push_back( Point3D( 1, 0, 0 ) );
245     texcoords.push_back( Point3D( 0, 1, 0 ) );
246     texcoords.push_back( Point3D( 1, 1, 0 ) );
247
248     vertex_index.push_back( 0 );
249     vertex_index.push_back( 1 );
250     vertex_index.push_back( 2 );
251     vertex_index.push_back( 3 );
252
253     normal_index.push_back( 0 );
254     normal_index.push_back( 0 );
255     normal_index.push_back( 0 );
256     normal_index.push_back( 0 );
257
258     tex_index.push_back( 0 );
259     tex_index.push_back( 1 );
260     tex_index.push_back( 2 );
261     tex_index.push_back( 3 );
262
263     ssgLeaf *leaf = sgMakeLeaf( path, GL_TRIANGLE_STRIP, matlib, material,
264                                 nodes, normals, texcoords,
265                                 vertex_index, normal_index, tex_index,
266                                 false, NULL );
267
268     object->addKid( leaf );
269
270     return object;
271 }