]> git.mxchange.org Git - simgear.git/blob - simgear/scene/tgdb/apt_signs.cxx
2f80afe3ef76a7b0b99b0bdde075978f63c8693e
[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         scale = m->get_xsize() / (m->get_ysize() < 0.001 ? 1.0 : m->get_ysize());
43     }
44     SGMaterial *material;
45     SGMaterialGlyph *glyph;
46     double scale;
47 };
48
49
50 // translation table for 'command' to glyph name
51 struct pair {
52     const char *keyword;
53     const char *glyph_name;
54 } cmds[] = {
55     {"l",       "left"},
56     {"lu",      "up-left"},
57     {"ld",      "down-left"},
58     {"r",       "right"},
59     {"ru",      "up-right"},
60     {"rd",      "down-right"},
61     {"u",       "up"},
62     {"ul",      "up-left"},
63     {"ur",      "up-right"},
64     {"d",       "down"},
65     {"dl",      "down-left"},
66     {"dr",      "down-right"},
67     {"no-exit", "no-exit"},
68     {0, 0},
69 };
70
71
72 // Y ... black on yellow            -> direction, destination, boundary
73 // R ... white on red               -> mandatory instruction
74 // L ... yellow on black with frame -> runway/taxiway location
75 // B ... white on black             -> runway distance remaining
76 //
77 // u/d/l/r     ... up/down/left/right arrow or two-letter combinations
78 //                 thereof (ur, dl, ...)
79 //
80 // Example: {l}E|{L}[T]|{Y,ur}L|E{r}
81 //
82 ssgBranch *sgMakeTaxiSign( SGMaterialLib *matlib,
83                            const string path, const string content )
84 {
85     const double sign_height = 1.0;   // meter     TODO make configurable
86
87     vector<element_info *> elements;
88     double total_width = 0.0;
89     bool cmd = false;
90     char *newmat = "YellowSign";
91
92     ssgBranch *object = new ssgBranch();
93     object->setName((char *)content.c_str());
94     SGMaterial *material = matlib->find(newmat);
95
96     for (const char *s = content.data(); *s; s++) {
97         string name;
98         const char *newmat = 0;
99
100         if (*s == '{') {
101             if (cmd)
102                 SG_LOG(SG_TERRAIN, SG_ALERT, TAXI "unexpected { in sign contents");
103             cmd = true;
104             continue;
105         } else if (*s == '}') {
106             if (!cmd)
107                 SG_LOG(SG_TERRAIN, SG_ALERT, TAXI "unexpected } in sign contents");
108             cmd = false;
109             continue;
110         } else if (cmd) {
111             if (*s == ',')
112                 continue;
113             else if (*s == 'Y')
114                 newmat = "YellowSign";
115             else if (*s == 'R')
116                 newmat = "RedSign";
117             else if (*s == 'L')
118                 newmat = "FramedSign";
119             else if (*s == 'B')
120                 newmat = "BlackSign";
121             else {
122                 // find longest match of cmds[]
123                 int maxlen = 0, len;
124                 for (int i = 0; cmds[i].keyword; i++) {
125                     len = strlen(cmds[i].keyword);
126                     if (!strncmp(s, cmds[i].keyword, len)) {
127                         maxlen = len;
128                         name = cmds[i].glyph_name;
129                     }
130                 }
131                 if (maxlen)
132                     s += maxlen - 1;
133             }
134             if (s[1] != ',' && s[1] != '}')
135                 SG_LOG(SG_TERRAIN, SG_ALERT, TAXI "garbage after command `" << s << '\'');
136
137             if (newmat) {
138                 material = matlib->find(newmat);
139                 continue;
140             }
141
142             if (name.empty()) {
143                 SG_LOG(SG_TERRAIN, SG_ALERT, TAXI "unknown command `" << s << '\'');
144                 continue;
145             }
146         } else
147             name = *s;
148
149         if (!material) {
150             SG_LOG( SG_TERRAIN, SG_ALERT, TAXI "material doesn't exit");
151             continue;
152         }
153
154         SGMaterialGlyph *glyph = material->get_glyph(name);
155         if (!glyph) {
156             SG_LOG( SG_TERRAIN, SG_ALERT, TAXI "unsupported character `" << *s << '\'');
157             continue;
158         }
159
160         element_info *e = new element_info(material, glyph);
161         elements.push_back(e);
162         total_width += glyph->get_width() * e->scale;
163     }
164
165     double hpos = -total_width / 2;
166
167     sgVec3 normal;
168     sgSetVec3(normal, 0, -1, 0);
169
170     sgVec4 color;
171     sgSetVec4(color, 1.0, 1.0, 1.0, 1.0);
172
173     for (unsigned int i = 0; i < elements.size(); i++) {
174         element_info *element = elements[i];
175
176         double xoffset = element->glyph->get_left();
177         double width = element->glyph->get_width();
178         double abswidth = width * element->scale;
179
180         // vertices
181         ssgVertexArray *vl = new ssgVertexArray(4);
182         vl->add(hpos,            0, 0);
183         vl->add(hpos + abswidth, 0, 0);
184         vl->add(hpos,            0, sign_height);
185         vl->add(hpos + abswidth, 0, sign_height);
186
187         // texture coordinates
188         ssgTexCoordArray *tl = new ssgTexCoordArray(4);
189         tl->add(xoffset,         0);
190         tl->add(xoffset + width, 0);
191         tl->add(xoffset,         1);
192         tl->add(xoffset + width, 1);
193
194         // normals
195         ssgNormalArray *nl = new ssgNormalArray(1);
196         nl->add(normal);
197
198         // colors
199         ssgColourArray *cl = new ssgColourArray(1);
200         cl->add(color);
201
202         ssgLeaf *leaf = new ssgVtxTable(GL_TRIANGLE_STRIP, vl, nl, tl, cl);
203         ssgSimpleState *state = element->material->get_state();
204         //if (!lighted)
205         //    state->setMaterial(GL_EMISSION, 0, 0, 0, 1);
206         leaf->setState(state);
207
208         object->addKid(leaf);
209         hpos += abswidth;
210         delete element;
211     }
212
213     return object;
214 }
215
216
217
218
219
220 ssgBranch *sgMakeRunwaySign( SGMaterialLib *matlib,
221                              const string path, const string name )
222 {
223     // for demo purposes we assume each element (letter) is 1x1 meter.
224     // Sign is placed 0.25 meters above the ground
225
226     ssgBranch *object = new ssgBranch();
227     object->setName( (char *)name.c_str() );
228
229     double width = name.length() / 3.0;
230
231     string material = name;
232
233     point_list nodes;
234     point_list normals;
235     point_list texcoords;
236     int_list vertex_index;
237     int_list normal_index;
238     int_list tex_index;
239
240     nodes.push_back( Point3D( -width, 0, 0.25 ) );
241     nodes.push_back( Point3D( width + 1, 0, 0.25 ) );
242     nodes.push_back( Point3D( -width, 0, 1.25 ) );
243     nodes.push_back( Point3D( width + 1, 0, 1.25 ) );
244
245     normals.push_back( Point3D( 0, -1, 0 ) );
246
247     texcoords.push_back( Point3D( 0, 0, 0 ) );
248     texcoords.push_back( Point3D( 1, 0, 0 ) );
249     texcoords.push_back( Point3D( 0, 1, 0 ) );
250     texcoords.push_back( Point3D( 1, 1, 0 ) );
251
252     vertex_index.push_back( 0 );
253     vertex_index.push_back( 1 );
254     vertex_index.push_back( 2 );
255     vertex_index.push_back( 3 );
256
257     normal_index.push_back( 0 );
258     normal_index.push_back( 0 );
259     normal_index.push_back( 0 );
260     normal_index.push_back( 0 );
261
262     tex_index.push_back( 0 );
263     tex_index.push_back( 1 );
264     tex_index.push_back( 2 );
265     tex_index.push_back( 3 );
266
267     ssgLeaf *leaf = sgMakeLeaf( path, GL_TRIANGLE_STRIP, matlib, material,
268                                 nodes, normals, texcoords,
269                                 vertex_index, normal_index, tex_index,
270                                 false, NULL );
271
272     object->addKid( leaf );
273
274     return object;
275 }