1 // apt_signs.cxx -- build airport signs on the fly
3 // Written by Curtis Olson, started July 2001.
5 // Copyright (C) 2001 Curtis L. Olson - http://www.flightgear.org/~curt
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.
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.
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.
24 # include <simgear_config.h>
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>
33 #include "apt_signs.hxx"
35 #define TAXI "OBJECT_TAXI_SIGN: "
36 #define RWY "OBJECT_RUNWAY_SIGN: "
39 // for temporary storage of sign elements
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());
45 SGMaterialGlyph *glyph;
50 // translation table for 'command' to glyph name
53 const char *glyph_name;
67 {"no-exit", "no-exit"},
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
77 // u/d/l/r ... up/down/left/right arrow or two-letter combinations
78 // thereof (ur, dl, ...)
80 // Example: {l}E|{L}[T]|{Y,ur}L|E{r}
82 ssgBranch *sgMakeTaxiSign( SGMaterialLib *matlib,
83 const string path, const string content )
85 const double sign_height = 1.0; // meter TODO make configurable
87 vector<element_info *> elements;
88 double total_width = 0.0;
90 char *newmat = "YellowSign";
92 ssgBranch *object = new ssgBranch();
93 object->setName((char *)content.c_str());
94 SGMaterial *material = matlib->find(newmat);
96 for (const char *s = content.data(); *s; s++) {
98 const char *newmat = 0;
102 SG_LOG(SG_TERRAIN, SG_ALERT, TAXI "unexpected { in sign contents");
105 } else if (*s == '}') {
107 SG_LOG(SG_TERRAIN, SG_ALERT, TAXI "unexpected } in sign contents");
114 newmat = "YellowSign";
118 newmat = "FramedSign";
120 newmat = "BlackSign";
122 // find longest match of cmds[]
124 for (int i = 0; cmds[i].keyword; i++) {
125 len = strlen(cmds[i].keyword);
126 if (!strncmp(s, cmds[i].keyword, len)) {
128 name = cmds[i].glyph_name;
134 if (s[1] != ',' && s[1] != '}')
135 SG_LOG(SG_TERRAIN, SG_ALERT, TAXI "garbage after command `" << s << '\'');
138 material = matlib->find(newmat);
143 SG_LOG(SG_TERRAIN, SG_ALERT, TAXI "unknown command `" << s << '\'');
150 SG_LOG( SG_TERRAIN, SG_ALERT, TAXI "material doesn't exit");
154 SGMaterialGlyph *glyph = material->get_glyph(name);
156 SG_LOG( SG_TERRAIN, SG_ALERT, TAXI "unsupported character `" << *s << '\'');
160 element_info *e = new element_info(material, glyph);
161 elements.push_back(e);
162 total_width += glyph->get_width() * e->scale;
165 double hpos = -total_width / 2;
168 sgSetVec3(normal, 0, -1, 0);
171 sgSetVec4(color, 1.0, 1.0, 1.0, 1.0);
173 for (unsigned int i = 0; i < elements.size(); i++) {
174 element_info *element = elements[i];
176 double xoffset = element->glyph->get_left();
177 double width = element->glyph->get_width();
178 double abswidth = width * element->scale;
181 ssgVertexArray *vl = new ssgVertexArray(4);
183 vl->add(hpos + abswidth, 0, 0);
184 vl->add(hpos, 0, sign_height);
185 vl->add(hpos + abswidth, 0, sign_height);
187 // texture coordinates
188 ssgTexCoordArray *tl = new ssgTexCoordArray(4);
190 tl->add(xoffset + width, 0);
192 tl->add(xoffset + width, 1);
195 ssgNormalArray *nl = new ssgNormalArray(1);
199 ssgColourArray *cl = new ssgColourArray(1);
202 ssgLeaf *leaf = new ssgVtxTable(GL_TRIANGLE_STRIP, vl, nl, tl, cl);
203 ssgSimpleState *state = element->material->get_state();
205 // state->setMaterial(GL_EMISSION, 0, 0, 0, 1);
206 leaf->setState(state);
208 object->addKid(leaf);
220 ssgBranch *sgMakeRunwaySign( SGMaterialLib *matlib,
221 const string path, const string name )
223 // for demo purposes we assume each element (letter) is 1x1 meter.
224 // Sign is placed 0.25 meters above the ground
226 ssgBranch *object = new ssgBranch();
227 object->setName( (char *)name.c_str() );
229 double width = name.length() / 3.0;
231 string material = name;
235 point_list texcoords;
236 int_list vertex_index;
237 int_list normal_index;
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 ) );
245 normals.push_back( Point3D( 0, -1, 0 ) );
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 ) );
252 vertex_index.push_back( 0 );
253 vertex_index.push_back( 1 );
254 vertex_index.push_back( 2 );
255 vertex_index.push_back( 3 );
257 normal_index.push_back( 0 );
258 normal_index.push_back( 0 );
259 normal_index.push_back( 0 );
260 normal_index.push_back( 0 );
262 tex_index.push_back( 0 );
263 tex_index.push_back( 1 );
264 tex_index.push_back( 2 );
265 tex_index.push_back( 3 );
267 ssgLeaf *leaf = sgMakeLeaf( path, GL_TRIANGLE_STRIP, matlib, material,
268 nodes, normals, texcoords,
269 vertex_index, normal_index, tex_index,
272 object->addKid( leaf );