1
0
Fork 0

Marker pins

This commit is contained in:
Tobias Dammers 2022-01-15 18:20:35 +01:00 committed by James Turner
parent af0df69126
commit fe8b7bea21
5 changed files with 171 additions and 10 deletions

View file

@ -24,8 +24,10 @@
#include <Main/fg_props.hxx>
#include <Scenery/scenery.hxx>
#include <Scenery/marker.hxx>
#include <osg/ProxyNode>
#include <osgText/String>
#include "modelmgr.hxx"
@ -121,6 +123,8 @@ FGModelMgr::add_model (SGPropertyNode * node)
SG_LOG(SG_AIRCRAFT, SG_WARN, "add_model called with empty path");
return;
}
const std::string internal_model{node->getStringValue("internal-model", "external")};
osg::Node *object;
@ -128,21 +132,38 @@ FGModelMgr::add_model (SGPropertyNode * node)
instance->loaded_node = node->addChild("loaded");
instance->loaded_node->setBoolValue(false);
try {
if (internal_model == "marker") {
std::string label{node->getStringValue("marker/text", "MARKER")};
float r = node->getFloatValue("marker/color[0]", 1.0f);
float g = node->getFloatValue("marker/color[1]", 1.0f);
float b = node->getFloatValue("marker/color[2]", 1.0f);
osg::Vec4f color(r, g, b, 1.0f);
float font_size = node->getFloatValue("marker/size", 1.0f);
float pin_height = node->getFloatValue("marker/height", 1000.0f);
float tip_height = node->getFloatValue("marker/tip-height", 0.0f);
object = fgCreateMarkerNode(osgText::String(label, osgText::String::ENCODING_UTF8), font_size, pin_height, tip_height, color);
}
else if (internal_model == "external") {
try {
std::string fullPath = simgear::SGModelLib::findDataFile(model_path);
if (fullPath.empty()) {
SG_LOG(SG_AIRCRAFT, SG_ALERT, "add_model: unable to find model with name '" << model_path << "'");
return;
SG_LOG(SG_AIRCRAFT, SG_ALERT, "add_model: unable to find model with name '" << model_path << "'");
return;
}
object = SGModelLib::loadDeferredModel(fullPath, globals->get_props());
} catch (const sg_throwable& t) {
SG_LOG(SG_AIRCRAFT, SG_ALERT, "Error loading " << model_path << ":\n "
<< t.getFormattedMessage() << t.getOrigin());
return;
} catch (const sg_throwable& t) {
SG_LOG(SG_AIRCRAFT, SG_ALERT, "Error loading " << model_path << ":\n "
<< t.getFormattedMessage() << t.getOrigin());
return;
}
}
const std::string modelName{node->getStringValue("name", model_path.c_str())};
SG_LOG(SG_AIRCRAFT, SG_INFO, "Adding model " << modelName);
else {
object = new osg::Node;
SG_LOG(SG_AIRCRAFT, SG_WARN, "Unsupported internal-model type " << internal_model);
}
const std::string modelName{node->getStringValue("name", model_path.c_str())};
SG_LOG(SG_AIRCRAFT, SG_INFO, "Adding model " << modelName);
SGModelPlacement *model = new SGModelPlacement;
instance->model = model;

View file

@ -9,6 +9,7 @@ set(SOURCES
tilecache.cxx
tileentry.cxx
tilemgr.cxx
marker.cxx
)
set(HEADERS
@ -21,6 +22,7 @@ set(HEADERS
tilecache.hxx
tileentry.hxx
tilemgr.hxx
marker.hxx
)
flightgear_component(Scenery "${SOURCES}" "${HEADERS}")

119
src/Scenery/marker.cxx Normal file
View file

@ -0,0 +1,119 @@
// marker.cxx - 3D Marker pins in FlightGear
// Copyright (C) 2022 Tobias Dammers
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "Scenery/marker.hxx"
#include <simgear/scene/util/SGNodeMasks.hxx>
#include <simgear/scene/util/SGReaderWriterOptions.hxx>
#include <simgear/scene/material/Effect.hxx>
#include <simgear/scene/material/EffectGeode.hxx>
#include <osg/Geometry>
#include <osg/Material>
#include <osg/Node>
#include <osg/Billboard>
#include <osgText/Text>
#include <osgText/String>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <osgDB/Registry>
osg::Node* fgCreateMarkerNode(const osgText::String& label, float font_size, float pin_height, float tip_height, const osg::Vec4f& color)
{
auto mainNode = new osg::Group;
auto textNode = new osg::Billboard;
mainNode->addChild(textNode);
textNode->setMode(osg::Billboard::AXIAL_ROT);
auto text = new osgText::Text;
text->setText(label);
text->setAlignment(osgText::Text::CENTER_BOTTOM);
text->setAxisAlignment(osgText::Text::XZ_PLANE);
text->setFont("Fonts/LiberationFonts/LiberationSans-Regular.ttf");
// text->setCharacterSizeMode(osgText::Text::OBJECT_COORDS_WITH_MAXIMUM_SCREEN_SIZE_CAPPED_BY_FONT_HEIGHT);
text->setCharacterSize(font_size, 1.0f);
text->setFontResolution(std::max(32.0f, font_size), std::max(32.0f, font_size));
text->setColor(color);
text->setPosition(osg::Vec3(0, 0, pin_height));
text->setBackdropType(osgText::Text::OUTLINE);
text->setBackdropColor(osg::Vec4(0, 0, 0, 0.75));
textNode->addDrawable(text);
float top_spacing = font_size * 0.25;
if (pin_height - top_spacing > tip_height) {
osg::Vec4f solid = color;
osg::Vec4f transparent = color;
osg::Vec3f nvec(0, 1, 0);
solid[3] = 1.0f;
transparent[3] = 0.0f;
auto geoNode = new simgear::EffectGeode;
mainNode->addChild(geoNode);
auto pinGeo = new osg::Geometry;
osg::Vec3Array* vtx = new osg::Vec3Array;
osg::Vec3Array* nor = new osg::Vec3Array;
osg::Vec4Array* rgb = new osg::Vec4Array;
nor->push_back(nvec);
vtx->push_back(osg::Vec3f(0, 0, tip_height));
rgb->push_back(solid);
vtx->push_back(osg::Vec3f(-font_size * 0.125, 0, pin_height - top_spacing));
rgb->push_back(transparent);
vtx->push_back(osg::Vec3f(0, 0, tip_height));
rgb->push_back(solid);
vtx->push_back(osg::Vec3f(0, font_size * 0.125, pin_height - top_spacing));
rgb->push_back(transparent);
vtx->push_back(osg::Vec3f(0, 0, tip_height));
rgb->push_back(solid);
vtx->push_back(osg::Vec3f(font_size * 0.125, 0, pin_height - top_spacing));
rgb->push_back(transparent);
vtx->push_back(osg::Vec3f(0, 0, tip_height));
rgb->push_back(solid);
vtx->push_back(osg::Vec3f(0, -font_size * 0.125, pin_height - top_spacing));
rgb->push_back(transparent);
vtx->push_back(osg::Vec3f(0, 0, tip_height));
rgb->push_back(solid);
vtx->push_back(osg::Vec3f(-font_size * 0.125, 0, pin_height - top_spacing));
rgb->push_back(transparent);
pinGeo->setVertexArray(vtx);
pinGeo->setColorArray(rgb, osg::Array::BIND_PER_VERTEX);
pinGeo->setNormalArray(nor, osg::Array::BIND_OVERALL);
pinGeo->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUAD_STRIP, 0, vtx->size()));
geoNode->addDrawable(pinGeo);
auto stateSet = geoNode->getOrCreateStateSet();
stateSet->setMode(GL_FOG, osg::StateAttribute::OFF);
stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
stateSet->setMode(GL_BLEND, osg::StateAttribute::OFF);
stateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::ON);
stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON);
osg::ref_ptr<simgear::SGReaderWriterOptions> opt;
opt = simgear::SGReaderWriterOptions::copyOrCreate(osgDB::Registry::instance()->getOptions());
simgear::Effect* effect = simgear::makeEffect("Effects/marker-pin", true, opt);
if (effect)
geoNode->setEffect(effect);
}
mainNode->setNodeMask(~simgear::CASTSHADOW_BIT);
return mainNode;
}

16
src/Scenery/marker.hxx Normal file
View file

@ -0,0 +1,16 @@
// marker.hxx - 3D Marker pins in FlightGear
// Copyright (C) 2022 Tobias Dammers
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
#pragma once
namespace osgText {
class String;
}
namespace osg {
class Node;
class Vec4f;
}
osg::Node* fgCreateMarkerNode(const osgText::String&, float font_size, float pin_height, float tip_height, const osg::Vec4f& color);

View file

@ -676,6 +676,9 @@ static naRef f_geodinfo(naContext c, naRef me, int argc, naRef* args)
const simgear::BVHMaterial *material;
SGGeod geod = SGGeod::fromDegM(lon, lat, elev);
if (globals == nullptr)
return naNil();
const auto scenery = globals->get_scenery();
if (scenery == nullptr)
return naNil();