From cd143c15d5b2ea357052606c259a8eba17ce90b2 Mon Sep 17 00:00:00 2001 From: mfranz Date: Sun, 9 Apr 2006 19:51:00 +0000 Subject: [PATCH] rewrite of OBJECT_TAXI_SIGN code. The name is a bit misleading, as this type can also create runway signs. (/me thinks about changing that ...) --- simgear/scene/tgdb/apt_signs.cxx | 257 +++++++++++++++++++++---------- 1 file changed, 179 insertions(+), 78 deletions(-) diff --git a/simgear/scene/tgdb/apt_signs.cxx b/simgear/scene/tgdb/apt_signs.cxx index 5674d7a6..175e5c6f 100644 --- a/simgear/scene/tgdb/apt_signs.cxx +++ b/simgear/scene/tgdb/apt_signs.cxx @@ -27,91 +27,192 @@ #include #include #include +#include +#include #include "apt_signs.hxx" - +#define TAXI "OBJECT_TAXI_SIGN: " +#define RWY "OBJECT_RUNWAY_SIGN: " + + +// for temporary storage of sign elements +struct element_info { + element_info(SGMaterial *m, SGMaterialGlyph *g) : material(m), glyph(g) {} + SGMaterial *material; + SGMaterialGlyph *glyph; +}; + + +// translation table for 'command' to glyph name +struct pair { + const char *keyword; + const char *glyph_name; +} cmds[] = { + {"l", "left"}, + {"lu", "up-left"}, + {"ld", "down-left"}, + {"r", "right"}, + {"ru", "up-right"}, + {"rd", "down-right"}, + {"u", "up"}, + {"ul", "up-left"}, + {"ur", "up-right"}, + {"d", "down"}, + {"dl", "down-left"}, + {"dr", "down-right"}, + {"no-exit", "no-exit"}, + {0, 0}, +}; + + +// Y ... black on yellow -> direction, destination, boundary +// R ... white on red -> mandatory instruction +// L ... yellow on black with frame -> runway/taxiway location +// B ... white on black -> runway distance remaining +// +// u/d/l/r ... up/down/left/right arrow or two-letter combinations +// thereof (ur, dl, ...) +// +// Example: {l}E|{L}[T]|{Y,ur}L|E{r} +// ssgBranch *sgMakeTaxiSign( SGMaterialLib *matlib, const string path, const string content ) { - // for demo purposes we assume each element (letter) is 1x1 meter. - // Sign is placed 0.25 meters above the ground + const double sign_height = 1.0; // meter TODO make configurable + + vector elements; + double total_width = 0.0; + bool cmd = false; + char *newmat = "YellowSign"; ssgBranch *object = new ssgBranch(); - object->setName( (char *)content.c_str() ); - - double offset = content.length() / 2.0; - - for ( unsigned int i = 0; i < content.length(); ++i ) { - string material; - - char item = content[i]; - if ( item == '<' ) { - material = "ArrowL.rgb"; - } else if ( item == '>' ) { - material = "ArrowR.rgb"; - } else if ( item >= 'A' && item <= 'Z' ) { - material = "Letter"; - material += item; - material += ".rgb"; - } else if ( item >= 'a' && item <= 'z' ) { - int tmp = item - 'a'; - char c = 'A' + tmp; - material = "Black"; - material += c; - material += ".rgb"; - } else { - SG_LOG( SG_TERRAIN, SG_ALERT, - "Unknown taxi sign code = '" << item << "' !!!!" ); - return NULL; - } - - point_list nodes; nodes.clear(); - point_list normals; normals.clear(); - point_list texcoords; texcoords.clear(); - int_list vertex_index; vertex_index.clear(); - int_list normal_index; normal_index.clear(); - int_list tex_index; tex_index.clear(); - - nodes.push_back( Point3D( -offset + i, 0, 0.25 ) ); - nodes.push_back( Point3D( -offset + i + 1, 0, 0.25 ) ); - nodes.push_back( Point3D( -offset + i, 0, 1.25 ) ); - nodes.push_back( Point3D( -offset + i + 1, 0, 1.25 ) ); - - normals.push_back( Point3D( 0, -1, 0 ) ); - - texcoords.push_back( Point3D( 0, 0, 0 ) ); - texcoords.push_back( Point3D( 1, 0, 0 ) ); - texcoords.push_back( Point3D( 0, 1, 0 ) ); - texcoords.push_back( Point3D( 1, 1, 0 ) ); - - vertex_index.push_back( 0 ); - vertex_index.push_back( 1 ); - vertex_index.push_back( 2 ); - vertex_index.push_back( 3 ); - - normal_index.push_back( 0 ); - normal_index.push_back( 0 ); - normal_index.push_back( 0 ); - normal_index.push_back( 0 ); - - tex_index.push_back( 0 ); - tex_index.push_back( 1 ); - tex_index.push_back( 2 ); - tex_index.push_back( 3 ); - - ssgLeaf *leaf = sgMakeLeaf( path, GL_TRIANGLE_STRIP, matlib, material, - nodes, normals, texcoords, - vertex_index, normal_index, tex_index, - false, NULL ); - - object->addKid( leaf ); + object->setName((char *)content.c_str()); + SGMaterial *material = matlib->find(newmat); + + for (const char *s = content.data(); *s; s++) { + string name; + const char *newmat = 0; + + if (*s == '{') { + if (cmd) + SG_LOG(SG_TERRAIN, SG_ALERT, TAXI "unexpected { in sign contents"); + cmd = true; + continue; + } else if (*s == '}') { + if (!cmd) + SG_LOG(SG_TERRAIN, SG_ALERT, TAXI "unexpected } in sign contents"); + cmd = false; + continue; + } else if (cmd) { + if (*s == ',') + continue; + else if (*s == 'Y') + newmat = "YellowSign"; + else if (*s == 'R') + newmat = "RedSign"; + else if (*s == 'L') + newmat = "FramedSign"; + else if (*s == 'B') + newmat = "BlackSign"; + else { + // find longest match of cmds[] + int maxlen = 0, len; + for (int i = 0; cmds[i].keyword; i++) { + len = strlen(cmds[i].keyword); + if (!strncmp(s, cmds[i].keyword, len)) { + maxlen = len; + name = cmds[i].glyph_name; + } + } + if (maxlen) + s += maxlen - 1; + } + if (s[1] != ',' && s[1] != '}') + SG_LOG(SG_TERRAIN, SG_ALERT, TAXI "garbage after command `" << s << '\''); + + if (newmat) { + material = matlib->find(newmat); + continue; + } + + if (name.empty()) { + SG_LOG(SG_TERRAIN, SG_ALERT, TAXI "unknown command `" << s << '\''); + continue; + } + } else + name = *s; + + if (!material) { + SG_LOG( SG_TERRAIN, SG_ALERT, TAXI "material doesn't exit"); + continue; + } + + SGMaterialGlyph *glyph = material->get_glyph(name); + if (!glyph) { + SG_LOG( SG_TERRAIN, SG_ALERT, TAXI "unsupported character `" << *s << '\''); + continue; + } + + elements.push_back(new element_info(material, glyph)); + total_width += glyph->get_width() * material->get_xscale(); + } + + double hpos = -total_width / 2; + + sgVec3 normal; + sgSetVec3(normal, 0, -1, 0); + + sgVec4 color; + sgSetVec4(color, 1.0, 1.0, 1.0, 1.0); + + for (unsigned int i = 0; i < elements.size(); i++) { + element_info *element = elements[i]; + + double xoffset = element->glyph->get_left(); + double width = element->glyph->get_width(); + double abswidth = width * element->material->get_xscale(); + + // vertices + ssgVertexArray *vl = new ssgVertexArray(4); + vl->add(hpos, 0, 0); + vl->add(hpos + abswidth, 0, 0); + vl->add(hpos, 0, sign_height); + vl->add(hpos + abswidth, 0, sign_height); + + // texture coordinates + ssgTexCoordArray *tl = new ssgTexCoordArray(4); + tl->add(xoffset, 0); + tl->add(xoffset + width, 0); + tl->add(xoffset, 1); + tl->add(xoffset + width, 1); + + // normals + ssgNormalArray *nl = new ssgNormalArray(1); + nl->add(normal); + + // colors + ssgColourArray *cl = new ssgColourArray(1); + cl->add(color); + + ssgLeaf *leaf = new ssgVtxTable(GL_TRIANGLE_STRIP, vl, nl, tl, cl); + ssgSimpleState *state = element->material->get_state(); + //if (!lighted) + // state->setMaterial(GL_EMISSION, 0, 0, 0, 1); + leaf->setState(state); + + object->addKid(leaf); + hpos += abswidth; + delete element; } return object; } + + + ssgBranch *sgMakeRunwaySign( SGMaterialLib *matlib, const string path, const string name ) { @@ -123,14 +224,14 @@ ssgBranch *sgMakeRunwaySign( SGMaterialLib *matlib, double width = name.length() / 3.0; - string material = name + ".rgb"; + string material = name; - point_list nodes; nodes.clear(); - point_list normals; normals.clear(); - point_list texcoords; texcoords.clear(); - int_list vertex_index; vertex_index.clear(); - int_list normal_index; normal_index.clear(); - int_list tex_index; tex_index.clear(); + point_list nodes; + point_list normals; + point_list texcoords; + int_list vertex_index; + int_list normal_index; + int_list tex_index; nodes.push_back( Point3D( -width, 0, 0.25 ) ); nodes.push_back( Point3D( width + 1, 0, 0.25 ) ); -- 2.39.5