FlightGear next
AirportBuilder.cxx
Go to the documentation of this file.
1/*
2 * SPDX-FileName: AirportBuilder.cxx
3 * SPDX-FileComment: Builder to create airports based on airport data for rendering in the scenery
4 * SPDX-FileCopyrightText: Copyright (C) 2020 Stuart Buchanan stuart13@gmail.com
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 */
7
8#include <algorithm>
9
10#include <osgDB/Registry>
11#include <osgUtil/Tessellator>
12#include <osgUtil/DelaunayTriangulator>
13
14#include <osg/Geode>
15#include <osg/Geometry>
16#include <osgTerrain/Terrain>
17#include <osgTerrain/TerrainTechnique>
18
19#include <simgear/scene/material/Effect.hxx>
20#include <simgear/scene/material/EffectGeode.hxx>
21#include <simgear/scene/model/BoundingVolumeBuildVisitor.hxx>
22#include <simgear/scene/model/ModelRegistry.hxx>
23#include <simgear/scene/tgdb/VPBTechnique.hxx>
24#include <simgear/scene/util/OsgMath.hxx>
25#include <simgear/scene/util/SGReaderWriterOptions.hxx>
26#include <simgear/scene/util/SGNodeMasks.hxx>
27
29#include <Main/globals.hxx>
30#include <Scenery/scenery.hxx>
31#include "airport.hxx"
32#include "runways.hxx"
33#include "pavement.hxx"
34
35#include "AirportBuilder.hxx"
36
37using namespace osg;
38using namespace simgear;
39
40namespace flightgear
41{
42
44{
45 supportsExtension("icao", "Dummy name to build an airport from apt.dat");
46}
47
51
52const char* AirportBuilder::className() const
53{
54 return "Airport Builder";
55}
56
57osgDB::ReaderWriter::ReadResult AirportBuilder::readNode(const std::string& fileName,
58 const osgDB::Options* options) const
59{
60 SGPath aptFile = SGPath(fileName);
61
62 if (! aptFile.isFile()) {
63 // Search for the file if we don't have a full path.
64 auto pathList = options->getDatabasePathList();
65 for(auto itr = pathList.begin(); itr != pathList.end(); ++itr) {
66 aptFile = SGPath(*itr, fileName);
67 if (aptFile.isFile()) break;
68 }
69 }
70
71 if (! aptFile.isFile()) return ReadResult::FILE_NOT_HANDLED;;
72
73 const std::string airportId = aptFile.file_base();
74 APTLoader aptLoader;
75
76 const FGAirport* airport = aptLoader.loadAirportFromFile(
77 airportId, {aptFile, SGPath()}); // maybe provide a path if this is used
78 if (! airport) return ReadResult::FILE_NOT_HANDLED;
79
80 SG_LOG( SG_TERRAIN, SG_DEBUG, "Building airport : " << airportId << " " << airport->getName());
81 SG_LOG( SG_TERRAIN, SG_DEBUG, "Lat/Lon : " << airport->getLatitude() << ", " << airport->getLongitude());
82 SG_LOG( SG_TERRAIN, SG_DEBUG, "Elevation : " << airport->getElevation());
83 SG_LOG( SG_TERRAIN, SG_DEBUG, "Runways : " << airport->numRunways());
84 SG_LOG( SG_TERRAIN, SG_DEBUG, "Helipads : " << airport->numHelipads());
85 SG_LOG( SG_TERRAIN, SG_DEBUG, "Taxiways : " << airport->numTaxiways());
86 SG_LOG( SG_TERRAIN, SG_DEBUG, "Pavements : " << airport->numPavements());
87 SG_LOG( SG_TERRAIN, SG_DEBUG, "Line Features : " << airport->numLineFeatures());
88
89 const SGGeod zeroAltitudeCenter = SGGeod::fromDegM(airport->getLongitude(), airport->getLatitude(), 0.0f);
90
91 const SGVec3f center = SGVec3f::fromGeod(zeroAltitudeCenter);
92
93 // Create a matrix operation that will center the airport facing the z axis
94 // We cannot also perform the translate to the center of the airport as we
95 // hit floating point precision issues, so we do that separately.
96 osg::Matrixd mat = osg::Matrix(toOsg(SGQuatd::fromLonLat(zeroAltitudeCenter)));
97 mat.preMultRotate(osg::Quat(0.0, 1.0, 0.0, 0.0));
98
99 std::vector<osg::Node*> nodeList;
100 osg::Group* group = new osg::Group();
101
102 // Build the boundary
103 auto boundaryList = airport->getBoundary();
104 std::for_each( boundaryList.begin(),
105 boundaryList.end(),
106 [&, mat, center, options] (FGPavementRef p) { group->addChild(this->createBoundary(mat, center, p, options)); } );
107
108 // Build the pavements
109 auto pavementlist = airport->getPavements();
110 std::for_each( pavementlist.begin(),
111 pavementlist.end(),
112 [&, mat, center, options] (FGPavementRef p) { group->addChild(this->createPavement(mat, center, p, options)); } );
113
114 // Build the runways
115 auto runwaylist = airport->getRunways();
116 std::for_each( runwaylist.begin(),
117 runwaylist.end(),
118 [&, mat, center, options] (FGRunwayRef p) { group->addChild(this->createRunway(mat, center, p, options)); } );
119
120 // Build line features
121 auto lineList = airport->getLineFeatures();
122 std::for_each( lineList.begin(),
123 lineList.end(),
124 [&, mat, center, options] (FGPavementRef p) { group->addChild(this->createLine(mat, center, p, options)); } );
125
126 // Place the airport in the correct location.
127 osg::Matrix matrix = makeZUpFrame(SGGeod::fromDegFt(airport->getLongitude(), airport->getLatitude(), airport->getElevation()));
128 osg::MatrixTransform* matrixTransform;
129 matrixTransform = new osg::MatrixTransform(matrix);
130 matrixTransform->setDataVariance(osg::Object::STATIC);
131 matrixTransform->addChild(group);
132
133 return matrixTransform;
134}
135
136osg::Node* AirportBuilder::createRunway(const osg::Matrixd mat, const SGVec3f center, const FGRunwayRef runway, const osgDB::Options* options) const
137{
138 std::vector<SGGeod> nodes;
139 nodes.push_back(runway->pointOffCenterline(0.0, -0.5 * runway->widthM()));
140 nodes.push_back(runway->pointOffCenterline(0.0, 0.5 * runway->widthM()));
141 nodes.push_back(runway->pointOffCenterline(runway->lengthM(), 0.5 * runway->widthM()));
142 nodes.push_back(runway->pointOffCenterline(runway->lengthM(), -0.5 * runway->widthM()));
143
144 osg::Vec3Array* points = new osg::Vec3Array;
145 points->reserve(nodes.size());
146 std::transform( nodes.begin(),
147 nodes.end(),
148 std::back_inserter(*points),
149 [mat, center](SGGeod n) {
150 return mat * toOsg(SGVec3f::fromGeod(n) - center) + osg::Vec3f(0,0, RUNWAY_OFFSET);
151 }
152 );
153
154 osg::ref_ptr<osgUtil::DelaunayTriangulator> triangulator = new osgUtil::DelaunayTriangulator;
155 triangulator->setInputPointArray(points);
156 triangulator->triangulate();
157
158 osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
159 geometry->setVertexArray(points);
160 geometry->addPrimitiveSet(triangulator->getTriangles()); // triangles with constraint cut
161
162 osg::Vec3Array* n = new osg::Vec3Array;
163 n->push_back(osg::Vec3f(0.0f, 0.0f, 1.0f));
164
165 osg::Vec4Array* c = new osg::Vec4Array;
166 c->push_back(osg::Vec4f(1.0f, 1.0f, 1.0f, 1.0f));
167
168 geometry->setColorArray(c, osg::Array::BIND_OVERALL);
169 geometry->setNormalArray(n, osg::Array::BIND_OVERALL);
170
171 EffectGeode* geode = new EffectGeode;
172 ref_ptr<Effect> effect = getMaterialEffect("pa_rest", options);
173 geode->setEffect(effect.get());
174 geode->addDrawable(geometry);
175
176 return geode;
177}
178
179osg::Node* AirportBuilder::createPavement(const osg::Matrixd mat, const SGVec3f center, const FGPavementRef pavement, const osgDB::Options* options) const
180{
181 const FGPavement::NodeList nodes = pavement->getNodeList();
182 if (nodes.size() < 2) return NULL;
183
184 osg::ref_ptr<osgUtil::Tessellator> tessellator = new osgUtil::Tessellator;
185 tessellator->setBoundaryOnly(false);
186 tessellator->beginTessellation();
187 tessellator->beginContour();
188
189 // Track the previous vertex for bezier curve generation.
190 osg::Vec3f* previous = NULL;
191
192 // Bezier control. Bezier curve is node n-1 -> n -> n+1 so need to store for
193 // handling the next node in addition to generating for the BezierNode itself.
194 bool bezier = false;
195 osg::Vec3f control;
196
197 auto itr = nodes.begin();
198 for (; itr < nodes.end(); ++itr) {
199 FGPavement::NodeBase* node = *itr;
200
201 osg::Vec3f* v = new osg::Vec3f(mat * toOsg(SGVec3f::fromGeod(node->mPos) - center) + osg::Vec3f(0,0, PAVEMENT_OFFSET));
202
203 if (FGPavement::BezierNode *bez = dynamic_cast<FGPavement::BezierNode*>(node)) {
204 // Store the bezier control node for generation when we know the next node.
205 control = mat * toOsg(SGVec3f::fromGeod(bez->mControl) - center) + osg::Vec3f(0,0, PAVEMENT_OFFSET);
206 bezier = true;
207
208 // Generate from the last node to this one, reflecting the control point
209 for (float t = 0.05f; t < 0.95f; t += 0.05f ) {
210
211 osg::Vec3f p0 = osg::Vec3f();
212 if (previous != NULL) p0 = *previous;
213 osg::Vec3f p1 = *v + *v - control;
214 osg::Vec3f p2 = *v;
215
216 osg::Vec3f* b = new osg::Vec3f(p1 +
217 (p0 - p1)*(1.0f - t)*(1.0f - t) +
218 (p2 - p1)*t*t);
219
220 tessellator->addVertex(b);
221 }
222
223 tessellator->addVertex(v);
224
225 } else if (bezier) {
226 // Last node was a BezierNode, so generate the required bezier curve to this node.
227 for (float t = 0.05f; t < 0.95f; t += 0.05f ) {
228 osg::Vec3f p0 = *previous;
229 osg::Vec3f p1 = control;
230 osg::Vec3f p2 = *v;
231
232 osg::Vec3f* b = new osg::Vec3f(p1 +
233 (p0 - p1)*(1.0f - t)*(1.0f - t) +
234 (p2 - p1)*t*t);
235
236 tessellator->addVertex(b);
237 }
238
239 bezier = false;
240 tessellator->addVertex(v);
241 } else {
242 // SimpleNode
243 tessellator->addVertex(v);
244 }
245 previous = v;
246 if (node->mClose) {
247 tessellator->endContour();
248 tessellator->beginContour();
249 }
250 }
251
252 tessellator->endContour();
253 tessellator->endTessellation();
254
255 // Build the geometry based on the tessellation results.
256
257 osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
258 auto primList = tessellator->getPrimList();
259 osg::Vec3Array* points = new osg::Vec3Array();
260 osg::Vec3Array* normals = new osg::Vec3Array();
261 osg::Vec2Array* texCoords = new osg::Vec2Array();
262 geometry->setVertexArray(points);
263 unsigned int idx = 0;
264 auto primItr = primList.begin();
265 for (; primItr < primList.end(); ++ primItr) {
266 auto vertices = (*primItr)->_vertices;
267 std::for_each( vertices.begin(),
268 vertices.end(),
269 [points, texCoords, normals](auto v) {
270 points->push_back(*v);
271 texCoords->push_back(osg::Vec2f(v->x(), v->y()));
272 normals->push_back(osg::Vec3f(0.0, 0.0, 1.0));
273 }
274 );
275
276 geometry->addPrimitiveSet(new osg::DrawArrays((*primItr)->_mode, idx, vertices.size()));
277 idx += vertices.size();
278 }
279
280 osg::Vec4Array* c = new osg::Vec4Array;
281 c->push_back(osg::Vec4f(1.0f, 1.0f, 1.0f, 1.0f));
282
283 geometry->setColorArray(c, osg::Array::BIND_OVERALL);
284 geometry->setNormalArray(normals, osg::Array::BIND_PER_VERTEX);
285 geometry->setTexCoordArray(0, texCoords, osg::Array::BIND_PER_VERTEX);
286
287 EffectGeode* geode = new EffectGeode;
288 ref_ptr<Effect> effect = getMaterialEffect("Asphalt", options);
289 geode->setEffect(effect.get());
290 geode->addDrawable(geometry);
291
292 return geode;
293}
294
295osg::Node* AirportBuilder::createBoundary(const osg::Matrixd mat, const SGVec3f center, const FGPavementRef pavement, const osgDB::Options* options) const
296{
297 const FGPavement::NodeList nodes = pavement->getNodeList();
298
299 if (nodes.size() == 0) return NULL;
300
301 osg::ref_ptr<osgUtil::Tessellator> tessellator = new osgUtil::Tessellator;
302 tessellator->setBoundaryOnly(false);
303 tessellator->beginTessellation();
304 tessellator->beginContour();
305
306 // Track the previous vertex for bezier curve generation.
307 osg::Vec3f* previous = NULL;
308
309 // Bezier control. Bezier curve is node n-1 -> n -> n+1 so need to store for
310 // handling the next node in addition to generating for the BezierNode itself.
311 bool bezier = false;
312 osg::Vec3f control;
313
314 auto itr = nodes.begin();
315 for (; itr < nodes.end(); ++itr) {
316 FGPavement::NodeBase* node = *itr;
317
318 osg::Vec3f* v = new osg::Vec3f(mat * toOsg(SGVec3f::fromGeod(node->mPos) - center) + osg::Vec3f(0,0, BOUNDARY_OFFSET));
319
320 if (FGPavement::BezierNode *bez = dynamic_cast<FGPavement::BezierNode*>(node)) {
321 // Store the bezier control node for generation when we know the next node.
322 control = osg::Vec3f(mat * toOsg(SGVec3f::fromGeod(bez->mControl) - center) + osg::Vec3f(0,0, BOUNDARY_OFFSET));
323 bezier = true;
324
325 // Generate from the last node to this one, reflecting the control point
326 for (float t = 0.05f; t < 0.95f; t += 0.05f ) {
327 osg::Vec3f p0 = osg::Vec3f();
328 if (previous != NULL) p0 = *previous;
329 osg::Vec3f p1 = *v + *v - control;
330 osg::Vec3f p2 = *v;
331
332 osg::Vec3f* b = new osg::Vec3f(p1 +
333 (p0 - p1)*(1.0f - t)*(1.0f - t) +
334 (p2 - p1)*t*t);
335
336 tessellator->addVertex(b);
337 }
338
339 tessellator->addVertex(v);
340
341 } else if (bezier) {
342 // Last node was a BezierNode, so generate the required bezier curve to this node.
343 for (float t = 0.05f; t < 0.95f; t += 0.05f ) {
344 osg::Vec3f p0 = *previous;
345 osg::Vec3f p1 = control;
346 osg::Vec3f p2 = *v;
347
348 osg::Vec3f* b = new osg::Vec3f(p1 +
349 (p0 - p1)*(1.0f - t)*(1.0f - t) +
350 (p2 - p1)*t*t);
351
352 tessellator->addVertex(b);
353 }
354
355 bezier = false;
356 tessellator->addVertex(v);
357 } else {
358 // SimpleNode
359 tessellator->addVertex(v);
360 }
361
362 previous = v;
363 if (node->mClose) {
364 tessellator->endContour();
365 tessellator->beginContour();
366 }
367 }
368
369 tessellator->endContour();
370 tessellator->endTessellation();
371
372 // Build the geometry based on the tessellation results.
373 osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
374 auto primList = tessellator->getPrimList();
375 osg::Vec3Array* points = new osg::Vec3Array();
376 geometry->setVertexArray(points);
377 unsigned int idx = 0;
378 auto primItr = primList.begin();
379 for (; primItr < primList.end(); ++ primItr) {
380 auto vertices = (*primItr)->_vertices;
381 std::for_each( vertices.begin(),
382 vertices.end(),
383 [points](auto v) { points->push_back(*v); }
384 );
385
386 geometry->addPrimitiveSet(new osg::DrawArrays((*primItr)->_mode, idx, vertices.size()));
387 idx += vertices.size();
388 }
389
390 osg::Vec3Array* n = new osg::Vec3Array;
391 n->push_back(osg::Vec3f(0.0, 0.0, 1.0));
392
393 osg::Vec4Array* c = new osg::Vec4Array;
394 c->push_back(osg::Vec4f(1.0f, 1.0f, 1.0f, 1.0f));
395
396 geometry->setColorArray(c, osg::Array::BIND_OVERALL);
397 geometry->setNormalArray(n, osg::Array::BIND_OVERALL);
398
399 EffectGeode* geode = new EffectGeode;
400 ref_ptr<Effect> effect = getMaterialEffect("Default", options);
401 geode->setEffect(effect.get());
402 geode->addDrawable(geometry);
403
404 return geode;
405}
406
407osg::Node* AirportBuilder::createLine(const osg::Matrixd mat, const SGVec3f center, const FGPavementRef line, const osgDB::Options* options) const
408{
409 const FGPavement::NodeList nodes = line->getNodeList();
410
411 if (nodes.size() == 0) return NULL;
412
413 // Track the previous vertex for bezier curve generation.
414 osg::Vec3f previous;
415
416 // Track along the vertex list to create the correct Drawables
417 unsigned int idx = 0;
418 unsigned int length = 0;
419
420 // Track the last set line code
421 unsigned int paintCode = 0;
422
423 unsigned int lines = 0;
424
425 // Bezier control. Bezier curve is node n-1 -> n -> n+1 so need to store for
426 // handling the next node in addition to generating for the BezierNode itself.
427 bool bezier = false;
428 osg::Vec3f control;
429
430 osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
431 osg::Vec3Array* points = new osg::Vec3Array();
432 geometry->setVertexArray(points);
433
434 osg::Vec3Array* n = new osg::Vec3Array;
435 n->push_back(osg::Vec3f(0.0, 0.0, 1.0));
436 geometry->setNormalArray(n, osg::Array::BIND_OVERALL);
437
438 osg::Vec4Array* c = new osg::Vec4Array;
439 geometry->setColorArray(c, osg::Array::BIND_PER_VERTEX);
440
441 auto itr = nodes.begin();
442 for (; itr < nodes.end(); ++itr) {
443 FGPavement::NodeBase* node = *itr;
444 osg::Vec3f v = osg::Vec3f(mat * toOsg(SGVec3f::fromGeod(node->mPos) - center) + osg::Vec3f(0,0, MARKING_OFFSET));
445
446 if (node->mPaintCode != 0) paintCode = node->mPaintCode;
447
448 if (FGPavement::BezierNode *bez = dynamic_cast<FGPavement::BezierNode*>(node)) {
449 // Store the bezier control node for generation when we know the next node.
450 control = osg::Vec3f(mat * toOsg(SGVec3f::fromGeod(bez->mControl) - center) + osg::Vec3f(0,0, MARKING_OFFSET));
451 bezier = true;
452
453 // Generate from the last node to this one, reflecting the control point
454 for (float t = 0.05f; t < 0.95f; t += 0.05f ) {
455 osg::Vec3f p0 = previous;
456 osg::Vec3f p1 = v + v - control;
457 osg::Vec3f p2 = v;
458
459 osg::Vec3f b =
460 osg::Vec3f(p1 +
461 (p0 - p1)*(1.0f - t)*(1.0f - t) +
462 (p2 - p1)*t*t);
463
464 points->push_back(b);
465 c->push_back(getLineColor(paintCode));
466 length += 1;
467 }
468
469 points->push_back(v);
470 c->push_back(getLineColor(paintCode));
471 length += 1;
472
473 if (node->mClose && node->mLoop) {
474 // Special case if this is the end node and it loops back to the start.
475 // In this case there is not going to be a forward node to generate, so
476 // we need to generate the bezier curve now.
477
478 for (float t = 0.05f; t < 0.95f; t += 0.05f ) {
479 osg::Vec3f p0 = v;
480 osg::Vec3f p1 = control;
481 osg::Vec3f p2 = points->at(idx);
482
483 osg::Vec3f b =
484 osg::Vec3f(p1 +
485 (p0 - p1)*(1.0f - t)*(1.0f - t) +
486 (p2 - p1)*t*t);
487
488 points->push_back(b);
489 c->push_back(getLineColor(paintCode));
490 length += 1;
491 }
492
493 bezier = false;
494 }
495
496 } else if (bezier) {
497 // Last node was a BezierNode, so generate the required bezier curve to this node.
498 for (float t = 0.05f; t < 0.95f; t += 0.05f ) {
499 osg::Vec3f p0 = previous;
500 osg::Vec3f p1 = control;
501 osg::Vec3f p2 = v;
502
503 osg::Vec3f b =
504 osg::Vec3f(p1 +
505 (p0 - p1)*(1.0f - t)*(1.0f - t) +
506 (p2 - p1)*t*t);
507
508 points->push_back(b);
509 c->push_back(getLineColor(paintCode));
510 length += 1;
511 }
512
513 bezier = false;
514 } else {
515 // SimpleNode
516 points->push_back(v);
517 c->push_back(getLineColor(paintCode));
518 length += 1;
519 }
520
521 previous = v;
522
523 if (node->mClose) {
524 geometry->addPrimitiveSet(new osg::DrawArrays(
525 node->mLoop ? GL_LINE_LOOP : GL_LINE_STRIP,
526 idx,
527 length));
528 idx += length;
529 length = 0;
530 lines++;
531 }
532 }
533
534 // We should be using different Effects for different lines, and/or
535 // parameterizing a single Effect to encode some line type information so
536 // we can use a single Effect for all lines.
537 EffectGeode* geode = new EffectGeode;
538 ref_ptr<Effect> effect = getMaterialEffect("lf_sng_solid_yellow", options);
539 geode->setEffect(effect.get());
540 geode->addDrawable(geometry);
541
542
543 return geode;
544}
545
546osg::Vec4f AirportBuilder::getLineColor(const int aPaintCode) const
547{
548 if (aPaintCode == 1) return osg::Vec4f(0.7f, 0.7f, 0.3f, 1.0f); // Solid yellow
549 if (aPaintCode == 2) return osg::Vec4f(0.7f, 0.7f, 0.3f, 1.0f); // Broken yellow
550 if (aPaintCode == 3) return osg::Vec4f(0.9f, 0.9f, 0.3f, 1.0f); // Double yellow
551 if (aPaintCode == 4) return osg::Vec4f(0.9f, 0.9f, 0.3f, 1.0f); // Two broken yellow lines and two solid yellow lines. Broken line on left of string.
552 if (aPaintCode == 5) return osg::Vec4f(0.9f, 0.9f, 0.3f, 1.0f); // Broken yellow line with parallel solid yellow line
553 if (aPaintCode == 6) return osg::Vec4f(0.5f, 0.5f, 0.0f, 1.0f); // Yellow cross-hatched
554 if (aPaintCode == 7) return osg::Vec4f(0.9f, 0.9f, 0.3f, 1.0f); // Solid Yellow with broken yellow on each side
555 if (aPaintCode == 8) return osg::Vec4f(0.9f, 0.9f, 0.3f, 1.0f); // Widely separated, broken yellow line
556 if (aPaintCode == 9) return osg::Vec4f(0.9f, 0.9f, 0.3f, 1.0f); // Widely separated, broken double yellow line
557
558 // As above with black border
559 if (aPaintCode == 51) return osg::Vec4f(0.7f, 0.7f, 0.3f, 1.0f); // Solid yellow
560 if (aPaintCode == 52) return osg::Vec4f(0.7f, 0.7f, 0.3f, 1.0f); // Broken yellow
561 if (aPaintCode == 53) return osg::Vec4f(0.9f, 0.9f, 0.3f, 1.0f); // Double yellow
562 if (aPaintCode == 54) return osg::Vec4f(0.9f, 0.9f, 0.3f, 1.0f); // Two broken yellow lines and two solid yellow lines. Broken line on left of string.
563 if (aPaintCode == 55) return osg::Vec4f(0.9f, 0.9f, 0.3f, 1.0f); // Broken yellow line with parallel solid yellow line
564 if (aPaintCode == 56) return osg::Vec4f(0.5f, 0.5f, 0.0f, 1.0f); // Yellow cross-hatched
565 if (aPaintCode == 57) return osg::Vec4f(0.9f, 0.9f, 0.3f, 1.0f); // Solid Yellow with broken yellow on each side
566 if (aPaintCode == 58) return osg::Vec4f(0.9f, 0.9f, 0.3f, 1.0f); // Widely separated, broken yellow line
567 if (aPaintCode == 59) return osg::Vec4f(0.9f, 0.9f, 0.3f, 1.0f); // Widely separated, broken double yellow line
568
569 if (aPaintCode == 20) return osg::Vec4f(0.8f, 0.8f, 0.8f, 1.0f); // Solid White
570 if (aPaintCode == 21) return osg::Vec4f(0.7f, 0.7f, 0.7f, 1.0f); // White chequerboard
571 if (aPaintCode == 22) return osg::Vec4f(0.6f, 0.6f, 0.6f, 1.0f); // Broken white line
572
573 return osg::Vec4f(0.7f, 0.7f, 0.3f, 1.0f); // Default (probably an error), so red
574}
575
576osg::ref_ptr<Effect> AirportBuilder::getMaterialEffect(std::string material, const osgDB::Options* options) const
577{
578 ref_ptr<Effect> effect;
579 SGPropertyNode_ptr effectProp = new SGPropertyNode();
580
581 osg::ref_ptr<SGReaderWriterOptions> sgOpts(SGReaderWriterOptions::copyOrCreate(options));
582
583 if (sgOpts->getMaterialLib()) {
584 const SGGeod loc = SGGeod(sgOpts->getLocation());
585 SGMaterialCache* matcache = sgOpts->getMaterialLib()->generateMatCache(loc, sgOpts);
586 SGMaterial* mat = matcache->find(material);
587 delete matcache;
588
589 if (mat) {
590 return mat->get_effect();
591 }
592 }
593
594 SG_LOG( SG_TERRAIN, SG_ALERT, "Unable to get effect for " << material);
595 makeChild(effectProp, "inherits-from")->setStringValue("Effects/terrain-default");
596 effectProp->addChild("default")->setBoolValue(true);
597 effect = makeEffect(effectProp, true, sgOpts);
598 return effect;
599}
600
601
602}
603typedef simgear::ModelRegistryCallback<simgear::DefaultProcessPolicy, simgear::NoCachePolicy,
604 simgear::NoOptimizePolicy,
605 simgear::NoSubstitutePolicy, simgear::BuildGroupBVHPolicy>
607
608namespace
609{
610 osgDB::RegisterReaderWriterProxy<flightgear::AirportBuilder> g_readerAirportBuilder;
611 simgear::ModelRegistryCallbackProxy<AirportCallback> g_icaoCallbackProxy("icao");
612}
simgear::ModelRegistryCallback< simgear::DefaultProcessPolicy, simgear::NoCachePolicy, simgear::NoOptimizePolicy, simgear::NoSubstitutePolicy, simgear::BuildGroupBVHPolicy > AirportCallback
#define p2(x, y)
#define p(x)
bool options(int, char **)
Definition JSBSim.cpp:568
SGSharedPtr< FGPavement > FGPavementRef
SGSharedPtr< FGRunway > FGRunwayRef
unsigned int numRunways() const
Definition airport.cxx:102
FGPavementList getLineFeatures() const
Definition airport.cxx:391
unsigned int numTaxiways() const
Definition airport.cxx:330
double getElevation() const
Definition airport.hxx:61
double getLatitude() const
Definition airport.hxx:59
double getLongitude() const
Definition airport.hxx:57
FGPavementList getPavements() const
Definition airport.cxx:357
unsigned int numLineFeatures() const
Definition airport.cxx:385
unsigned int numHelipads() const
Definition airport.cxx:109
FGPavementList getBoundary() const
Definition airport.cxx:374
unsigned int numPavements() const
Definition airport.cxx:351
FGRunwayList getRunways() const
Retrieve all runways at the airport.
Definition airport.cxx:300
const std::string & getName() const
Definition airport.hxx:54
std::vector< SGSharedPtr< NodeBase > > NodeList
Definition pavement.hxx:54
const FGAirport * loadAirportFromFile(const std::string &id, const NavDataCache::SceneryLocation &sceneryLocation)
virtual const char * className() const
virtual ReadResult readNode(const std::string &fileName, const osgDB::Options *options) const
FlightPlan.hxx - defines a full flight-plan object, including departure, cruise, arrival information ...
Definition Addon.cxx:53
Definition AIBase.hxx:25