Skip to content

Commit

Permalink
Update the osgearth_3pv utility to work with ortho AND to support aut…
Browse files Browse the repository at this point in the history
…omatic tracking
  • Loading branch information
gwaldron committed Oct 2, 2024
1 parent b44dc6b commit 1a43446
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 99 deletions.
191 changes: 97 additions & 94 deletions src/applications/osgearth_3pv/osgearth_3pv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,13 @@
#include <osgEarth/EarthManipulator>
#include <osgEarth/ExampleResources>
#include <osgEarth/Utils>
#include <osgEarth/Math>
#include <osgEarth/ShaderLoader>

#include <osgEarth/Horizon>
#include <osgEarth/Lighting>
#include <osgEarth/GLUtils>
#include <osgEarth/LineDrawable>

#include <osgEarth/PlaceNode>

#define LC "[viewer] "

using namespace osgEarth;
Expand All @@ -45,36 +44,18 @@ using namespace osgEarth;
#include <osgDB/ReadFile>
#include <osgViewer/CompositeViewer>
#include <osgGA/TrackballManipulator>
#include <cstdlib> // for putenv

#if 0
struct PlacerCallback : public MouseCoordsTool::Callback
{
PlaceNode* _place;
osg::View* _eyeView;
PlacerCallback(PlaceNode* place, osgViewer::View* eyeView) : _place(place), _eyeView(eyeView) { }

// called when valid map coordinates are found under the mouse
void set(const GeoPoint& coords, osg::View* view, MapNode* mapNode)
{
_place->setPosition(coords);
_place->setNodeMask(~0);

osg::Vec3d eyeWorld, c, u;
_eyeView->getCamera()->getViewMatrixAsLookAt(eyeWorld, c, u);
osg::Vec3d placeWorld;
coords.toWorld(placeWorld);

_place->setText( Stringify() << "Range: " << (int)(eyeWorld-placeWorld).length() << "m" );
}

// called when no map coords are found under the mouse
void reset(osg::View* view, MapNode* mapNode)
{
_place->setNodeMask(0);
// this shader will outline each terrain tile
const char* outline_shader = R"(
#pragma vp_function outline_tile, fragment
in vec4 oe_layer_tilec;
void outline_tile(inout vec4 color) {
vec2 uv = abs(oe_layer_tilec.xy * 2.0 - 1.0);
if (uv.x > 0.99 || uv.y > 0.99) {
color = vec4(1.0, 0.0, 0.0, 1.0);
}
}
};
#endif
)";

struct CaptureFrustum : public osg::NodeCallback
{
Expand Down Expand Up @@ -116,6 +97,7 @@ createFrustumGeometry()
osg::Group* g1 = new osg::Group();
g1->addChild(mt);
g1->getOrCreateStateSet()->setRenderBinDetails(3, "RenderBin");
g1->getOrCreateStateSet()->setRenderBinDetails(3, "RenderBin");

osg::Group* top = new osg::Group();
top->addChild(g0);
Expand All @@ -135,34 +117,39 @@ createFrustumGeometry()
void
updateFrustumGeometry(osg::Node* node, const osg::Matrix& modelview, const osg::Matrix& proj)
{
// Get near and far from the Projection matrix.
const double near = proj(3,2) / (proj(2,2)-1.0);
const double far = proj(3,2) / (1.0+proj(2,2));

// Get the sides of the near plane.
const double nLeft = near * (proj(2,0)-1.0) / proj(0,0);
const double nRight = near * (1.0+proj(2,0)) / proj(0,0);
const double nTop = near * (1.0+proj(2,1)) / proj(1,1);
const double nBottom = near * (proj(2,1)-1.0) / proj(1,1);

// Get the sides of the far plane.
const double fLeft = far * (proj(2,0)-1.0) / proj(0,0);
const double fRight = far * (1.0+proj(2,0)) / proj(0,0);
const double fTop = far * (1.0+proj(2,1)) / proj(1,1);
const double fBottom = far * (proj(2,1)-1.0) / proj(1,1);
osg::Vec3 LBN, RBN, RTN, LTN, LBF, RBF, RTF, LTF;

LineDrawable* geom = static_cast<LineDrawable*>(node->getUserData());
if (ProjectionMatrix::isPerspective(proj))
{
double L, R, B, T, N, F;
ProjectionMatrix::getPerspective(proj, L, R, B, T, N, F);

double x = F / N;
LBN.set(L, B, -N);
RBN.set(R, B, -N);
RTN.set(R, T, -N);
LTN.set(L, T, -N);
LBF.set(x * L, x * B, -F);
RBF.set(x * R, x * B, -F);
RTF.set(x * R, x * T, -F);
LTF.set(x * L, x * T, -F);
}
else
{
double L, R, B, T, N, F;
ProjectionMatrix::getOrtho(proj, L, R, B, T, N, F);

LBN.set(L, B, -N);
RBN.set(R, B, -N);
RTN.set(R, T, -N);
LTN.set(L, T, -N);
LBF.set(L, B, -F);
RBF.set(R, B, -F);
RTF.set(R, T, -F);
LTF.set(L, T, -F);
}

osg::Vec3
LBN(nLeft, nBottom, -near),
RBN(nRight, nBottom, -near),
RTN(nRight, nTop, -near),
LTN(nLeft, nTop, -near),
LBF(fLeft, fBottom, -far),
RBF(fRight, fBottom, -far),
RTF(fRight, fTop, -far),
LTF(fLeft, fTop, -far),
EYE(0,0,0);
LineDrawable* geom = static_cast<LineDrawable*>(node->getUserData());

int i=0;

Expand All @@ -179,25 +166,32 @@ updateFrustumGeometry(osg::Node* node, const osg::Matrix& modelview, const osg::
geom->setVertex(i++, LTF); geom->setVertex(i++, LBF);

// sides
geom->setVertex(i++, EYE); geom->setVertex(i++, LBF);
geom->setVertex(i++, EYE); geom->setVertex(i++, RBF);
geom->setVertex(i++, EYE); geom->setVertex(i++, LTF);
geom->setVertex(i++, EYE); geom->setVertex(i++, RTF);
if (ProjectionMatrix::isPerspective(proj))
{
geom->setVertex(i++, osg::Vec3()); geom->setVertex(i++, LBF);
geom->setVertex(i++, osg::Vec3()); geom->setVertex(i++, RBF);
geom->setVertex(i++, osg::Vec3()); geom->setVertex(i++, LTF);
geom->setVertex(i++, osg::Vec3()); geom->setVertex(i++, RTF);
}
else
{
geom->setVertex(i++, LBN); geom->setVertex(i++, LBF);
geom->setVertex(i++, RBN); geom->setVertex(i++, RBF);
geom->setVertex(i++, RTN); geom->setVertex(i++, RTF);
geom->setVertex(i++, LTN); geom->setVertex(i++, LTF);
}

geom->dirty();

osg::MatrixTransform* xform = static_cast<osg::MatrixTransform*>(geom->getParent(0));
xform->setMatrix( osg::Matrixd::inverse(modelview) );
}


char debugEnv[] = "OSGEARTH_REX_DEBUG=1";

int
main( int argc, char** argv )
{
osgEarth::initialize();

putenv(debugEnv);

osg::ArgumentParser arguments( &argc, argv );

osg::ref_ptr< osg::Group > root = new osg::Group;
Expand All @@ -216,24 +210,32 @@ main( int argc, char** argv )
// Turn on FSAA, makes the lines look better.
osg::DisplaySettings::instance()->setNumMultiSamples( 4 );

bool track = true;
if (arguments.read("--no-track"))
track = false;

auto modelManip = new EarthManipulator();
auto spyManip = new EarthManipulator();

// Create View 0 -- Just the loaded model.
{
osgViewer::View* view = new osgViewer::View;
viewer.addView( view );
viewer.addView(view);

view->setUpViewInWindow( 20, 20, 800, 800 );
view->setSceneData( scene );
view->setCameraManipulator( new EarthManipulator() );
view->setUpViewInWindow(20, 20, 1400, 1400);
view->setSceneData(scene);
view->setCameraManipulator(modelManip);
}

// Create view 1 -- Contains the loaded moel, as well as a wireframe frustum derived from View 0's Camera.
{
osgViewer::View* view = new osgViewer::View;
viewer.addView( view );
viewer.addView(view);

view->setUpViewInWindow( 850, 20, 800, 800 );
view->setSceneData( root.get() );
view->setCameraManipulator( new EarthManipulator() );
view->setUpViewInWindow(1450, 20, 1400, 1400);
view->setSceneData(root.get());
view->setCameraManipulator(spyManip);
spyManip->home(0);
}

MapNodeHelper helper;
Expand All @@ -244,43 +246,44 @@ main( int argc, char** argv )
}
scene->addChild( node );

// A shader to outline the terrain tiles.
ShaderLoader::load(scene, outline_shader);

helper.configureView( viewer.getView(0) );
helper.configureView( viewer.getView(1) );

MapNode* mapNode = MapNode::get(node.get());

osg::ref_ptr<osg::Image> icon = osgDB::readRefImageFile("../data/placemark32.png");
PlaceNode* place = new PlaceNode();
place->setIconImage(icon.get());
place->setMapNode(mapNode);
place->getOrCreateStateSet()->setRenderBinDetails(10, "DepthSortedBin");
place->setDynamic(true);
place->setNodeMask(0);
viewer.getView(0)->getCamera()->addChild( place );

#if 0
MouseCoordsTool* mct = new MouseCoordsTool(mapNode);
mct->addCallback( new PlacerCallback(place, viewer.getView(0)) );
viewer.getView(1)->addEventHandler( mct );
#endif

mapNode->addChild(new HorizonNode());

osg::Matrix proj;
viewer.getView(0)->getCamera()->addCullCallback(new CaptureFrustum(proj));

// This puts the terrain engine into SPY mode.
viewer.getView(1)->getCamera()->setName("Spy");

viewer.getView(1)->getCamera()->setCullCallback(
new ObjectStorage::SetValue<bool>("osgEarth.Spy", true));

auto* mapNode = MapNode::get(node);

while (!viewer.done())
{
updateFrustumGeometry(
frustum,
viewer.getView(0)->getCamera()->getViewMatrix(),
proj);

if (track)
{
if (viewer.getFrameStamp()->getFrameNumber() == 0)
{
spyManip->home(0);
}
else
{
Viewpoint model_vp = modelManip->getViewpoint();
Viewpoint sky_vp = spyManip->getViewpoint();
sky_vp.focalPoint() = model_vp.focalPoint();
spyManip->setViewpoint(sky_vp);
}
}

viewer.frame();
}
return 0;
Expand Down
8 changes: 3 additions & 5 deletions src/applications/osgearth_imgui/osgearth_imgui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
#include <osgEarthImGui/ImGuiApp>
#include <osgEarth/EarthManipulator>
#include <osgEarth/ExampleResources>
#include <osgEarth/Metrics>
#include <osgViewer/Viewer>

#include <osgEarthImGui/LayersGUI>
Expand Down Expand Up @@ -80,17 +79,16 @@ main(int argc, char** argv)

osgEarth::initialize(arguments);

// Set up the viewer and input handler:
osgViewer::Viewer viewer(arguments);
viewer.setThreadingModel(viewer.SingleThreaded);
viewer.setCameraManipulator(new EarthManipulator(arguments));

// This is normally called by Viewer::run but we are running our frame loop manually so we need to call it here.
viewer.setReleaseContextAtEndOfFrameHint(false);

// Call this to enable ImGui rendering.
// If you use the MapNodeHelper, call this first.
viewer.setRealizeOperation(new ImGuiAppEngine::RealizeOperation);

// Load the earth file.
osg::ref_ptr<osg::Node> node = MapNodeHelper().load(arguments, &viewer);
if (node.valid())
{
Expand Down Expand Up @@ -138,7 +136,7 @@ main(int argc, char** argv)
viewer.getEventHandlers().push_front(ui);

viewer.setSceneData(node);
return Metrics::run(viewer);
return viewer.run();
}
else
{
Expand Down

0 comments on commit 1a43446

Please sign in to comment.