Compare commits

...

6 Commits

Author SHA1 Message Date
2f52548074 change to osgearth 2.10 2025-01-19 22:26:21 +08:00
ad02144014 moidyf render 2025-01-18 22:36:28 +08:00
32ed1bf037 modify render 2025-01-17 02:33:15 +08:00
c3bb7a8054 modify render 2025-01-16 00:13:05 +08:00
7effa0e8f4 modify osg render widge modth 2025-01-15 02:02:25 +08:00
7237c650a3 add new render mode 2025-01-14 01:33:51 +08:00
46 changed files with 2135 additions and 3232 deletions

View File

@ -9,7 +9,7 @@ SET(CMAKE_CXX_STANDARD_REQUIRED ON)
SET(CMAKE_INCLUDE_CURRENT_DIR ON) SET(CMAKE_INCLUDE_CURRENT_DIR ON)
find_package(QT NAMES Qt6 Qt5 COMPONENTS Widgets LinguistTools REQUIRED) find_package(QT NAMES Qt6 Qt5 COMPONENTS Widgets LinguistTools REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets LinguistTools OpenGL REQUIRED) find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Gui Widgets LinguistTools OpenGL REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Widgets LinguistTools DataVisualization Charts Network REQUIRED) find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Widgets LinguistTools DataVisualization Charts Network REQUIRED)
message("qt VERSION " ${QT_VERSION_MAJOR}) message("qt VERSION " ${QT_VERSION_MAJOR})
@ -85,8 +85,7 @@ INCLUDE_DIRECTORIES(
${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}
${Thirdparty}/spdlog/include ${Thirdparty}/spdlog/include
${Thirdparty}/breakpad/include ${Thirdparty}/breakpad/include
${Thirdparty}/3rdParty_x64/include ${Thirdparty}/3rdParty/include
${Thirdparty}/OpenSceneGraph-3.6.5/include
${Thirdparty}/TritonSDK/PublicHeaders ${Thirdparty}/TritonSDK/PublicHeaders
${Thirdparty}/matlab/include ${Thirdparty}/matlab/include
# ${Thirdparty}/Python39/include # ${Thirdparty}/Python39/include
@ -94,8 +93,7 @@ INCLUDE_DIRECTORIES(
LINK_DIRECTORIES( LINK_DIRECTORIES(
${Thirdparty}/spdlog/lib ${Thirdparty}/spdlog/lib
${Thirdparty}/3rdParty_x64/lib ${Thirdparty}/3rdParty/lib
${Thirdparty}/OpenSceneGraph-3.6.5/lib
${Thirdparty}/matlab/lib/win64/microsoft ${Thirdparty}/matlab/lib/win64/microsoft
${Thirdparty}/TritonSDK/lib/vc143/x64 ${Thirdparty}/TritonSDK/lib/vc143/x64
# ${Thirdparty}/Python39/libs # ${Thirdparty}/Python39/libs
@ -146,6 +144,7 @@ target_link_libraries(
${PROJECT_NAME} ${PROJECT_NAME}
PRIVATE PRIVATE
Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::Widgets
Qt${QT_VERSION_MAJOR}::Charts Qt${QT_VERSION_MAJOR}::Charts
Qt${QT_VERSION_MAJOR}::DataVisualization Qt${QT_VERSION_MAJOR}::DataVisualization
@ -166,6 +165,9 @@ target_link_libraries(
osgSim osgSim
osgWidget osgWidget
osgEarth osgEarth
osgEarthUtil
osgEarthAnnotation
osgEarthTriton
Triton-MT-DLL Triton-MT-DLL
libeng libeng
libmx libmx

View File

@ -1,5 +1,7 @@
#include "CrashHandler.h" #include "CrashHandler.h"
#if 0
#include <QCoreApplication> #include <QCoreApplication>
#include <QMessageBox> #include <QMessageBox>
#include <QDir> #include <QDir>
@ -110,3 +112,4 @@ void TestCrash() {
volatile int* a = (int*)(nullptr); volatile int* a = (int*)(nullptr);
*a = 1; *a = 1;
} }
#endif

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#if 0
bool InstallCrashHandler(); bool InstallCrashHandler();
void TestCrash(); void TestCrash();
#endif

View File

@ -1,3 +1,4 @@
#if 0
#include "app/Application.h" #include "app/Application.h"
#include "common/SpdLogger.h" #include "common/SpdLogger.h"
@ -5,10 +6,16 @@
#include "common/CrashHandler.h" #include "common/CrashHandler.h"
#include "ui/MainFrame.h" #include "ui/MainFrame.h"
#include "viewer/OSGEnv.h"
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
SpdLogger logger("logs/log.txt", 5); SpdLogger logger("logs/log.txt", 5);
if (!OSGEnv::init()) {
LOG_ERROR("OSGEnv::init() failed!");
return 1;
}
Application::setAttribute(Qt::AA_EnableHighDpiScaling); Application::setAttribute(Qt::AA_EnableHighDpiScaling);
Application app(argc, argv); Application app(argc, argv);
@ -23,5 +30,727 @@ int main(int argc, char* argv[]) {
mainWindow.showMaximized(); mainWindow.showMaximized();
ret = app.exec(); ret = app.exec();
OSGEnv::destroy();
return ret; return ret;
} }
#else
//
//#include <osgDB/ReadFile>
//
//#include <osgWidget/Util>
//#include <osgWidget/WindowManager>
//#include <osgWidget/Frame>
//#include <osgWidget/Box>
//
//const unsigned int MASK_2D = 0xF0000000;
//
//// NOTE: THIS IS JUST A TEMPORARY HACK! :) This functionality will all eventually be
//// encapsulate into another class in osgWidget proper.
//bool scrollWindow(osgWidget::Event& ev) {
// // The first thing we need to do is make sure we have a Frame object...
// osgWidget::Frame* frame = dynamic_cast<osgWidget::Frame*>(ev.getWindow());
//
// if (!frame) return false;
//
// // And now we need to make sure our Frame has a valid internal EmbeddedWindow widget.
// osgWidget::Window::EmbeddedWindow* ew =
// dynamic_cast<osgWidget::Window::EmbeddedWindow*>(frame->getEmbeddedWindow())
// ;
//
// if (!ew) return false;
//
// // Lets get the visible area so that we can use it to make sure our scrolling action
// // is necessary in the first place.
// const osgWidget::Quad& va = ew->getWindow()->getVisibleArea();
//
// // The user wants to scroll up; make sure that the visible area's Y origin isn't already
// // at 0.0f, 0.0f.
// if (ev.getWindowManager()->isMouseScrollingUp() && va[1] != 0.0f)
// ew->getWindow()->addVisibleArea(0, -20)
// ;
//
// else if (va[1] <= (ew->getWindow()->getHeight() - ew->getHeight()))
// ew->getWindow()->addVisibleArea(0, 20)
// ;
//
// // We need to manually call update to make sure the visible area scissoring is done
// // properly.
// frame->update();
//
// return true;
//}
//
//bool changeTheme(osgWidget::Event& ev) {
// std::string theme;
//
// if (ev.key == osgGA::GUIEventAdapter::KEY_Right)
// theme = "osgWidget/theme-1.png"
// ;
//
// else if (ev.key == osgGA::GUIEventAdapter::KEY_Left)
// theme = "osgWidget/theme-2.png"
// ;
//
// else return false;
//
// osgWidget::Frame* frame = dynamic_cast<osgWidget::Frame*>(ev.getWindow());
//
// if (!frame) return false;
//
// // This is just one way to access all our Widgets; we could just as well have used:
// //
// // for(osgWidget::Frame::Iterator i = frame.begin(); i != frame.end() i++) {}
// //
// // ...and it have worked, too.
// for (unsigned int row = 0; row < 3; row++) {
// for (unsigned int col = 0; col < 3; col++) {
// frame->getByRowCol(row, col)->setImage(theme);
// }
// }
//
// return true;
//}
//
//int main(int, char**) {
// osgViewer::Viewer viewer;
//
// osgWidget::WindowManager* wm = new osgWidget::WindowManager(
// &viewer,
// 1280.0f,
// 1024.0f,
// MASK_2D,
// osgWidget::WindowManager::WM_PICK_DEBUG
// //osgWidget::WindowManager::WM_NO_INVERT_Y
// );
//
// std::string baes("D:/Project/DYTSrouce/bin/Release/data/");
// osgWidget::Frame* frame = osgWidget::Frame::createSimpleFrameFromTheme(
// "frame",
// osgDB::readRefImageFile(baes + "osgWidget/theme.png"),
// 40.0f,
// 40.0f,
// osgWidget::Frame::FRAME_ALL
// );
//
// frame->getBackground()->setColor(0.0f, 0.0f, 0.0f, 0.0f);
//
// // This is our Transformers box. :)
// osgWidget::Box* box = new osgWidget::Box("images", osgWidget::Box::VERTICAL);
// osgWidget::Widget* img1 = new osgWidget::Widget("im1", 512.0f, 512.0f);
// osgWidget::Widget* img2 = new osgWidget::Widget("im2", 512.0f, 512.0f);
// osgWidget::Widget* img3 = new osgWidget::Widget("im3", 512.0f, 512.0f);
// osgWidget::Widget* img4 = new osgWidget::Widget("im4", 512.0f, 512.0f);
//
// const std::string image1 = "D:/Project/DYTSrouce/bin/Release/resources/northarrow/_n.png";
// img1->setImage(image1, true);
// img2->setImage(baes + "osgWidget/scrolled2.jpg", true);
// img3->setImage(baes + "osgWidget/scrolled3.jpg", true);
// img4->setImage(baes + "osgWidget/scrolled4.jpg", true);
//
// img1->setMinimumSize(10.0f, 10.0f);
// img2->setMinimumSize(10.0f, 10.0f);
// img3->setMinimumSize(10.0f, 10.0f);
// img4->setMinimumSize(10.0f, 10.0f);
//
// box->addWidget(img1);
// box->addWidget(img2);
// box->addWidget(img3);
// box->addWidget(img4);
// box->setEventMask(osgWidget::EVENT_NONE);
//
// //frame->getEmbeddedWindow()->setWindow(box);
// frame->setWindow(box);
// frame->getEmbeddedWindow()->setColor(1.0f, 1.0f, 1.0f, 1.0f);
// frame->resize(300.0f, 300.0f);
// frame->addCallback(new osgWidget::Callback(&scrollWindow, osgWidget::EVENT_MOUSE_SCROLL));
// frame->addCallback(new osgWidget::Callback(&changeTheme, osgWidget::EVENT_KEY_DOWN));
//
// wm->addChild(frame);
//
// return osgWidget::createExample(viewer, wm);
//}
#ifdef QT_VERSION
#include <QApplication>
#include <QMainWindow>
#include <QOpenGLWidget>
#include <QMouseEvent>
#include <QWheelEvent>
#include <QDesktopWidget>
#include <QScreen>
#include <QtGlobal>
#include <QWindow>
#include <osg/ref_ptr>
#include <osgViewer/GraphicsWindow>
#include <osgViewer/Viewer>
#include <osg/Camera>
#include <osg/ShapeDrawable>
#include <osg/StateSet>
#include <osg/Material>
#include <osgGA/EventQueue>
#include <osgGA/TrackballManipulator>
#include <osgDB/ReadFile>
#include <osgEarth/MapNode>
#include <osgEarthUtil/Sky>
#include <osgEarthUtil/Ephemeris>
#include <osgEarthUtil/EarthManipulator>
//#include <osgEarth/GLUtils>
#include <iostream>
#include <stdio.h>
#include "viewer/OSGEnv.h"
class QtOSGWidget : public QOpenGLWidget {
public:
QtOSGWidget(qreal scaleX, qreal scaleY, QWidget* parent = 0)
: QOpenGLWidget(parent)
//, _mGraphicsWindow(new osgViewer::GraphicsWindowEmbedded(this->x(), this->y(),
//this->width(), this->height()))
, _mViewer(new osgViewer::Viewer)
, m_scaleX(scaleX)
, m_scaleY(scaleY) {
osg::ref_ptr<osg::DisplaySettings> ds = osg::DisplaySettings::instance();
osg::ref_ptr<osg::GraphicsContext::Traits> traits
= new osg::GraphicsContext::Traits(ds);
traits->x = 0;
traits->y = 0;
traits->width = width();
traits->height = height();
traits->alpha = ds->getMinimumNumAlphaBits();
traits->stencil = ds->getMinimumNumStencilBits();
traits->sampleBuffers = ds->getMultiSamples();
traits->samples = ds->getNumMultiSamples();
traits->windowDecoration = false;
traits->doubleBuffer = true;
traits->sharedContext = nullptr;
traits->setInheritedWindowPixelFormat = true;
//_mGraphicsWindow = new osgViewer::GraphicsWindowEmbedded(0, 0, width(), height());
_mGraphicsWindow = new osgViewer::GraphicsWindowEmbedded(traits);
//osg::Cylinder* cylinder = new osg::Cylinder(osg::Vec3(0.f, 0.f, 0.f), 0.25f, 0.5f);
//osg::ShapeDrawable* sd = new osg::ShapeDrawable(cylinder);
//sd->setColor(osg::Vec4(0.8f, 0.5f, 0.2f, 1.f));
//osg::Geode* geode = new osg::Geode;
//geode->addDrawable(sd);
osg::ref_ptr<osg::Node> node = osgDB::readNodeFile("D:/Project/DYT/Tool/TritonSample/TritonSample/triton.earth");
if (!node.valid())
return ;
// If the node doesn't contain a MapNode (earth file), bail out:
auto mapNode = osgEarth::MapNode::get(node);
if (!mapNode)
return ;
auto sky = osgEarth::Util::SkyNode::create();
//auto parent = mapNode->getParent(0);
sky->addChild(mapNode);
//parent->addChild(sky);
//parent->removeChild(mapNode);
sky->setAtmosphereVisible(true);
sky->setSunVisible(true);
sky->setMoonVisible(true);
sky->setStarsVisible(true);
sky->setDateTime(osgEarth::DateTime(2024, 12, 24, 6));
//sky->setSimulationTimeTracksDateTime(true);
//#ifndef OSG_GL3_AVAILABLE
// // If your OSG is build with a GL2 profile, install our custom realize op
// // to get all the shaders working:
// _mViewer->setRealizeOperation(new osgEarth::GL3RealizeOperation());
//#endif
// _mViewer->realize();
//
//
// _mViewer->setCameraManipulator(new osgEarth::Util::EarthManipulator());
osg::Camera* camera = new osg::Camera;
camera->setViewport(0, 0, this->width(), this->height());
//camera->setClearColor(osg::Vec4(0.9f, 0.9f, 1.f, 1.f));
float aspectRatio = static_cast<float>(this->width()) / static_cast<float>(this->height());
camera->setProjectionMatrixAsPerspective(30.f, aspectRatio, 1.f, 1000.f);
camera->setGraphicsContext(_mGraphicsWindow);
_mViewer->setCamera(camera);
//_mViewer->setSceneData(geode);
_mViewer->setSceneData(sky);
sky->attach(_mViewer);
osgGA::TrackballManipulator* manipulator = new osgGA::TrackballManipulator;
manipulator->setAllowThrow(false);
this->setMouseTracking(true);
_mViewer->setCameraManipulator(manipulator);
_mViewer->getDatabasePager()->setUnrefImageDataAfterApplyPolicy(true, false);
//_mViewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);
//_mViewer->setRealizeOperation(new osgEarth::GL3RealizeOperation());
//_mViewer->realize();
}
virtual ~QtOSGWidget() {}
void setScale(qreal X, qreal Y) {
m_scaleX = X;
m_scaleY = Y;
this->resizeGL(this->width(), this->height());
}
protected:
virtual void paintGL() {
_mViewer->frame();
}
virtual void resizeGL(int width, int height) {
this->getEventQueue()->windowResize(this->x() * m_scaleX, this->y() * m_scaleY, width * m_scaleX, height * m_scaleY);
_mGraphicsWindow->resized(this->x() * m_scaleX, this->y() * m_scaleY, width * m_scaleX, height * m_scaleY);
osg::Camera* camera = _mViewer->getCamera();
camera->setViewport(0, 0, this->width() * m_scaleX, this->height() * m_scaleY);
}
virtual void initializeGL() {
//osg::Geode* geode = dynamic_cast<osg::Geode*>(_mViewer->getSceneData());
//osg::StateSet* stateSet = geode->getOrCreateStateSet();
//osg::Material* material = new osg::Material;
//material->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE);
//stateSet->setAttributeAndModes(material, osg::StateAttribute::ON);
//stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON);
// osg::ref_ptr<osg::Node> node = osgDB::readNodeFile("D:/Project/DYT/Tool/TritonSample/TritonSample/triton.earth");
// if (!node.valid())
// return ;
//
// // If the node doesn't contain a MapNode (earth file), bail out:
// auto mapNode = osgEarth::MapNode::get(node);
// if (!mapNode)
// return ;
//
//
//
// auto sky = osgEarth::SkyNode::create();
// //auto parent = mapNode->getParent(0);
// sky->addChild(mapNode);
// //parent->addChild(sky);
// //parent->removeChild(mapNode);
//
//
// sky->setAtmosphereVisible(true);
// sky->setSunVisible(true);
// sky->setMoonVisible(true);
// sky->setStarsVisible(true);
//
// sky->setDateTime(osgEarth::DateTime(2024, 12, 24, 6));
// sky->setSimulationTimeTracksDateTime(true);
//
// _mViewer->setSceneData(sky);
//
//#ifndef OSG_GL3_AVAILABLE
// // If your OSG is build with a GL2 profile, install our custom realize op
// // to get all the shaders working:
// _mViewer->setRealizeOperation(new osgEarth::GL3RealizeOperation());
//#endif
// _mViewer->realize();
//
//
// _mViewer->setCameraManipulator(new osgEarth::Util::EarthManipulator());
}
virtual void mouseMoveEvent(QMouseEvent* event) {
this->getEventQueue()->mouseMotion(event->x() * m_scaleX, event->y() * m_scaleY);
}
virtual void mousePressEvent(QMouseEvent* event) {
unsigned int button = 0;
switch (event->button()) {
case Qt::LeftButton:
button = 1;
break;
case Qt::MiddleButton:
button = 2;
break;
case Qt::RightButton:
button = 3;
break;
default:
break;
}
this->getEventQueue()->mouseButtonPress(event->x() * m_scaleX, event->y() * m_scaleY, button);
}
virtual void mouseReleaseEvent(QMouseEvent* event) {
unsigned int button = 0;
switch (event->button()) {
case Qt::LeftButton:
button = 1;
break;
case Qt::MiddleButton:
button = 2;
break;
case Qt::RightButton:
button = 3;
break;
default:
break;
}
this->getEventQueue()->mouseButtonRelease(event->x() * m_scaleX, event->y() * m_scaleY, button);
}
virtual void wheelEvent(QWheelEvent* event) {
int delta = event->delta();
osgGA::GUIEventAdapter::ScrollingMotion motion = delta > 0 ?
osgGA::GUIEventAdapter::SCROLL_UP : osgGA::GUIEventAdapter::SCROLL_DOWN;
this->getEventQueue()->mouseScroll(motion);
}
virtual bool event(QEvent* event) {
bool handled = QOpenGLWidget::event(event);
this->update();
return handled;
}
private:
osgGA::EventQueue* getEventQueue() const {
osgGA::EventQueue* eventQueue = _mGraphicsWindow->getEventQueue();
return eventQueue;
}
osg::ref_ptr<osgViewer::GraphicsWindowEmbedded> _mGraphicsWindow;
osg::ref_ptr<osgViewer::Viewer> _mViewer;
qreal m_scaleX, m_scaleY;
};
int main(int argc, char** argv) {
QApplication qapp(argc, argv);
OSGEnv::init();
QMainWindow window;
QtOSGWidget* widget = new QtOSGWidget(1, 1, &window);
window.setCentralWidget(widget);
window.show();
return qapp.exec();
}
#endif
#include <osgViewer/Viewer>
#include <osgDB/FileNameUtils>
#include <osgDB/ReadFile>
#include <osgEarth/NodeUtils>
#include <osgEarth/LineDrawable>
#include <osgEarth/Registry>
#include <osgEarthUtil/EarthManipulator>
#include <osgEarthUtil/ExampleResources>
#include <osgEarthUtil/Controls>
#include <osgEarthTriton/TritonAPIWrapper>
#include <osgEarthTriton/TritonCallback>
#include <osgEarthTriton/TritonOptions>
#include <osgEarthTriton/TritonLayer>
#include <osgEarthAnnotation/AnnotationLayer>
#include <osgEarthAnnotation/PlaceNode>
#include <osgEarthAnnotation/GeoPositionNode>
#define LC "[osgearth_triton] "
using namespace osgEarth;
using namespace osgEarth::Util;
using namespace osgEarth::Triton;
using namespace osgEarth::Annotation;
namespace ui = osgEarth::Util::Controls;
struct Settings {
optional<double> chop;
optional<double> seaState;
optional<float> alpha;
osg::observer_ptr<TritonLayer> tritonLayer;
void apply(Environment& env, Ocean& ocean) {
if (chop.isSet()) {
ocean.SetChoppiness(chop.get());
chop.clear();
}
if (seaState.isSet()) {
env.SimulateSeaState(seaState.get(), 0.0);
seaState.clear();
}
osg::ref_ptr<TritonLayer> layer;
if (alpha.isSet() && tritonLayer.lock(layer)) {
layer->setOpacity(alpha.value());
alpha.clear();
}
}
};
class TritonCallback : public osgEarth::Triton::Callback {
public:
TritonCallback(Settings& settings) : _settings(settings) {}
void onInitialize(Environment& env, Ocean& ocean) {
//todo
}
void onDrawOcean(Environment& env, Ocean& ocean) {
_settings.apply(env, ocean);
}
Settings& _settings;
};
struct App {
App() {
tritonLayer = NULL;
map = NULL;
const double lon = -118.5406, lat = 32.7838;
anchor.set(
SpatialReference::get("wgs84"), lon, lat, 0.0,
ALTMODE_ABSOLUTE);
isect = new Triton::TritonIntersections();
}
Map* map;
TritonLayer* tritonLayer;
Settings settings;
osg::ref_ptr<Triton::TritonIntersections> isect;
AnnotationLayer* labels;
AnnotationLayer* normals;
LineDrawable* normalDrawable;
GeoPoint anchor;
void addTriton() {
// Create TritonNode from TritonOptions
osgEarth::Triton::TritonOptions tritonOptions;
tritonOptions.user() = "my_user_name";
tritonOptions.licenseCode() = "my_license_code";
tritonOptions.maxAltitude() = 100000;
tritonOptions.useHeightMap() = true;
const char* ev_t = ::getenv("TRITON_PATH");
if (ev_t) {
tritonOptions.resourcePath() = osgDB::concatPaths(
std::string(ev_t),
"Resources");
OE_INFO << LC
<< "Setting resource path to << " << tritonOptions.resourcePath().get()
<< std::endl;
} else {
OE_WARN << LC
<< "No resource path! Triton might not initialize properly. "
<< "Consider setting the TRITON_PATH environment variable."
<< std::endl;
}
tritonLayer = new TritonLayer(tritonOptions, new TritonCallback(settings));
map->addLayer(tritonLayer);
settings.tritonLayer = tritonLayer;
tritonLayer->addIntersections(isect.get());
}
void removeTriton() {
if (tritonLayer)
map->removeLayer(tritonLayer);
tritonLayer = 0L;
}
void addBuoyancyTest(osg::Node* model) {
//labels = new AnnotationLayer();
//map->addLayer(labels);
normals = new AnnotationLayer();
map->addLayer(normals);
// geometry for a unit normal vector
normalDrawable = new LineDrawable(GL_LINES);
normalDrawable->setColor(osg::Vec4(1, 1, 0, 1));
normalDrawable->pushVertex(osg::Vec3(0, 0, 0));
normalDrawable->pushVertex(osg::Vec3(0, 0, 10));
normalDrawable->pushVertex(osg::Vec3(-2, 0, 0.5));
normalDrawable->pushVertex(osg::Vec3(2, 0, 0.5));
normalDrawable->pushVertex(osg::Vec3(0, -2, 0.5));
normalDrawable->pushVertex(osg::Vec3(0, 2, 0.5));
normalDrawable->finish();
// a single shared anchor point for the intersection set:
isect->setAnchor(anchor);
// generate a bunch of local points around the anchor:
for (int x = -50; x <= 50; x += 25) {
for (int y = -50; y <= 50; y += 25) {
isect->addLocalPoint(osg::Vec3d(x, y, 0));
// a label communicating the wave height:
//PlaceNode* label = new PlaceNode();
//label->setDynamic(true);
//label->setPosition(anchor);
//label->setIconImage(image);
//label->setText("-");
//labels->getGroup()->addChild(label);
// a normal vector and optional model:
GeoPositionNode* normal = new GeoPositionNode();
normal->setDynamic(true);
normal->getPositionAttitudeTransform()->addChild(normalDrawable);
if (model)
normal->getPositionAttitudeTransform()->addChild(model);
normal->setPosition(anchor);
normals->getGroup()->addChild(normal);
}
}
//ScreenSpaceLayout::setDeclutteringEnabled(false);
}
void updateBuoyancyTest() {
for (unsigned i = 0; i < isect->getHeights().size(); ++i) {
osg::Vec3d local = isect->getInput()[i];
local.z() = isect->getHeights()[i];
//PlaceNode* label = dynamic_cast<PlaceNode*>(labels->getGroup()->getChild(i));
//label->getPositionAttitudeTransform()->setPosition(local);
//label->setText(Stringify()<<std::setprecision(2)<<local.z());
GeoPositionNode* normalNode = dynamic_cast<GeoPositionNode*>(normals->getGroup()->getChild(i));
normalNode->getPositionAttitudeTransform()->setPosition(local);
osg::Quat q;
q.makeRotate(osg::Vec3d(0, 0, 1), isect->getNormals()[i]);
normalNode->getPositionAttitudeTransform()->setAttitude(q);
}
}
};
App s_app;
template<typename T> struct Set : public ui::ControlEventHandler {
optional<T>& _var;
Set(optional<T>& var) : _var(var) {}
void onValueChanged(ui::Control*, double value) {
_var = value;
}
};
struct Toggle : public ui::ControlEventHandler {
void onValueChanged(ui::Control*, bool value) {
if (s_app.tritonLayer)
s_app.removeTriton();
else
s_app.addTriton();
}
};
Container* createUI() {
VBox* box = new VBox();
box->setBackColor(0, 0, 0, 0.5);
Grid* grid = box->addControl(new Grid());
int r = 0;
grid->setControl(0, r, new LabelControl("Chop"));
grid->setControl(1, r, new HSliderControl(0, 3, 0, new Set<double>(s_app.settings.chop)));
++r;
grid->setControl(0, r, new LabelControl("Sea State"));
grid->setControl(1, r, new HSliderControl(0, 12, 5, new Set<double>(s_app.settings.seaState)));
++r;
grid->setControl(0, r, new LabelControl("Alpha"));
grid->setControl(1, r, new HSliderControl(0, 1.0, 1.0, new Set<float>(s_app.settings.alpha)));
++r;
grid->setControl(0, r, new LabelControl("Toggle"));
grid->setControl(1, r, new CheckBoxControl(true, new Toggle()));
grid->getControl(1, r - 1)->setHorizFill(true, 200);
return box;
}
int
usage(const char* name) {
OE_DEBUG
<< "\nUsage: " << name << " file.earth" << std::endl
<< osgEarth::Util::MapNodeHelper().usage() << std::endl;
return 0;
}
int
main(int argc, char** argv) {
osg::ArgumentParser arguments(&argc, argv);
// help?
if (arguments.read("--help"))
return usage(argv[0]);
//osg::Node* model = 0L;
std::string filename = "D:/Project/DYT/Tool/TritonSample/TritonSample/triton.earth";
osg::ref_ptr<osg::Node> node = osgDB::readNodeFile(filename);
//if (arguments.read("--model", filename)) {
// model = osgDB::readRefNodeFile(filename).release();
// Registry::shaderGenerator().run(model);
//}
osg::ref_ptr<MapNode> mapNode = MapNode::get(node.get());
// create a viewer:
osgViewer::Viewer viewer(arguments);
// Tell the database pager to not modify the unref settings
viewer.getDatabasePager()->setUnrefImageDataAfterApplyPolicy(false, false);
// install our default manipulator (do this before calling load)
EarthManipulator* manip = new EarthManipulator();
viewer.setCameraManipulator(manip);
// load an earth file, and support all or our example command-line options
// and earth file <external> tags
//osg::Group* node = osgEarth::Util::MapNodeHelper().load(arguments, &viewer, createUI());
osg::Group* root = new osg::Group();
root->addChild(node);
if (root) {
viewer.getCamera()->setNearFarRatio(0.00002);
viewer.getCamera()->setSmallFeatureCullingPixelSize(-1.0f);
viewer.setSceneData(node);
s_app.map = MapNode::get(node)->getMap();
s_app.addTriton();
//s_app.addBuoyancyTest(model);
// Zoom the camera to our area of interest:
Viewpoint vp;
vp.heading() = 25.0f;
vp.pitch() = -25;
vp.range() = 400.0;
vp.focalPoint() = s_app.anchor;
manip->setViewpoint(vp);
#ifdef OSG_GL3_AVAILABLE
if (viewer) {
viewer->setRealizeOperation(new GL3RealizeOperation());
}
#endif
while (!viewer.done()) {
viewer.frame();
s_app.updateBuoyancyTest();
}
} else {
return usage(argv[0]);
}
}
#endif

View File

@ -7,7 +7,7 @@
#include <osg/LightSource> #include <osg/LightSource>
#include <osgDB/ReadFile> #include <osgDB/ReadFile>
#include <osgEarth/GLUtils> #include <osgEarth/GLUtils>
#include <osgEarth/EarthManipulator> #include <osgEarthUtil/EarthManipulator>
#include <osgShadow/ShadowedScene> #include <osgShadow/ShadowedScene>
#include <osgShadow/ViewDependentShadowMap> #include <osgShadow/ViewDependentShadowMap>
@ -40,8 +40,12 @@ void OEScene::InitEventHandle(class OsgView* view) {
//view->GetView()->addEventHandler(new osgEarth::Util::EarthManipulator()); //view->GetView()->addEventHandler(new osgEarth::Util::EarthManipulator());
view->GetView()->addEventHandler(new osgViewer::HelpHandler); InitEventHandle(view->GetView());
view->GetView()->addEventHandler(new osgViewer::StatsHandler); }
void OEScene::InitEventHandle(osgViewer::View* view) {
view->addEventHandler(new osgViewer::HelpHandler);
view->addEventHandler(new osgViewer::StatsHandler);
} }
void OEScene::AttachView(OsgView* view) { void OEScene::AttachView(OsgView* view) {
@ -50,6 +54,11 @@ void OEScene::AttachView(OsgView* view) {
return; return;
} }
//AttachView(view->GetView());
}
void OEScene::AttachView(osgViewer::Viewer* view) {
earthRootNode_ = osgDB::readNodeFile("triton.earth"); earthRootNode_ = osgDB::readNodeFile("triton.earth");
if (!earthRootNode_) { if (!earthRootNode_) {
LOG_ERROR("read earth node(triton.earth) failed"); LOG_ERROR("read earth node(triton.earth) failed");
@ -67,7 +76,7 @@ void OEScene::AttachView(OsgView* view) {
dyt_check(nullptr != g_srs_); dyt_check(nullptr != g_srs_);
} }
skyDome_ = osgEarth::SkyNode::create(); skyDome_ = osgEarth::Util::SkyNode::create();
if (!earthMapNode_) { if (!earthMapNode_) {
LOG_WARN("eart map node is nullptr"); LOG_WARN("eart map node is nullptr");
return; return;
@ -75,10 +84,10 @@ void OEScene::AttachView(OsgView* view) {
skyDome_->addChild(earthMapNode_); skyDome_->addChild(earthMapNode_);
osg::Node* node = view->GetView()->getSceneData(); osg::Node* node = view->getSceneData();
if (nullptr == node) { if (nullptr == node) {
LOG_INFO("view scene data is nullptr, root valid:{}", skyDome_.valid()); LOG_INFO("view scene data is nullptr, root valid:{}", skyDome_.valid());
view->GetView()->setSceneData(skyDome_); view->setSceneData(skyDome_);
} else { } else {
osg::Group* group = node->asGroup(); osg::Group* group = node->asGroup();
if (nullptr != group) { if (nullptr != group) {
@ -89,7 +98,7 @@ void OEScene::AttachView(OsgView* view) {
} }
} }
skyDome_->attach(view->GetView()); skyDome_->attach(view);
skyDome_->setAtmosphereVisible(true); skyDome_->setAtmosphereVisible(true);
skyDome_->setSunVisible(true); skyDome_->setSunVisible(true);
@ -97,10 +106,9 @@ void OEScene::AttachView(OsgView* view) {
skyDome_->setStarsVisible(true); skyDome_->setStarsVisible(true);
skyDome_->setDateTime(osgEarth::DateTime(2024, 12, 24, 3)); skyDome_->setDateTime(osgEarth::DateTime(2024, 12, 24, 3));
skyDome_->setSimulationTimeTracksDateTime(true); //skyDome_->setSimulationTimeTracksDateTime(true);
logarithmicDepthBuffer_->install(view->GetView()->getCamera());
logarithmicDepthBuffer_->install(view->getCamera());
} }
void OEScene::DetachView(OsgView* view) { void OEScene::DetachView(OsgView* view) {

View File

@ -4,9 +4,10 @@
#include <osg/TextureCubeMap> #include <osg/TextureCubeMap>
#include <osgText/Text> #include <osgText/Text>
#include <osgEarth/ModelNode> #include <osgEarth/MapNode>
#include <osgEarth/Sky> #include <osgEarthUtil/Sky>
#include <osgEarth/LogarithmicDepthBuffer> #include <osgEarthUtil/LogarithmicDepthBuffer>
#include <osgViewer/Viewer>
//#include "scene/SkyDome.h" //#include "scene/SkyDome.h"
@ -20,7 +21,9 @@ class OEScene : public osg::Referenced {
public: public:
OEScene(); OEScene();
void InitEventHandle(OsgView* view); void InitEventHandle(OsgView* view);
void InitEventHandle(osgViewer::View* view);
void AttachView(OsgView* view); void AttachView(OsgView* view);
void AttachView(osgViewer::Viewer* view);
void DetachView(OsgView* view); void DetachView(OsgView* view);
osg::ref_ptr<osg::TextureCubeMap> LoadCubeMapTextures(const std::string& dir); osg::ref_ptr<osg::TextureCubeMap> LoadCubeMapTextures(const std::string& dir);
@ -49,7 +52,7 @@ private:
osg::ref_ptr<osg::Node> earthRootNode_; osg::ref_ptr<osg::Node> earthRootNode_;
osg::ref_ptr<osgEarth::MapNode> earthMapNode_; osg::ref_ptr<osgEarth::MapNode> earthMapNode_;
osg::ref_ptr<osg::Group> entityRoot_; osg::ref_ptr<osg::Group> entityRoot_;
osg::ref_ptr<osgEarth::SkyNode> skyDome_; osg::ref_ptr<osgEarth::Util::SkyNode> skyDome_;
std::unique_ptr<osgEarth::Util::LogarithmicDepthBuffer> logarithmicDepthBuffer_; std::unique_ptr<osgEarth::Util::LogarithmicDepthBuffer> logarithmicDepthBuffer_;
osg::ref_ptr<OESceneUI> sceneUI_; osg::ref_ptr<OESceneUI> sceneUI_;
}; };

View File

@ -1,114 +0,0 @@
/* -*-c++-*- */
/* osgEarth - Geospatial SDK for OpenSceneGraph
* Copyright 2020 Pelican Mapping
* http://osgearth.org
*
* osgEarth is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#include "TritonAPIWrapper.h"
#include <Triton.h>
#define LC "[TritonAPI] "
using namespace osgEarth::Triton;
#define SETGET_EXPLICIT(NS, SETTER, GETTER, TYPE) \
void NS :: SETTER (TYPE value) { HANDLE-> SETTER (value); } \
TYPE NS :: GETTER () const { return HANDLE -> GETTER (); }
#define SETGET(NS, FUNC, TYPE) \
SETGET_EXPLICIT(NS, Set##FUNC, Get##FUNC, TYPE)
#define TOVEC3(X) ::Triton::Vector3(X.x(),X.y(),X.z())
#define FROMVEC3(X) osg::Vec3(X.x,X.y,X.z)
//................................
#undef HANDLE
#define HANDLE ((::Triton::BreakingWavesParameters*)_handle)
SETGET(BreakingWavesParameters, Steepness, float);
SETGET(BreakingWavesParameters, Wavelength, float);
//................................
#undef HANDLE
#define HANDLE ((::Triton::Environment*)_handle)
BreakingWavesParameters Environment::GetBreakingWavesParameters() const {
return BreakingWavesParameters((uintptr_t)&HANDLE->GetBreakingWavesParameters());
}
void Environment::SetDirectionalLight(const osg::Vec3& dir, const osg::Vec3& color) {
HANDLE->SetDirectionalLight(TOVEC3(dir), TOVEC3(color));
}
osg::Vec3 Environment::GetLightDirection() const {
const ::Triton::Vector3& v = HANDLE->GetLightDirection();
return FROMVEC3(v);
}
osg::Vec3 Environment::GetDirectionalLightColor() const {
const ::Triton::Vector3& v = HANDLE->GetDirectionalLightColor();
return FROMVEC3(v);
}
void Environment::SetAmbientLight(const osg::Vec3& color) {
HANDLE->SetAmbientLight(TOVEC3(color));
}
osg::Vec3 Environment::GetAmbientLightColor() const {
const ::Triton::Vector3& v = HANDLE->GetAmbientLightColor();
return FROMVEC3(v);
}
void Environment::SimulateSeaState(double bscale, double winddir) {
HANDLE->SimulateSeaState(bscale, winddir);
}
void Environment::SetAboveWaterVisibility(double visibility, osg::Vec3 fog_color) {
HANDLE->SetAboveWaterVisibility(visibility, TOVEC3(fog_color));
}
void Environment::GetAboveWaterVisibility(double &visibility, osg::Vec3 &fog_color) const {
::Triton::Vector3 triton_fog_col;
HANDLE->GetAboveWaterVisibility(visibility, triton_fog_col);
fog_color = FROMVEC3(triton_fog_col);
}
void Environment::SetEnvironmentMap(GLuint cubeMap, const osg::Matrixd &textureMatrix) {
::Triton::Matrix3 triton_tex_mat(
textureMatrix(0, 0), textureMatrix(0, 1), textureMatrix(0, 2),
textureMatrix(1, 0), textureMatrix(1, 1), textureMatrix(1, 2),
textureMatrix(2, 0), textureMatrix(2, 1), textureMatrix(2, 2));
::Triton::TextureHandle tex_handle = (::Triton::TextureHandle)(static_cast<size_t>(cubeMap));
HANDLE->SetEnvironmentMap(tex_handle, triton_tex_mat);
}
GLuint Environment::GetEnvironmentMap() const {
::Triton::TextureHandle tex_handle = HANDLE->GetEnvironmentMap();
return static_cast<GLuint>((size_t)tex_handle);
}
osg::Matrixd Environment::GetEnvironmentMapMatrix() const {
::Triton::Matrix3 m = HANDLE->GetEnvironmentMapMatrix();
osg::Matrixd env_map_matrix(
m.elem[0][0], m.elem[0][1], m.elem[0][2], 0,
m.elem[1][0], m.elem[1][1], m.elem[1][2], 0,
m.elem[2][0], m.elem[2][1], m.elem[2][2], 0,
0, 0, 0, 1);
return env_map_matrix;
}
SETGET(Environment, SunIntensity, float);
//................................
#undef HANDLE
#define HANDLE ((::Triton::Ocean*)_handle)
SETGET(Ocean, Choppiness, float);
//SETGET(Ocean, MaximumWavePeriod, double);
SETGET_EXPLICIT(Ocean, EnableSpray, SprayEnabled, bool);
SETGET_EXPLICIT(Ocean, EnableGodRays, GodRaysEnabled, bool);
SETGET(Ocean, GodRaysFade, float);
void Ocean::EnableWireframe(bool wireframe) { HANDLE->EnableWireframe(wireframe); }
void Ocean::SetQuality(OceanQuality value) { HANDLE->SetQuality((::Triton::OceanQuality)value); }
OceanQuality Ocean::GetQuality() const { return (OceanQuality)HANDLE->GetQuality(); }

View File

@ -1,112 +0,0 @@
/* -*-c++-*- */
/* osgEarth - Geospatial SDK for OpenSceneGraph
* Copyright 2020 Pelican Mapping
* http://osgearth.org
*
* osgEarth is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#ifndef OSGEARTH_TRITON_API_WRAPPER
#define OSGEARTH_TRITON_API_WRAPPER 1
//#include "Common"
#include <osg/Vec3>
#include <osg/Matrix>
#include <osg/GL>
#include <stdint.h> // for uintptr_t
namespace osgEarth {
namespace Util {
class OceanNode;
}
}
namespace osgEarth { namespace Triton
{
/** Enumerates the ocean quality settings used in Ocean::SetQuality() */
enum OceanQuality {
GOOD,
BETTER,
BEST
};
class BreakingWavesParameters
{
public:
void SetSteepness(float);
float GetSteepness() const;
void SetWavelength(float);
float GetWavelength() const;
public:
BreakingWavesParameters(uintptr_t handle) : _handle(handle) { }
uintptr_t _handle;
};
class Environment
{
public:
void SetDirectionalLight(const osg::Vec3& dir, const osg::Vec3& color);
osg::Vec3 GetLightDirection() const;
osg::Vec3 GetDirectionalLightColor() const;
void SetAmbientLight(const osg::Vec3& color);
osg::Vec3 GetAmbientLightColor() const;
void SetSunIntensity(float intensity);
float GetSunIntensity() const;
BreakingWavesParameters GetBreakingWavesParameters() const;
void SimulateSeaState(double bs, double winddir);
void SetAboveWaterVisibility(double visibility, osg::Vec3 fog_color);
void GetAboveWaterVisibility(double &visibility, osg::Vec3 &fog_color) const;
void SetEnvironmentMap(GLuint id, const osg::Matrixd &textureMatrix = osg::Matrixd());
GLuint GetEnvironmentMap() const;
osg::Matrixd GetEnvironmentMapMatrix() const;
public:
Environment(uintptr_t handle) : _handle(handle) { }
uintptr_t _handle;
};
class Ocean
{
public:
void SetChoppiness(float);
float GetChoppiness() const;
void EnableWireframe(bool wireframe);
void SetQuality(OceanQuality value);
OceanQuality GetQuality() const;
void EnableSpray(bool enabled);
bool SprayEnabled() const;
void EnableGodRays(bool enabled);
bool GodRaysEnabled() const;
void SetGodRaysFade(float fadeAmount);
float GetGodRaysFade() const;
public:
Ocean(uintptr_t handle) : _handle(handle) { }
uintptr_t _handle;
};
} } // namespace osgEarth::SilverLining
#endif // OSGEARTH_TRITON_API_WRAPPER

View File

@ -1,39 +0,0 @@
/* -*-c++-*- */
/* osgEarth - Geospatial SDK for OpenSceneGraph
* Copyright 2020 Pelican Mapping
* http://osgearth.org
*
* osgEarth is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#ifndef OSGEARTH_TRITON_CALLBACK_H
#define OSGEARTH_TRITON_CALLBACK_H 1
#include "TritonAPIWrapper.h"
namespace osgEarth { namespace Triton
{
/**
* A callback that lets you execute code in the proper context.
*/
class Callback : public osg::Referenced
{
public:
virtual void onInitialize(Environment& env, Ocean& ocean) { }
virtual void onDrawOcean(Environment& env, Ocean& ocean) { }
};
} } // namespace osgEarth::Triton
#endif // OSGEARTH_TRITON_CALLBACK_H

View File

@ -1,229 +0,0 @@
/* -*-c++-*- */
/* osgEarth - Geospatial SDK for OpenSceneGraph
* Copyright 2020 Pelican Mapping
* http://osgearth.org
*
* osgEarth is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#include "TritonContext.h"
#include <osg/GLExtensions>
#include <osg/Math>
#include <osgDB/FileNameUtils>
#include <osgEarth/SpatialReference>
#include <cstdlib>
#include <QApplication>
#define LC "[TritonContext] "
using namespace osgEarth::Triton;
TritonContext::TritonContext(const TritonLayer::Options& options) :
_options ( options ),
_initAttempted ( false ),
_initFailed ( false ),
_resourceLoader ( 0L ),
_environment ( 0L ),
_environmentWrapper ( 0L ),
_ocean ( 0L ),
_oceanWrapper ( 0L )
{
//nop
}
TritonContext::~TritonContext()
{
if (_oceanWrapper)
delete _oceanWrapper;
if (_environmentWrapper)
delete _environmentWrapper;
}
void
TritonContext::setSRS(const osgEarth::SpatialReference* srs)
{
_srs = srs;
}
void
TritonContext::setCallback(Callback* callback)
{
_callback = callback;
}
bool
TritonContext::passHeightMapToTriton() const
{
return _options.useHeightMap() == true;
}
int
TritonContext::getHeightMapSize() const
{
return osg::clampBetween(_options.heightMapSize().get(), 64u, 2048u);
}
const std::string&
TritonContext::getMaskLayerName() const
{
return _options.maskLayer().externalLayerName().get();
}
void
TritonContext::initialize(osg::RenderInfo& renderInfo)
{
if ( !_initAttempted && !_initFailed )
{
// lock/double-check:
std::lock_guard<std::mutex> excl(_initMutex);
if ( !_initAttempted && !_initFailed )
{
_initAttempted = true;
std::string resourcePath = _options.resourcePath().get();
if (resourcePath.empty() && ::getenv("TRITON_PATH"))
{
resourcePath = osgDB::concatPaths(::getenv("TRITON_PATH"), "Resources");
}
if ( resourcePath.empty() )
{
const QString dir = QString("%1/TritonResources").arg(QApplication::applicationDirPath());
resourcePath = dir.toStdString();
}
_resourceLoader = new ::Triton::ResourceLoader(resourcePath.c_str());
_environment = new ::Triton::Environment();
_environmentWrapper = new Environment((uintptr_t)_environment);
_environment->SetLicenseCode(
_options.user()->c_str(),
_options.licenseCode()->c_str() );
// "WGS84" is used to represent any ellipsoid.
::Triton::CoordinateSystem cs =
_srs->isGeographic() ? ::Triton::WGS84_ZUP :
::Triton::FLAT_ZUP;
// Set the ellipsoid to match the one in our map's SRS.
if ( _srs->isGeographic() )
{
const Ellipsoid& ellipsoid = _srs->getEllipsoid();
std::string eqRadius = Stringify() << ellipsoid.getRadiusEquator();
std::string poRadius = Stringify() << ellipsoid.getRadiusPolar();
_environment->SetConfigOption( "equatorial-earth-radius-meters", eqRadius.c_str() );
_environment->SetConfigOption( "polar-earth-radius-meters", poRadius.c_str() );
}
//_environment->SetConfigOption("avoid-opengl-stalls", "yes");
//_environment->SetConfigOption("fft-texture-update-frame-delayed", "yes");
float openGLVersion = osg::getGLVersionNumber();
enum ::Triton::Renderer tritonOpenGlVersion = ::Triton::OPENGL_2_0;
#ifndef OSG_GL_FIXED_FUNCTION_AVAILABLE
if( openGLVersion >= 4.1 )
tritonOpenGlVersion = ::Triton::OPENGL_4_1;
else if( openGLVersion >= 4.0 )
tritonOpenGlVersion = ::Triton::OPENGL_4_0;
else if( openGLVersion >= 3.2 )
tritonOpenGlVersion = ::Triton::OPENGL_3_2;
#endif
::Triton::EnvironmentError err = _environment->Initialize(
cs,
tritonOpenGlVersion,
_resourceLoader );
if ( err == ::Triton::SUCCEEDED )
{
::Triton::WindFetch wf;
wf.SetWind( 10.0, 0.0 );
_environment->AddWindFetch( wf );
_ocean = ::Triton::Ocean::Create(
_environment,
::Triton::JONSWAP,
true ); // enableHeightTests - activated GetHeight for intersections
}
if ( _ocean )
{
_oceanWrapper = new Ocean((uintptr_t)_ocean);
// fire init callback if available
if (_callback.valid())
{
_callback->onInitialize(getEnvironmentWrapper(), getOceanWrapper());
}
OE_INFO << LC << "Triton initialized OK!" << std::endl;
}
else
{
_initFailed = true;
OE_WARN << LC << "Triton initialization failed- err=" << err << std::endl;
}
}
}
}
bool
TritonContext::intersect(const osg::Vec3d& start, const osg::Vec3d& dir, float& out_height, osg::Vec3f& out_normal) const
{
::Triton::Vector3 p(start.ptr());
::Triton::Vector3 d(dir.ptr());
::Triton::Vector3 normal;
bool ok = _ocean->GetHeight(p, d, out_height, normal);
out_normal.set(normal.x, normal.y, normal.z);
return ok;
}
void
TritonContext::resizeGLObjectBuffers(unsigned maxSize)
{
osg::Object::resizeGLObjectBuffers(maxSize);
}
void
TritonContext::releaseGLObjects(osg::State* state) const
{
osg::Object::releaseGLObjects(state);
OE_DEBUG << LC << "Triton shutting down - releasing GL resources\n";
if (state)
{
if ( _ocean )
{
delete _ocean;
_ocean = 0L;
}
if ( _environment )
{
delete _environment;
_environment = 0L;
}
if ( _resourceLoader )
{
delete _resourceLoader;
_resourceLoader = 0L;
}
}
}

View File

@ -1,115 +0,0 @@
/* -*-c++-*- */
/* osgEarth - Geospatial SDK for OpenSceneGraph
* Copyright 2020 Pelican Mapping
* http://osgearth.org
*
* osgEarth is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#ifndef OSGEARTH_TRITON_CONTEXT_H
#define OSGEARTH_TRITON_CONTEXT_H
#include <Triton.h>
#include <Camera.h> // Triton
#include "TritonLayer.h"
#include "TritonAPIWrapper.h"
#include "TritonCallback.h"
#include <osg/Referenced>
#include <osg/Light>
#include <osgEarth/Threading>
namespace osgEarth {
class SpatialReference;
}
namespace osgEarth { namespace Triton
{
/**
* Contains all the Triton SDK handles.
*/
class TritonContext : public osg::Object
{
public:
META_Object(osgEarth, TritonContext);
TritonContext(const TritonLayer::Options&);
/** Sets the spatial reference system of the map */
void setSRS(const osgEarth::SpatialReference* srs);
/** Sets the user callback */
void setCallback(Callback* callback);
Callback* getCallback() const { return _callback.get(); }
public: // accessors
bool ready() const { return _initAttempted && !_initFailed; }
/** Spatial reference of the map */
const osgEarth::SpatialReference* getSRS() const { return _srs.get(); }
void initialize(osg::RenderInfo& renderInfo);
bool intersect(const osg::Vec3d& start, const osg::Vec3d& dir, float& out_height, osg::Vec3f& out_normal) const;
::Triton::Environment* getEnvironment() { return _environment; }
Environment& getEnvironmentWrapper() const { return *_environmentWrapper; }
::Triton::Ocean* getOcean() { return _ocean; }
Ocean& getOceanWrapper() const { return *_oceanWrapper; }
bool passHeightMapToTriton() const;
int getHeightMapSize() const;
const std::string& getMaskLayerName() const;
public: // osg::Object
void resizeGLObjectBuffers(unsigned maxSize);
/** If State is non-zero, this function releases any associated OpenGL objects for
* the specified graphics context. Otherwise, releases OpenGL objects
* for all graphics contexts. */
void releaseGLObjects(osg::State* state) const;
protected:
virtual ~TritonContext();
// hidden ctors (for META_Object)
TritonContext() { }
TritonContext(const TritonContext&, const osg::CopyOp&) { }
private:
TritonLayer::Options _options;
bool _initAttempted;
bool _initFailed;
std::mutex _initMutex;
osg::ref_ptr<const osgEarth::SpatialReference> _srs;
mutable ::Triton::ResourceLoader* _resourceLoader;
mutable ::Triton::Environment* _environment;
mutable ::Triton::Ocean* _ocean;
Environment* _environmentWrapper;
Ocean* _oceanWrapper;
osg::ref_ptr<Callback> _callback;
};
} } // namespace osgEarth::Triton
#endif // OSGEARTH_TRITON_CONTEXT_H

View File

@ -1,330 +0,0 @@
/* -*-c++-*- */
/* osgEarth - Geospatial SDK for OpenSceneGraph
* Copyright 2020 Pelican Mapping
* http://osgearth.org
*
* osgEarth is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#include "TritonContext.h"
#include "TritonDrawable.h"
#include "TritonHeightMap.h"
#include <Version.h>
#include <osg/MatrixTransform>
#include <osg/FrameBufferObject>
#include <osg/Depth>
#include <osgEarth/SpatialReference>
#include <osgEarth/VirtualProgram>
#include <osgEarth/MapNode>
#include <osgEarth/TerrainEngineNode>
#include <osgEarth/Random>
#include <osgEarth/GLUtils>
#undef LC
#define LC "[TritonDrawable] "
//#define DEBUG_HEIGHTMAP
using namespace osgEarth::Triton;
TritonDrawable::TritonDrawable(TritonContext* TRITON) :
_TRITON(TRITON)
{
// call this to ensure draw() gets called every frame.
setSupportsDisplayList( false );
setUseVertexBufferObjects( false );
// dynamic variance prevents update/cull overlap when drawing this
setDataVariance( osg::Object::DYNAMIC );
_wgs84 = SpatialReference::get("wgs84");
_ecef = _wgs84->getGeocentricSRS();
}
TritonDrawable::~TritonDrawable()
{
//nop
}
void
TritonDrawable::setMaskLayer(const osgEarth::ImageLayer* layer)
{
_maskLayer = layer;
}
void
TritonDrawable::setHeightMapGenerator(TritonHeightMap* value)
{
_heightMapGenerator = value;
}
void
TritonDrawable::setPlanarReflectionMap(osg::Texture2D* map)
{
_planarReflectionMap = map;
}
void
TritonDrawable::setPlanarReflectionProjection(osg::RefMatrix* proj)
{
_planarReflectionProjection = proj;
}
osg::BoundingBox
TritonDrawable::computeBoundingBox() const
{
return osg::BoundingBox();
}
namespace {
// Wrapper around Ocean->GetShaderObject() to account for API changes from Triton 3.x to 4.x
GLint
getOceanShader(::Triton::Ocean* ocean, ::Triton::Shaders shaderProgram, void* context, const ::Triton::Camera* camera)
{
#if (TRITON_MAJOR_VERSION >= 4)
return (GLint)ocean->GetShaderObject( shaderProgram, context, camera );
#else
return (GLint)ocean->GetShaderObject( shaderProgram );
#endif
}
}
void
TritonDrawable::drawImplementation(osg::RenderInfo& renderInfo) const
{
OE_GL_ZONE;
osg::State* state = renderInfo.getState();
state->disableAllVertexArrays();
_TRITON->initialize( renderInfo );
if ( !_TRITON->ready() )
return;
// Configure the height map generator.
// If configuration fails, attempt to continue without a heightmap.
if (_heightMapGenerator.valid())
{
bool configOK = _heightMapGenerator->configure(_TRITON->getHeightMapSize(), *state);
if (configOK == false)
{
_heightMapGenerator = 0L;
OE_WARN << LC << "Failed to establish a legal FBO configuration; disabling height map generator!" << std::endl;
}
}
::Triton::Environment* environment = _TRITON->getEnvironment();
// Find or create the Triton camera for this OSG camera:
CameraLocal& local = _local.get(renderInfo.getCurrentCamera());
if (local._tritonCam == 0L)
{
local._tritonCam = environment->CreateCamera();
local._tritonCam->SetName(renderInfo.getCurrentCamera()->getName().c_str());
}
::Triton::Camera* tritonCam = local._tritonCam;
auto cid = GLUtils::getSharedContextID(*state);
osgEarth::NativeProgramAdapterCollection& adapters = _adapters[cid];
if ( adapters.empty() )
{
OE_DEBUG << LC << "Initializing Triton program adapters" << std::endl;
const std::vector<const char*> prefixes = { "osg_", "oe_" };
adapters.push_back( new osgEarth::NativeProgramAdapter(state, getOceanShader(_TRITON->getOcean(), ::Triton::WATER_SURFACE, 0L, tritonCam), prefixes, "WATER_SURFACE"));
adapters.push_back( new osgEarth::NativeProgramAdapter(state, getOceanShader(_TRITON->getOcean(), ::Triton::WATER_SURFACE_PATCH, 0L, tritonCam), prefixes, "WATER_SURFACE_PATCH"));
adapters.push_back( new osgEarth::NativeProgramAdapter(state, getOceanShader(_TRITON->getOcean(), ::Triton::GOD_RAYS, 0L, tritonCam), prefixes, "GOD_RAYS"));
adapters.push_back( new osgEarth::NativeProgramAdapter(state, getOceanShader(_TRITON->getOcean(), ::Triton::SPRAY_PARTICLES, 0L, tritonCam), prefixes, "SPRAY_PARTICLES"));
adapters.push_back( new osgEarth::NativeProgramAdapter(state, getOceanShader(_TRITON->getOcean(), ::Triton::WAKE_SPRAY_PARTICLES, 0L, tritonCam), prefixes, "WAKE_SPRAY_PARTICLES"));
#if 0
// In older Triton (3.91), this line causes problems in Core profile and prevents the ocean from drawing. In newer Triton (4.01),
// this line causes a crash because there is no context passed in to GetShaderObject(), resulting in multiple NULL references.
adapters.push_back( new osgEarth::NativeProgramAdapter(state, getOceanShader(_TRITON->getOcean(), ::Triton::WATER_DECALS, 0L, tritonCam), prefixes, "WATER_DECALS"));
#endif
}
adapters.apply( state );
// Pass the final view and projection matrices into Triton.
if ( environment )
{
tritonCam->SetCameraMatrix(state->getModelViewMatrix().ptr());
tritonCam->SetProjectionMatrix(state->getProjectionMatrix().ptr());
}
// Calculate sea level based on the camera:
if (_verticalDatum.valid())
{
GeoPoint cam(_ecef, osg::Vec3d(0, 0, 0) * state->getInitialInverseViewMatrix(), ALTMODE_ABSOLUTE);
cam.transformInPlace(_wgs84);
auto msl = _verticalDatum->hae2msl(cam.y(), cam.x(), 0.0);
environment->SetSeaLevel(-msl);
}
if (_heightMapGenerator.valid())
{
GLint texName;
osg::Matrix hMM;
if (_heightMapGenerator->getTextureAndMatrix(renderInfo, texName, hMM))
{
// copy the OSG matrix to a Triton matrix:
::Triton::Matrix4 texMat(
hMM(0, 0), hMM(0, 1), hMM(0, 2), hMM(0, 3),
hMM(1, 0), hMM(1, 1), hMM(1, 2), hMM(1, 3),
hMM(2, 0), hMM(2, 1), hMM(2, 2), hMM(2, 3),
hMM(3, 0), hMM(3, 1), hMM(3, 2), hMM(3, 3));
environment->SetHeightMap((::Triton::TextureHandle)texName, texMat, 0L, tritonCam);
//OE_DEBUG << LC << "Updating height map, FN=" << renderInfo.getState()->getFrameStamp()->getFrameNumber() << std::endl;
}
}
state->dirtyAllVertexArrays();
// Now light and draw the ocean:
if ( environment )
{
// User pre-draw callback:
if (_TRITON->getCallback())
{
_TRITON->getCallback()->onDrawOcean(
_TRITON->getEnvironmentWrapper(),
_TRITON->getOceanWrapper());
}
osg::Light* light = renderInfo.getView() ? renderInfo.getView()->getLight() : NULL;
// This is the light attached to View so there are no transformations above..
// But in general case you would need to accumulate all transforms above the light into this matrix
osg::Matrix lightLocalToWorldMatrix = osg::Matrix::identity();
// If you don't know where the sun lightsource is attached and don't know its local to world matrix you may use
// following elaborate scheme to grab the light source while drawing Triton ocean:
// - Install cull callback to catch CullVisitor and record pointer to its associated RenderStage
// I was hoping RenderStage can be found from renderInfo in drawImplementation but I didn't figure how ...
// - When TritonDrawable::drawImplementation is called all lights will be already applied to OpenGL
// then just find proper infinite directional light by scanning renderStage->PositionalStateContainer.
// - Note that we canot scan for the lights inside cull because they may not be traversed before Triton drawable
// - When you found interesting ligt source that can work as Sun, read its modelview matrix and lighting params
// Multiply light position by ( modelview * inverse camera view ) and pass this to Triton with lighting colors
if ( light && light->getPosition().w() == 0 )
{
osg::Vec4 ambient = light->getAmbient();
osg::Vec4 diffuse = light->getDiffuse();
osg::Vec4 position = light->getPosition();
// Compute light position/direction in the world
position = position * lightLocalToWorldMatrix;
// Diffuse direction and color
environment->SetDirectionalLight(
::Triton::Vector3( position[0], position[1], position[2] ),
::Triton::Vector3( diffuse[0], diffuse[1], diffuse[2] ) );
// Sun-based ambient value:
osg::Vec3d up = osg::Vec3d(0,0,0) * renderInfo.getCurrentCamera()->getInverseViewMatrix();
up.normalize();
osg::Vec3d pos3 = osg::Vec3d(position.x(), position.y(), position.z());
pos3.normalize();
float dot = osg::clampAbove(up*pos3, 0.0); dot*=dot;
float sunAmbient = (float)osg::clampBetween( dot, 0.0f, 0.88f );
float fa = osg::maximum(sunAmbient, ambient[0]);
// Ambient color based on the zenith color in the cube map
environment->SetAmbientLight( ::Triton::Vector3(fa, fa, fa) );
}
else
{
environment->SetDirectionalLight( ::Triton::Vector3(0,0,1), ::Triton::Vector3(1,1,1) );
environment->SetAmbientLight( ::Triton::Vector3(0.88f, 0.88f, 0.88f) );
}
if ( _cubeMap.valid() )
{
// Build transform from our cube map orientation space to native Triton orientation
// See worldToCubeMap function used in SkyBox to orient sky texture so that sky is up and earth is down
osg::Matrix m = osg::Matrix::rotate( osg::PI_2, osg::X_AXIS ); // = worldToCubeMap
::Triton::Matrix3 transformFromYUpToZUpCubeMapCoords(
m(0,0), m(0,1), m(0,2),
m(1,0), m(1,1), m(1,2),
m(2,0), m(2,1), m(2,2) );
// Grab the cube map from our sky box and give it to Triton to use as an _environment map
// GLenum texture = renderInfo.getState()->getLastAppliedTextureAttribute( _stage, osg::StateAttribute::TEXTURE );
environment->SetEnvironmentMap(
(::Triton::TextureHandle)_cubeMap->getTextureObject(cid)->id(),
transformFromYUpToZUpCubeMapCoords );
if( _planarReflectionMap.valid() && _planarReflectionProjection.valid() )
{
osg::Matrix & p = *_planarReflectionProjection;
::Triton::Matrix3 planarProjection(
p(0,0), p(0,1), p(0,2),
p(1,0), p(1,1), p(1,2),
p(2,0), p(2,1), p(2,2) );
environment->SetPlanarReflectionMap(
(::Triton::TextureHandle)_planarReflectionMap->getTextureObject(cid)->id(),
planarProjection,
0.125 );
}
}
// Draw the ocean for the current time sample
if ( _TRITON->getOcean() )
{
osg::GLExtensions* ext = osg::GLExtensions::Get(cid, true);
bool writeDepth = true;
const osg::Depth* depth = static_cast<const osg::Depth*>(state->getLastAppliedAttribute(osg::StateAttribute::DEPTH));
if (depth)
writeDepth = depth->getWriteMask();
double simTime = renderInfo.getView()->getFrameStamp()->getSimulationTime();
simTime = fmod(simTime, 86400.0);
_TRITON->getOcean()->Draw(
simTime,
writeDepth, // depth writes
true, // draw water
true, // draw particles
NULL, // optional context
tritonCam);
}
}
// Put GL back in a state that won't confuse the OSG state tracking:
state->dirtyAllVertexArrays();
state->dirtyAllAttributes();
state->dirtyAllModes();
#ifndef OSG_GL_FIXED_FUNCTION_AVAILABLE
// Keep OSG from reapplying GL_LIGHTING on next state change after dirtyAllModes().
state->setModeValidity(GL_LIGHTING, false);
#endif
// Keep an eye on this.
// I had to remove something similar in another module (Rex engine) because it was causing
// positional attributes (like clip planes) to re-apply with an incorrect MVM. -gw
state->apply();
}

View File

@ -1,102 +0,0 @@
/* -*-c++-*- */
/* osgEarth - Geospatial SDK for OpenSceneGraph
* Copyright 2020 Pelican Mapping
* http://osgearth.org
*
* osgEarth is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#ifndef OSGEARTH_TRITON_DRAWABLE_H
#define OSGEARTH_TRITON_DRAWABLE_H
#include <osg/Drawable>
#include <osg/RenderInfo>
#include <osg/TextureCubeMap>
#include <osg/Version>
#include <osg/Texture2D>
#include <osg/buffered_value>
#include <osgEarth/Terrain>
#include <osgEarth/NativeProgramAdapter>
#include <osgEarth/ImageLayer>
#include <osgEarth/VerticalDatum>
const unsigned int TRITON_OCEAN_MASK = 0x4; // 0100
namespace osgEarth { namespace Triton
{
class TritonContext;
class TritonHeightMap;
/**
* Custom drawable for rendering the Triton ocean effects
*/
class TritonDrawable : public osg::Drawable
{
public:
TritonDrawable(TritonContext* TRITON);
//! Layer to use as an ocean rendering mask
void setMaskLayer(const osgEarth::ImageLayer* maskLayer);
//! Height map generator to use to mask out the ocean where the
//! terrain has positive elevation
void setHeightMapGenerator(TritonHeightMap* heightMap);
//! Vertical datum to use to calculate sea level
void setVerticalDatum(VerticalDatum* value) {
_verticalDatum = value;
}
//! Gets the Triton Camera associated with an osg Camera
::Triton::Camera* getTritonCam(const osg::Camera* cam) {
return _local.get(cam)._tritonCam;
}
void setPlanarReflectionMap(osg::Texture2D* map);
void setPlanarReflectionProjection(osg::RefMatrix* proj);
public: // osg::Drawable
void drawImplementation(osg::RenderInfo& ri) const override;
osg::BoundingBox computeBoundingBox() const override;
protected:
virtual ~TritonDrawable();
osg::observer_ptr<TritonContext> _TRITON;
osg::observer_ptr<const osgEarth::ImageLayer> _maskLayer;
osg::ref_ptr<osg::TextureCubeMap> _cubeMap;
osg::ref_ptr<osg::Texture2D> _planarReflectionMap;
osg::ref_ptr<osg::RefMatrix> _planarReflectionProjection;
mutable osg::ref_ptr<TritonHeightMap> _heightMapGenerator;
osg::ref_ptr<VerticalDatum> _verticalDatum;
osg::ref_ptr<const SpatialReference> _wgs84, _ecef;
mutable osg::buffered_object<osgEarth::NativeProgramAdapterCollection> _adapters;
struct CameraLocal
{
::Triton::Camera* _tritonCam = nullptr;
};
mutable PerObjectFastMap<const osg::Camera*, CameraLocal> _local;
};
} } // namespace osgEarth::Triton
#endif // OSGEARTH_TRITON_DRAWABLE_H

View File

@ -1,434 +0,0 @@
/* -*-c++-*- */
/* osgEarth - Geospatial SDK for OpenSceneGraph
* Copyright 2020 Pelican Mapping
* http://osgearth.org
*
* osgEarth is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#include "TritonHeightMap.h"
#include "TritonContext.h"
#include <osgEarth/CullingUtils>
#include <osgEarth/VirtualProgram>
#include <osgEarth/TerrainEngineNode>
#include <osgEarth/Utils>
#define LC "[TritonHeightMap] "
using namespace osgEarth::Triton;
namespace
{
const char* vertexShader =
"#pragma import_defines(OE_TRITON_MASK_MATRIX);\n"
"// terrain SDK:\n"
"float oe_terrain_getElevation(); \n"
"out float oe_triton_elev;\n"
"#ifdef OE_TRITON_MASK_MATRIX\n"
"out vec2 maskCoords;\n"
"uniform mat4 OE_TRITON_MASK_MATRIX;\n"
"vec4 oe_layer_tilec;\n"
"#endif\n"
"void oe_triton_setupHeightMap(inout vec4 unused) \n"
"{ \n"
" oe_triton_elev = oe_terrain_getElevation(); \n"
"#ifdef OE_TRITON_MASK_MATRIX\n"
" maskCoords = (OE_TRITON_MASK_MATRIX * oe_layer_tilec).st;\n"
"#endif\n"
"} \n";
// The fragment shader simply takes the texture index that we generated
// in the vertex shader and does a texture lookup. In this case we're
// just wholesale replacing the color, so if the map had any existing
// imagery, this will overwrite it.
const char* fragmentShader =
"#pragma import_defines(OE_TRITON_MASK_SAMPLER);\n"
"in float oe_triton_elev;\n"
"#ifdef OE_TRITON_MASK_SAMPLER\n"
"in vec2 maskCoords;\n"
"uniform sampler2D OE_TRITON_MASK_SAMPLER;\n"
"#endif\n"
"out vec4 out_height; \n"
"void oe_triton_drawHeightMap(inout vec4 unused) \n"
"{ \n"
#ifdef DEBUG_HEIGHTMAP
// Map to black = -500m, white = +500m
" float nHeight = clamp(oe_triton_elev / 1000.0 + 0.5, 0.0, 1.0);\n"
#else
" float nHeight = oe_triton_elev;\n"
"#ifdef OE_TRITON_MASK_SAMPLER\n"
" float mask = texture(OE_TRITON_MASK_SAMPLER, maskCoords).a;\n"
" nHeight *= mask; \n"
"#endif\n"
#endif
" out_height = vec4( nHeight, 0.0, 0.0, 1.0 ); \n"
"} \n";
struct TerrainDirtyCallback : public osgEarth::TerrainCallback
{
osg::observer_ptr<TritonHeightMap> _hm;
TerrainDirtyCallback(TritonHeightMap* hm) : _hm(hm) { }
void onTileUpdate(const osgEarth::TileKey&, osg::Node*, osgEarth::TerrainCallbackContext&)
{
osg::ref_ptr<TritonHeightMap> hm;
if (_hm.lock(hm))
hm->dirty();
}
};
}
TritonHeightMap::TritonHeightMap() :
_texSize(0u),
_internalFormat((GLint)0),
_sourceFormat((GLenum)0)
{
setCullingActive(false);
}
TritonHeightMap::~TritonHeightMap()
{
osgEarth::TerrainEngineNode* t = dynamic_cast<osgEarth::TerrainEngineNode*>(_terrain.get());
if (t)
{
t->getTerrain()->removeTerrainCallback(static_cast<TerrainDirtyCallback*>(_terrainCallback.get()));
_terrainCallback = NULL;
}
}
void
TritonHeightMap::setTerrain(osg::Node* node)
{
_terrain = node;
osgEarth::TerrainEngineNode* t = dynamic_cast<osgEarth::TerrainEngineNode*>(node);
if (t)
{
TerrainDirtyCallback* cb = new TerrainDirtyCallback(this);
t->getTerrain()->addTerrainCallback(cb);
_terrainCallback = cb;
}
}
void
TritonHeightMap::setMaskLayer(const osgEarth::ImageLayer* layer)
{
_maskLayer = layer;
}
void
TritonHeightMap::SetDirty::operator()(CameraLocal& local)
{
local._mvpw.makeIdentity();
}
void
TritonHeightMap::dirty()
{
SetDirty setDirty;
_local.forEach(setDirty);
}
bool
TritonHeightMap::configure(unsigned texSize, osg::State& state)
{
bool result = true;
if (_texSize == 0u)
{
// first time through, single-lane and set up FBO parameters.
static std::mutex s_mutex;
std::lock_guard<std::mutex> lock(s_mutex);
if (_texSize == 0u)
{
_texSize = texSize;
if (!getBestFBOConfig(state, _internalFormat, _sourceFormat))
{
result = false;
}
}
}
return result;
}
namespace {
struct Format {
Format(GLint i, GLenum s, const std::string& n) :
internalFormat(i), sourceFormat(s), name(n) { }
GLint internalFormat;
GLenum sourceFormat;
std::string name;
};
}
bool
TritonHeightMap::getBestFBOConfig(osg::State& state, GLint& out_internalFormat, GLenum& out_sourceFormat)
{
#ifdef GL_LUMINANCE_FLOAT16_ATI
# define GL_LUMINANCE_FLOAT16_ATI 0x881E
#endif
std::vector<Format> formats;
#ifdef GL_R16F
formats.push_back(Format(GL_R16F, GL_RED, "GL_R16F"));
#endif
#ifdef GL_LUMINANCE16F_ARB
formats.push_back(Format(GL_LUMINANCE16F_ARB, GL_LUMINANCE, "GL_LUMINANCE16F_ARB"));
#endif
#ifdef GL_LUMINANCE_FLOAT16_ATI
formats.push_back(Format(GL_LUMINANCE_FLOAT16_ATI, GL_LUMINANCE, "GL_LUMINANCE_FLOAT16_ATI"));
#endif
#ifdef GL_R32F
formats.push_back(Format(GL_R32F, GL_RED, "GL_R32F"));
#endif
#ifdef GL_LUMINANCE32F_ARB
formats.push_back(Format(GL_LUMINANCE32F_ARB, GL_LUMINANCE, "GL_LUMINANCE32F_ARB"));
#endif
#ifdef GL_RGB16F_ARB
formats.push_back(Format(GL_RGB16F_ARB, GL_RGB, "GL_RGB16F_ARB"));
#endif
#ifdef GL_RGBA16F_ARB
formats.push_back(Format(GL_RGBA16F_ARB, GL_RGBA, "GL_RGBA16F_ARB"));
#endif
#ifdef GL_RGB32F_ARB
formats.push_back(Format(GL_RGB32F_ARB, GL_RGB, "GL_RGB32F_ARB"));
#endif
#ifdef GL_RGBA32F_ARB
formats.push_back(Format(GL_RGBA32F_ARB, GL_RGBA, "GL_RGBA32F_ARB"));
#endif
auto cid = GLUtils::getSharedContextID(state);
osg::GLExtensions* ext = osg::GLExtensions::Get(cid, true);
osg::State::CheckForGLErrors check = state.getCheckForGLErrors();
state.setCheckForGLErrors(state.NEVER_CHECK_GL_ERRORS);
bool found = false;
for(int i=0; i<formats.size() && !found; ++i)
{
const Format& format = formats[i];
osg::ref_ptr<osg::Texture2D> tex = new osg::Texture2D();
tex->setTextureSize(1, 1);
tex->setInternalFormat( format.internalFormat );
tex->setSourceFormat ( format.sourceFormat );
osg::ref_ptr<osg::FrameBufferObject> fbo = new osg::FrameBufferObject();
fbo->setAttachment( osg::Camera::COLOR_BUFFER0, osg::FrameBufferAttachment(tex.get()) );
fbo->apply( state );
GLenum status = ext->glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT);
fbo->releaseGLObjects( &state );
tex->releaseGLObjects( &state );
if ( status == GL_FRAMEBUFFER_COMPLETE_EXT )
{
out_internalFormat = format.internalFormat;
out_sourceFormat = format.sourceFormat;
found = true;
}
}
state.setCheckForGLErrors(check);
return found;
}
bool
TritonHeightMap::isConfigurationComplete() const
{
return
_texSize > 0u &&
_internalFormat != (GLint)0 &&
_sourceFormat != (GLenum)0;
}
void
TritonHeightMap::setup(CameraLocal& local, const std::string& name)
{
// make sure the FBO params are configured:
if (!isConfigurationComplete())
return;
local._frameNum = 0u;
local._tex = new osg::Texture2D();
local._tex->setName(Stringify() << "Triton HM (" << name << ")");
local._tex->setTextureSize(_texSize, _texSize);
local._tex->setInternalFormat( _internalFormat );
local._tex->setSourceFormat( _sourceFormat );
local._tex->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR);
local._tex->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR);
// Triton prob doesn't need this but it's good practice
if (_sourceFormat == GL_RED)
{
local._tex->setSwizzle(osg::Vec4i(GL_RED, GL_RED, GL_RED, GL_ONE));
}
local._rtt = new osg::Camera();
local._rtt->setName(local._tex->getName());
local._rtt->setReferenceFrame(osg::Transform::ABSOLUTE_RF_INHERIT_VIEWPOINT);
local._rtt->setClearMask(GL_COLOR_BUFFER_BIT); //GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
local._rtt->setClearColor(osg::Vec4(-1000.0, -1000.0, -1000.0, 1.0f));
local._rtt->setViewport(0, 0, _texSize, _texSize);
local._rtt->setRenderOrder(osg::Camera::PRE_RENDER);
local._rtt->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
local._rtt->setImplicitBufferAttachmentMask(0, 0);
local._rtt->attach(osg::Camera::COLOR_BUFFER0, local._tex.get());
//local._rtt->setCullMask( ~TRITON_OCEAN_MASK );
local._rtt->setAllowEventFocus(false);
local._rtt->setDrawBuffer(GL_FRONT);
local._rtt->setReadBuffer(GL_FRONT);
local._rtt->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
// TODO: create this once and just re-use it for all RTT cameras
osg::StateSet* rttSS = local._rtt->getOrCreateStateSet();
osgEarth::VirtualProgram* rttVP = osgEarth::VirtualProgram::getOrCreate(rttSS);
rttVP->setName("Triton Height Map");
rttVP->setFunction( "oe_triton_setupHeightMap", vertexShader, VirtualProgram::LOCATION_VERTEX_MODEL);
rttVP->setFunction( "oe_triton_drawHeightMap", fragmentShader, VirtualProgram::LOCATION_FRAGMENT_OUTPUT);
rttVP->setInheritShaders(false);
osg::StateAttribute::OverrideValue off = osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE;
rttSS->setDefine("OE_IS_DEPTH_CAMERA");
rttSS->setDefine("OE_TERRAIN_RENDER_IMAGERY", off);
rttSS->setDefine("OE_TERRAIN_RENDER_NORMAL_MAP", off);
rttSS->setDefine("OE_TERRAIN_BLEND_IMAGERY", off);
rttSS->setDefine("OE_TERRAIN_MORPH_GEOMETRY", off);
osg::ref_ptr<const osgEarth::ImageLayer> maskLayer;
if (_maskLayer.lock(maskLayer))
{
rttSS->setDefine("OE_TRITON_MASK_SAMPLER", maskLayer->getSharedTextureUniformName());
rttSS->setDefine("OE_TRITON_MASK_MATRIX", maskLayer->getSharedTextureMatrixUniformName());
OE_DEBUG << LC << "Using mask layer \"" << maskLayer->getName() << "\", sampler=" << maskLayer->getSharedTextureUniformName() << ", matrix=" << maskLayer->getSharedTextureMatrixUniformName() << std::endl;
}
if (_terrain.valid())
{
local._rtt->addChild(_terrain.get());
}
else
{
OE_WARN << LC << "Illegal: no terrain set (must call setTerrain)" << std::endl;
}
}
#define MAXABS4(A,B,C,D) \
osg::maximum(fabs(A), osg::maximum(fabs(B), osg::maximum(fabs(C),fabs(D))))
void
TritonHeightMap::update(CameraLocal& local, const osg::Camera* cam, osgEarth::Horizon* horizon)
{
osg::Vec3d eye = osg::Vec3d(0,0,0) * cam->getInverseViewMatrix();
double hd = horizon->getDistanceToVisibleHorizon();
local._rtt->setProjectionMatrix(osg::Matrix::ortho(-hd, hd, -hd, hd, 1.0, eye.length()));
local._rtt->setViewMatrixAsLookAt(eye, osg::Vec3d(0.0,0.0,0.0), osg::Vec3d(0.0,0.0,1.0));
static const osg::Matrixd scaleBias(
0.5, 0.0, 0.0, 0.0,
0.0, 0.5, 0.0, 0.0,
0.0, 0.0, 0.5, 0.0,
0.5, 0.5, 0.5, 1.0);
// Matrix that Triton will use to position the heightmap for sampling.
local._texMatrix = local._rtt->getViewMatrix() * local._rtt->getProjectionMatrix() * scaleBias;
}
void
TritonHeightMap::traverse(osg::NodeVisitor& nv)
{
if (nv.getVisitorType() == nv.CULL_VISITOR)
{
osgUtil::CullVisitor* cv = osgEarth::Culling::asCullVisitor(nv);
const osg::Camera* camera = cv->getCurrentCamera();
if (camera)
{
CameraLocal& local = _local.get(camera);
if (isConfigurationComplete())
{
// create the RTT for this camera on first encounter:
if (!local._rtt.valid())
{
setup(local, camera->getName());
}
// only update when the MVPW changes.
if (local._mvpw != *cv->getMVPW())
{
// update the RTT based on the current camera:
osg::ref_ptr<Horizon> horizon;
ObjectStorage::get(&nv, horizon);
update(local, camera, horizon);
// finally, traverse the camera to build the height map.
local._rtt->accept(nv);
local._frameNum = nv.getFrameStamp()->getFrameNumber();
local._mvpw = *cv->getMVPW();
}
}
else
{
//OE_DEBUG << LC << "Configuration not yet complete..." << std::endl;
}
}
}
}
bool
TritonHeightMap::getTextureAndMatrix(osg::RenderInfo& ri, GLint& out_texName, osg::Matrix& out_matrix)
{
if (!isConfigurationComplete())
return false;
CameraLocal& local = _local.get(ri.getCurrentCamera());
if (!local._tex.valid())
return false;
// did the texture change?
//OE_DEBUG << "FN=" << ri.getState()->getFrameStamp()->getFrameNumber() << "; localFN=" << local._frameNum << std::endl;
if (ri.getState()->getFrameStamp()->getFrameNumber() > local._frameNum)
return false;
auto cid = GLUtils::getSharedContextID(*ri.getState());
osg::Texture::TextureObject* obj = local._tex->getTextureObject(cid);
if (!obj)
return false;
out_texName = obj->id();
out_matrix = local._texMatrix;
return true;
}

View File

@ -1,109 +0,0 @@
/* -*-c++-*- */
/* osgEarth - Geospatial SDK for OpenSceneGraph
* Copyright 2020 Pelican Mapping
* http://osgearth.org
*
* osgEarth is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#ifndef OSGEARTH_TRITON_HEIGHT_MAP
#define OSGEARTH_TRITON_HEIGHT_MAP 1
#include <osgEarth/Containers>
#include <osgEarth/ImageLayer>
#include <osg/Node>
#include <osg/Camera>
#include <osg/Texture2D>
namespace osgEarth {
class Horizon;
}
namespace osgEarth { namespace Triton
{
/**
* Creates a height map that Triton can use to mask out the ocean where
* the terrain is above sea level.
*/
class TritonHeightMap : public osg::Node
{
public:
TritonHeightMap();
//! Sets the root of the terrain scene graph
void setTerrain(osg::Node*);
//! Sets the masking layer
void setMaskLayer(const osgEarth::ImageLayer* layer);
//! Configure the generator; return success t/f
bool configure(unsigned texSize, osg::State& state);
//! Fetch the heightmap texture and matrix generated for a camera.
bool getTextureAndMatrix(osg::RenderInfo&, GLint& out_texName, osg::Matrix& out_matrix);
//! Mark all height maps (for all cameras) for regeneration
void dirty();
public: // osg::Node
void traverse(osg::NodeVisitor&);
protected:
virtual ~TritonHeightMap();
private:
struct CameraLocal
{
osg::ref_ptr<osg::Camera> _rtt;
osg::ref_ptr<osg::Texture2D> _tex;
osg::Matrix _texMatrix;
osg::Matrix _mvpw;
unsigned _frameNum;
};
typedef osgEarth::PerObjectFastMap<const osg::Camera*, CameraLocal> Locals;
struct SetDirty : public Locals::Functor
{
void operator()(CameraLocal&);
};
//! Sets up an RTT camera for the first time
void setup(CameraLocal& local, const std::string& name);
//! Updates an RTT camera for the new view/projection matrices of the camera
void update(CameraLocal& local, const osg::Camera*, osgEarth::Horizon*);
//! Whether FBO configuration has happened yet
bool isConfigurationComplete() const;
//! Figures out the best FBO format on this GPU
static bool getBestFBOConfig(osg::State& state, GLint& internalFormat, GLenum& sourceFormat);
Locals _local;
osg::observer_ptr<osg::Node> _terrain;
unsigned _texSize;
GLint _internalFormat;
GLenum _sourceFormat;
osg::observer_ptr<const osgEarth::ImageLayer> _maskLayer;
osg::ref_ptr<osg::Referenced> _terrainCallback;
};
} } // namespace osgEarth::Triton
#endif // OSGEARTH_TRITON_HEIGHT_MAP

View File

@ -1,51 +0,0 @@
/* -*-c++-*- */
/* osgEarth - Geospatial SDK for OpenSceneGraph
* Copyright 2020 Pelican Mapping
* http://osgearth.org
*
* osgEarth is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#include "TritonIntersections.h"
using namespace osgEarth;
using namespace osgEarth::Triton;
TritonIntersections::TritonIntersections() :
_maxRange(1.0, Units::KILOMETERS)
{
}
void
TritonIntersections::setAnchor(const GeoPoint& value)
{
_anchor = value;
// zero out the other stuff:
_anchor.z() = 0.0;
_anchor.altitudeMode() = ALTMODE_ABSOLUTE;
}
void
TritonIntersections::addLocalPoint(const osg::Vec3d& p)
{
_input.push_back(p);
_heights.resize(_input.size());
_normals.resize(_input.size());
}
void
TritonIntersections::setMaxRange(const Distance& range)
{
_maxRange = range;
}

View File

@ -1,72 +0,0 @@
/* -*-c++-*- */
/* osgEarth - Geospatial SDK for OpenSceneGraph
* Copyright 2020 Pelican Mapping
* http://osgearth.org
*
* osgEarth is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#ifndef OSGEARTH_TRITON_INTERSECTIONS
#define OSGEARTH_TRITON_INTERSECTIONS 1
#include <osgEarth/VisibleLayer>
#include <osgEarth/ImageLayer>
#include "TritonCallback.h"
namespace osgEarth { namespace Triton
{
/**
* Pass this structure to TritonLayer and it will automatically
* populate the results with ocean wave intersections (local coordinates
* and normals.)
*/
class TritonIntersections : public osg::Referenced
{
public:
//! Construct an empty set
TritonIntersections();
//! Anchor point for intersectsions in this set. Only the X and Y
//! components are used. Any local points you add to this set will
//! be in the local coordinate system (LTP) around this anchor point.
void setAnchor(const GeoPoint& p);
//! Adds a point to the intersection set. The point should be in the
//! local coordinate system of the anchor point.
void addLocalPoint(const osg::Vec3d& p);
//! Maximum range at which to perform intersections. Beyond this
//! range Triton will skip this set. Default is 2km.
void setMaxRange(const Distance& value);
const Distance& getMaxRange() const { return _maxRange; }
//! Vector of input local points added by addLocalPoint.
const std::vector<osg::Vec3d>& getInput() const { return _input; }
//! Vector of heights resulting from the intersection tests.
const std::vector<float>& getHeights() const { return _heights; }
//! Vector of normals resulting from the intersection tests.
const std::vector<osg::Vec3d>& getNormals() const { return _normals; }
private:
GeoPoint _anchor;
std::vector<osg::Vec3d> _input;
std::vector<float> _heights;
std::vector<osg::Vec3d> _normals;
Distance _maxRange;
friend class TritonLayerNode;
};
} }
#endif // OSGEARTH_TRITON_INTERSECTIONS

View File

@ -1,386 +0,0 @@
/* -*-c++-*- */
/* osgEarth - Geospatial SDK for OpenSceneGraph
* Copyright 2020 Pelican Mapping
* http://osgearth.org
*
* osgEarth is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#include "TritonLayer.h"
#include "TritonContext.h"
#include "TritonDrawable.h"
#include "TritonHeightMap.h"
#include "TritonCallback.h"
#include <osgEarth/MapNode>
#include <osgEarth/ImageLayer>
#include <osgEarth/NodeUtils>
#include <osgEarth/ElevationLOD>
#include <osgEarth/TerrainEngineNode>
#include <osgEarth/VerticalDatum>
#include <osgUtil/CullVisitor>
#define LC "[TritonLayer] "
using namespace osgEarth::Triton;
namespace osgEarth { namespace Triton
{
class TritonLayerNode : public osg::Group
{
public:
TritonLayerNode(osgEarth::Triton::TritonLayer* layer,
LayerReference<osgEarth::ImageLayer>& mask) :
_tritonLayer(layer),
_maskLayer(mask),
_callback(0L),
_needsMapNode(true)
{
// To detect the map node:
ADJUST_UPDATE_TRAV_COUNT(this, +1);
// Disable bounds culling
setCullingActive(false);
}
~TritonLayerNode()
{
//nop
}
void setUserCallback(osgEarth::Triton::Callback* callback)
{
_callback = callback;
}
void dirty()
{
create();
}
/** MapNode to use; will be discovered automatically if not set here */
void setMapNode(osgEarth::MapNode* mapNode)
{
if (!mapNode)
{
this->removeChildren(0, this->getNumChildren());
_drawable = 0L;
_TRITON = 0L;
_needsMapNode = true;
}
else
{
_mapNode = mapNode;
create();
}
}
void create()
{
this->removeChildren(0, this->getNumChildren());
_drawable = 0L;
osg::ref_ptr<osgEarth::MapNode> mapNode;
if (!_mapNode.lock(mapNode))
return;
const osgEarth::Map* map = mapNode->getMap();
// create an object to house Triton data and resources.
if (!_TRITON.valid())
_TRITON = new TritonContext(_tritonLayer->options());
if (map)
_TRITON->setSRS(map->getSRS());
if (_callback.valid())
_TRITON->setCallback(_callback.get());
TritonDrawable* drawable = new TritonDrawable(_TRITON.get());
_drawable = drawable;
_drawable->setNodeMask(TRITON_OCEAN_MASK);
drawable->setMaskLayer(_maskLayer.getLayer());
this->addChild(_drawable);
// Place in the depth-sorted bin and set a rendering order.
// We want Triton to render after the terrain.
_drawable->getOrCreateStateSet()->setRenderBinDetails(
_tritonLayer->getRenderBinNumber(),
"DepthSortedBin");
// Install a vdatum for sea level calculations:
auto vdatum = VerticalDatum::get(_tritonLayer->options().vdatum().value());
if (vdatum)
drawable->setVerticalDatum(vdatum);
// If the user requested a height map, install it now.
// Configuration of the height map generator will take place later when
// we have a valid graphics context.
if (_tritonLayer->getUseHeightMap() == true)
{
TritonHeightMap* heightMapGen = new TritonHeightMap();
heightMapGen->setTerrain(mapNode->getTerrainEngine()->getNode());
if (_maskLayer.getLayer())
heightMapGen->setMaskLayer(_maskLayer.getLayer());
this->addChild(heightMapGen);
drawable->setHeightMapGenerator(heightMapGen);
}
}
void traverse(osg::NodeVisitor& nv)
{
if (nv.getVisitorType() == nv.UPDATE_VISITOR)
{
// Find a MapNode in the traversal path if necessary:
if (_needsMapNode)
{
osgEarth::MapNode* mapNode = osgEarth::findInNodePath<osgEarth::MapNode>(nv);
if (mapNode)
{
setMapNode(mapNode);
_needsMapNode = false;
ADJUST_UPDATE_TRAV_COUNT(this, -1);
}
}
}
else if (nv.getVisitorType() == nv.CULL_VISITOR && _drawable && _TRITON.valid() && _TRITON->getOcean())
{
// Update any intersections.
// For now this is running in the CULL traversal, which is not ideal.
// However the Triton Ocean::GetHeight method requires a pointer to the Triton "camera"
// and under our framework this is only available in CULL or DRAW.
// Running the intersection in eithe CULL or DRAW will result in a frame
// incoherency w.r.t the Triton update() call that updates the ocean state.
::Triton::Ocean* ocean = _TRITON->getOcean();
// Find the TritonCam associated with this osg Cam
osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(&nv);
::Triton::Camera* tritonCam = static_cast<TritonDrawable*>(_drawable)->getTritonCam(cv->getCurrentCamera());
osg::Vec3d eye = osg::Vec3d(0,0,0) * cv->getCurrentCamera()->getInverseViewMatrix();
for(std::vector<osg::ref_ptr<TritonIntersections> >::iterator i = _isect.begin();
i != _isect.end();
++i)
{
TritonIntersections* ir = i->get();
// allocate enough space for the output:
ir->_input.resize(ir->_input.size());
ir->_normals.resize(ir->_input.size());
osg::Matrix local2world;
ir->_anchor.createLocalToWorld(local2world);
// Make sure it's in range so as not to waste cycles:
osg::Vec3d anchor = osg::Vec3d(0,0,0) * local2world;
double m = ir->getMaxRange().as(Units::METERS);
if ((eye-anchor).length2() > (m))
{
continue;
}
osg::Matrix world2local;
world2local.invert(local2world);
for(unsigned i=0; i<ir->_input.size(); ++i)
{
const osg::Vec3d& local = ir->_input[i];
// transform the ray to world coordinates
osg::Vec3d start = local * local2world;
osg::Vec3d dir = osg::Matrix::transform3x3(local2world, osg::Vec3d(0,0,1));
// intersect the ocean
float& out_height = ir->_heights[i];
::Triton::Vector3 out_normalT;
bool ok = ocean->GetHeight(
::Triton::Vector3(start.x(), start.y(), start.z()),
::Triton::Vector3(dir.x(), dir.y(), dir.z()),
out_height,
out_normalT,
true, // visualCorrelation
true, // includeWakes
true, // highResolution
true, // threadSafe,
0L, // intersectionPoint,
true, // autoFlip
tritonCam);
if (ok)
{
// populate the output data in local coordinates
osg::Vec3d& normal = ir->_normals[i];
normal.set(out_normalT.x, out_normalT.y, out_normalT.z);
normal = osg::Matrix::transform3x3(normal, world2local);
}
else
{
// todo...what?
OE_WARN << "GetHeight returned false dude" << std::endl;
}
}
}
}
osg::Group::traverse(nv);
}
osg::ref_ptr<TritonContext> _TRITON;
osg::Drawable* _drawable;
LayerReference<osgEarth::ImageLayer>& _maskLayer;
osg::observer_ptr<osgEarth::MapNode> _mapNode;
osg::observer_ptr<osgEarth::Triton::TritonLayer> _tritonLayer;
osg::ref_ptr<Callback> _callback;
bool _needsMapNode;
std::vector<osg::ref_ptr<TritonIntersections> > _isect;
};
} }
//........................................................................
void
TritonLayer::Options::fromConfig(const osgEarth::Config& conf)
{
conf.get("user", _user);
conf.get("license_code", _licenseCode);
conf.get("resource_path", _resourcePath);
conf.get("use_height_map", _useHeightMap);
conf.get("height_map_size", _heightMapSize);
conf.get("render_bin_number", _renderBinNumber);
conf.get("max_altitude", _maxAltitude);
conf.get("vdatum", vdatum());
maskLayer().get(conf, "mask_layer");
}
osgEarth::Config
TritonLayer::Options::getConfig() const
{
osgEarth::Config conf = osgEarth::VisibleLayer::Options::getConfig();
conf.set("user", _user);
conf.set("license_code", _licenseCode);
conf.set("resource_path", _resourcePath);
conf.set("use_height_map", _useHeightMap);
conf.set("height_map_size", _heightMapSize);
conf.set("render_bin_number", _renderBinNumber);
conf.set("max_altitude", _maxAltitude);
conf.set("vdatum", vdatum());
maskLayer().set(conf, "mask_layer");
return conf;
}
//........................................................................
/** Register this layer so it can be used in an earth file */
namespace osgEarth { namespace Triton
{
REGISTER_OSGEARTH_LAYER(triton, TritonLayer);
REGISTER_OSGEARTH_LAYER(triton_ocean, TritonLayer);
} }
OE_LAYER_PROPERTY_IMPL(TritonLayer, std::string, UserName, user);
OE_LAYER_PROPERTY_IMPL(TritonLayer, std::string, LicenseCode, licenseCode);
OE_LAYER_PROPERTY_IMPL(TritonLayer, std::string, ResourcePath, resourcePath);
OE_LAYER_PROPERTY_IMPL(TritonLayer, bool, UseHeightMap, useHeightMap);
OE_LAYER_PROPERTY_IMPL(TritonLayer, unsigned, HeightMapSize, heightMapSize);
OE_LAYER_PROPERTY_IMPL(TritonLayer, int, RenderBinNumber, renderBinNumber);
OE_LAYER_PROPERTY_IMPL(TritonLayer, float, MaxAltitude, maxAltitude);
OE_LAYER_PROPERTY_IMPL(TritonLayer, std::string, VerticalDatum, vdatum);
void
TritonLayer::init()
{
super::init();
_seaLevel = 0.0f;
// Trick to force the VisibleLayer to install its opacity shader,
// which a modified Triton user-functions.glsl shader needs in order to control
// sea surface opacity.
float opacity = getOpacity();
setOpacity(0.0f);
setOpacity(opacity);
this->setName("Triton");
setRenderType(RENDERTYPE_CUSTOM);
ElevationLOD* lod = new ElevationLOD();
_root = lod;
if (options().maxAltitude().isSet())
{
OE_DEBUG << LC << "Setting max altitude = " << options().maxAltitude().get() << std::endl;
lod->setMaxElevation(options().maxAltitude().get());
}
_tritonNode = new TritonLayerNode(this, options().maskLayer());
_root->addChild(_tritonNode.get());
}
void
TritonLayer::setUserCallback(Callback* callback)
{
static_cast<TritonLayerNode*>(_tritonNode.get())->setUserCallback(callback);
}
osg::Node*
TritonLayer::getNode() const
{
return _root.get();
}
void
TritonLayer::setMaskLayer(osgEarth::ImageLayer* maskLayer)
{
options().maskLayer().setLayer(maskLayer);
static_cast<TritonLayerNode*>(_tritonNode.get())->dirty();
}
osgEarth::ImageLayer*
TritonLayer::getMaskLayer() const
{
return options().maskLayer().getLayer();
}
void
TritonLayer::addedToMap(const osgEarth::Map* map)
{
VisibleLayer::addedToMap(map);
options().maskLayer().addedToMap(map);
}
void
TritonLayer::removedFromMap(const osgEarth::Map* map)
{
VisibleLayer::removedFromMap(map);
options().maskLayer().removedFromMap(map);
setMaskLayer(0L);
}
void
TritonLayer::addIntersections(TritonIntersections* value)
{
TritonLayerNode* node = static_cast<TritonLayerNode*>(_tritonNode.get());
node->_isect.push_back(value);
}
osgEarth::Config
TritonLayer::getConfig() const
{
osgEarth::Config c = osgEarth::VisibleLayer::getConfig();
return c;
}

View File

@ -1,125 +0,0 @@
/* -*-c++-*- */
/* osgEarth - Geospatial SDK for OpenSceneGraph
* Copyright 2020 Pelican Mapping
* http://osgearth.org
*
* osgEarth is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#ifndef OSGEARTH_TRITON_LAYER
#define OSGEARTH_TRITON_LAYER 1
#include <osgEarth/VisibleLayer>
#include <osgEarth/LayerReference>
#include <osgEarth/ImageLayer>
#include "TritonCallback.h"
#include "TritonIntersections.h"
namespace osgEarth { namespace Triton
{
/**
* Node that roots the Triton adapter.
*/
class TritonLayer : public osgEarth::VisibleLayer
{
public:
class Options : public osgEarth::VisibleLayer::Options {
public:
META_LayerOptions(osgEarth, Options, osgEarth::VisibleLayer::Options);
OE_OPTION(std::string, user);
OE_OPTION(std::string, licenseCode);
OE_OPTION(std::string, resourcePath);
OE_OPTION(bool, useHeightMap, true);
OE_OPTION(unsigned, heightMapSize, 1024);
OE_OPTION(int, renderBinNumber, 12);
OE_OPTION(float, maxAltitude, 50000.0f);
OE_OPTION(std::string, vdatum, "egm96");
OE_OPTION_LAYER(osgEarth::ImageLayer, maskLayer);
virtual Config getConfig() const;
private:
void fromConfig(const Config& conf);
};
public:
META_Layer(osgEarth, TritonLayer, Options, osgEarth::VisibleLayer, triton);
//! Sets the user callback that's invoked when Triton start up
void setUserCallback(Triton::Callback* callback);
//! User name for license
void setUserName(const std::string& value);
const std::string& getUserName() const;
//! License code
void setLicenseCode(const std::string& value);
const std::string& getLicenseCode() const;
//! Triton resource path
void setResourcePath(const std::string& value);
const std::string& getResourcePath() const;
//! Whether to use a height map to fade out the ocean at the coastline
void setUseHeightMap(const bool& value);
const bool& getUseHeightMap() const;
//! Size in texels of the height map (each dimension)
void setHeightMapSize(const unsigned& value);
const unsigned& getHeightMapSize() const;
//! Render bin number to use for the ocean rendering
void setRenderBinNumber(const int& value);
const int& getRenderBinNumber() const;
//! Masking layer for the ocean
void setMaskLayer(osgEarth::ImageLayer* maskLayer);
osgEarth::ImageLayer* getMaskLayer() const;
//! Maximum visibility altitude
void setMaxAltitude(const float& value);
const float& getMaxAltitude() const;
//! Vertical datum to use to calculate sea level
void setVerticalDatum(const std::string& value);
const std::string& getVerticalDatum() const;
//! Adds an intersection set.
//! Each frame, Triton will perform intersections against the ocean surface
//! (including the waves) and populate the set with the results.
void addIntersections(TritonIntersections*);
public: // Layer
virtual osg::Node* getNode() const;
//! Serialize
virtual Config getConfig() const;
protected: // Layer
virtual void init();
virtual void addedToMap(const class osgEarth::Map*);
virtual void removedFromMap(const class osgEarth::Map*);
private:
osg::ref_ptr<osg::Group> _root;
osg::ref_ptr<osg::Node> _tritonNode;
float _seaLevel;
float _opacity;
};
} } // namespace osgEarth::Triton
#endif // OSGEARTH_TRITON_LAYER

View File

@ -489,143 +489,143 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/MainWindow.cpp" line="114"/> <location filename="../ui/MainWindow.cpp" line="115"/>
<source>Wave Curve</source> <source>Wave Curve</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/MainWindow.cpp" line="122"/> <location filename="../ui/MainWindow.cpp" line="123"/>
<source>Speed Curve</source> <source>Speed Curve</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/MainWindow.cpp" line="131"/> <location filename="../ui/MainWindow.cpp" line="132"/>
<source>3D Curve</source> <source>3D Curve</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/MainWindow.cpp" line="143"/> <location filename="../ui/MainWindow.cpp" line="144"/>
<location filename="../ui/MainWindow.cpp" line="168"/> <location filename="../ui/MainWindow.cpp" line="169"/>
<source>Target number</source> <source>Target number</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/MainWindow.cpp" line="143"/> <location filename="../ui/MainWindow.cpp" line="144"/>
<location filename="../ui/MainWindow.cpp" line="168"/> <location filename="../ui/MainWindow.cpp" line="169"/>
<source>Signal-to-noise ratio</source> <source>Signal-to-noise ratio</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/MainWindow.cpp" line="144"/> <location filename="../ui/MainWindow.cpp" line="145"/>
<location filename="../ui/MainWindow.cpp" line="169"/> <location filename="../ui/MainWindow.cpp" line="170"/>
<source>Azimuth line of sight</source> <source>Azimuth line of sight</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/MainWindow.cpp" line="144"/> <location filename="../ui/MainWindow.cpp" line="145"/>
<location filename="../ui/MainWindow.cpp" line="169"/> <location filename="../ui/MainWindow.cpp" line="170"/>
<source>Pitch gaze angle</source> <source>Pitch gaze angle</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/MainWindow.cpp" line="145"/> <location filename="../ui/MainWindow.cpp" line="146"/>
<location filename="../ui/MainWindow.cpp" line="170"/> <location filename="../ui/MainWindow.cpp" line="171"/>
<source>azimuth</source> <source>azimuth</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/MainWindow.cpp" line="145"/> <location filename="../ui/MainWindow.cpp" line="146"/>
<location filename="../ui/MainWindow.cpp" line="170"/> <location filename="../ui/MainWindow.cpp" line="171"/>
<source>Pitch angle</source> <source>Pitch angle</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/MainWindow.cpp" line="146"/> <location filename="../ui/MainWindow.cpp" line="147"/>
<location filename="../ui/MainWindow.cpp" line="171"/> <location filename="../ui/MainWindow.cpp" line="172"/>
<source>attribute</source> <source>attribute</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/MainWindow.cpp" line="146"/> <location filename="../ui/MainWindow.cpp" line="147"/>
<location filename="../ui/MainWindow.cpp" line="171"/> <location filename="../ui/MainWindow.cpp" line="172"/>
<source>Doppler</source> <source>Doppler</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/MainWindow.cpp" line="147"/> <location filename="../ui/MainWindow.cpp" line="148"/>
<location filename="../ui/MainWindow.cpp" line="172"/> <location filename="../ui/MainWindow.cpp" line="173"/>
<source>course</source> <source>course</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/MainWindow.cpp" line="147"/> <location filename="../ui/MainWindow.cpp" line="148"/>
<location filename="../ui/MainWindow.cpp" line="172"/> <location filename="../ui/MainWindow.cpp" line="173"/>
<source>Speed</source> <source>Speed</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/MainWindow.cpp" line="148"/> <location filename="../ui/MainWindow.cpp" line="149"/>
<location filename="../ui/MainWindow.cpp" line="173"/> <location filename="../ui/MainWindow.cpp" line="174"/>
<source>longitude</source> <source>longitude</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/MainWindow.cpp" line="148"/> <location filename="../ui/MainWindow.cpp" line="149"/>
<location filename="../ui/MainWindow.cpp" line="173"/> <location filename="../ui/MainWindow.cpp" line="174"/>
<source>latitude</source> <source>latitude</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/MainWindow.cpp" line="149"/> <location filename="../ui/MainWindow.cpp" line="150"/>
<location filename="../ui/MainWindow.cpp" line="174"/> <location filename="../ui/MainWindow.cpp" line="175"/>
<source>distance</source> <source>distance</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/MainWindow.cpp" line="149"/> <location filename="../ui/MainWindow.cpp" line="150"/>
<location filename="../ui/MainWindow.cpp" line="174"/> <location filename="../ui/MainWindow.cpp" line="175"/>
<source>velocity</source> <source>velocity</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/MainWindow.cpp" line="150"/> <location filename="../ui/MainWindow.cpp" line="151"/>
<location filename="../ui/MainWindow.cpp" line="175"/> <location filename="../ui/MainWindow.cpp" line="176"/>
<source>Radial dimensions</source> <source>Radial dimensions</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/MainWindow.cpp" line="150"/> <location filename="../ui/MainWindow.cpp" line="151"/>
<location filename="../ui/MainWindow.cpp" line="175"/> <location filename="../ui/MainWindow.cpp" line="176"/>
<source>Target RCS</source> <source>Target RCS</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/MainWindow.cpp" line="156"/> <location filename="../ui/MainWindow.cpp" line="157"/>
<source>Report Table</source> <source>Report Table</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/MainWindow.cpp" line="181"/> <location filename="../ui/MainWindow.cpp" line="182"/>
<source>Report</source> <source>Report</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/MainWindow.cpp" line="190"/> <location filename="../ui/MainWindow.cpp" line="191"/>
<source>Signal Indicator Lamp</source> <source>Signal Indicator Lamp</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/MainWindow.cpp" line="197"/> <location filename="../ui/MainWindow.cpp" line="198"/>
<source>ParamSetting</source> <source>ParamSetting</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/MainWindow.cpp" line="202"/> <location filename="../ui/MainWindow.cpp" line="203"/>
<source>Matlab File</source> <source>Matlab File</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../ui/MainWindow.cpp" line="207"/> <location filename="../ui/MainWindow.cpp" line="208"/>
<source>name: 5year 0412</source> <source>name: 5year 0412</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -840,12 +840,12 @@
<context> <context>
<name>QObject</name> <name>QObject</name>
<message> <message>
<location filename="../common/CrashHandler.cpp" line="69"/> <location filename="../common/CrashHandler.cpp" line="71"/>
<source>error</source> <source>error</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../common/CrashHandler.cpp" line="70"/> <location filename="../common/CrashHandler.cpp" line="72"/>
<source>the appliaction is crash</source> <source>the appliaction is crash</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -1254,18 +1254,12 @@
<context> <context>
<name>QtOsgViewWidget</name> <name>QtOsgViewWidget</name>
<message> <message>
<location filename="../viewer/QtOsgViewWidget.cpp" line="369"/> <location filename="../viewer/QtOsgViewWidget.cpp" line="273"/>
<location filename="../viewer/QtOsgViewWidget.cpp" line="377"/>
<source>warning</source> <source>warning</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../viewer/QtOsgViewWidget.cpp" line="369"/> <location filename="../viewer/QtOsgViewWidget.cpp" line="273"/>
<source>default workspace failed</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../viewer/QtOsgViewWidget.cpp" line="377"/>
<source>open dyt file failed</source> <source>open dyt file failed</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -1838,17 +1832,17 @@
<context> <context>
<name>osgQOpenGLWidget</name> <name>osgQOpenGLWidget</name>
<message> <message>
<location filename="../viewer/osgQOpenGLWidget.cpp" line="104"/> <location filename="../viewer/osgQOpenGLWidget.cpp" line="106"/>
<source>Screen %1</source> <source>Screen %1</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../viewer/osgQOpenGLWidget.cpp" line="114"/> <location filename="../viewer/osgQOpenGLWidget.cpp" line="116"/>
<source>Choose fullscreen target screen</source> <source>Choose fullscreen target screen</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../viewer/osgQOpenGLWidget.cpp" line="114"/> <location filename="../viewer/osgQOpenGLWidget.cpp" line="116"/>
<source>Screen</source> <source>Screen</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>

View File

@ -113,9 +113,9 @@ void MainFrame::InitUI() {
MainWindow* mainWindow = new MainWindow(this); MainWindow* mainWindow = new MainWindow(this);
layout->addWidget(mainWindow); layout->addWidget(mainWindow);
QtOsgViewWidget* viewWidget = mainWindow->GetViewWidget(); /* QtOsgViewWidget* viewWidget = mainWindow->GetViewWidget();
connect(fileMenu, &FileManagerMenu::LoadDyt, viewWidget, &QtOsgViewWidget::OnLoadDyt); connect(fileMenu, &FileManagerMenu::LoadDyt, viewWidget, &QtOsgViewWidget::OnLoadDyt);
connect(viewWidget, &QtOsgViewWidget::signalResetWorkSpace, mainWindow, &MainWindow::slotResetWorkSpace); connect(viewWidget, &QtOsgViewWidget::signalResetWorkSpace, mainWindow, &MainWindow::slotResetWorkSpace);*/
connect(system_, &SystemManagerMenu::signalShowUISetting, mainWindow, &MainWindow::slotShowUISetting); connect(system_, &SystemManagerMenu::signalShowUISetting, mainWindow, &MainWindow::slotShowUISetting);

View File

@ -13,7 +13,8 @@
#include "ModelBrowser.h" #include "ModelBrowser.h"
#include "DockWidget.h" #include "DockWidget.h"
#include "viewer/QtOsgViewWidget.h" #include "viewer/ViewWidget.h"
#include "viewer/OsgOpenGLWindow.h"
#include "viewer/OsgViewer.h" #include "viewer/OsgViewer.h"
#include "chartPlot/FitCurveDialog.h" #include "chartPlot/FitCurveDialog.h"
@ -44,7 +45,6 @@ MainWindow::MainWindow(QWidget* parent)
} }
MainWindow::~MainWindow() { MainWindow::~MainWindow() {
OsgViewer::Get().Uninitialize();
delete ui; delete ui;
} }
@ -83,8 +83,9 @@ void MainWindow::InitUI() {
connect(modelBrowser_, &ModelBrowser::WorkSpaceChange, propertyBrowser_, &PropertyBrowser::OnWorkSpaceChange); connect(modelBrowser_, &ModelBrowser::WorkSpaceChange, propertyBrowser_, &PropertyBrowser::OnWorkSpaceChange);
connect(modelBrowser_, &ModelBrowser::EntityChange, propertyBrowser_, &PropertyBrowser::OnEntityChange); connect(modelBrowser_, &ModelBrowser::EntityChange, propertyBrowser_, &PropertyBrowser::OnEntityChange);
qtOsgViewWidget_ = new QtOsgViewWidget; qtOsgViewWidget_ = new ViewWidget;
qtOsgViewWidget_->Initialize(); //qtOsgViewWidget_ = new OsgOpenGLWindow;
//qtOsgViewWidget_->Initialize();
m_mapDockWidget.insert("PropertyBrowser", attribte); m_mapDockWidget.insert("PropertyBrowser", attribte);
QString wavePath ="", speedPath = "", rdPath = "", matlabParam=""; QString wavePath ="", speedPath = "", rdPath = "", matlabParam="";
@ -210,9 +211,8 @@ void MainWindow::InitUI() {
InitDockLayout(); InitDockLayout();
//ui->viewWidget->layout()->addWidget(qtOsgViewWidget_); //ui->viewWidget->layout()->addWidget(qtOsgViewWidget_);
qtOsgViewWidget_->LoadDefaultScene(); //qtOsgViewWidget_->LoadDefaultScene();
OsgViewer::Get().Initialize();
OsgViewer::Get().OnFrame();
#if 0 #if 0
MatlabObject* mtlb = new MatlabObject; MatlabObject* mtlb = new MatlabObject;
@ -237,8 +237,9 @@ void MainWindow::InitDockLayout() {
tabWidget_->insertTab(i, mainWindow_, strTabName); tabWidget_->insertTab(i, mainWindow_, strTabName);
if (listDocArea[0].toList().size() > 0) { if (listDocArea[0].toList().size() > 0) {
mainWindow_->setCentralWidget(qtOsgViewWidget_); mainWindow_->setCentralWidget(qtOsgViewWidget_);
OsgViewer::Get().Initialize(); //mainWindow_->setCentralWidget(qtOsgViewWidget_->AsWidget());
OsgViewer::Get().OnFrame(); //OsgViewer::Get().Initialize();
//OsgViewer::Get().OnFrame();
} else { } else {
mainWindow_->takeCentralWidget(); mainWindow_->takeCentralWidget();
} }

View File

@ -21,9 +21,9 @@ public:
class ModelBrowser* GetModelBrowser() const { class ModelBrowser* GetModelBrowser() const {
return modelBrowser_; return modelBrowser_;
} }
class QtOsgViewWidget* GetViewWidget() const { /*class ViewWidget* GetViewWidget() const {
return qtOsgViewWidget_; return qtOsgViewWidget_;
} }*/
class FitCurveDialog* GetFitCurveDlg() const { class FitCurveDialog* GetFitCurveDlg() const {
return fitCurveDlg_; return fitCurveDlg_;
@ -55,7 +55,8 @@ private:
class ModelBrowser* modelBrowser_{ nullptr }; class ModelBrowser* modelBrowser_{ nullptr };
class PropertyBrowser* propertyBrowser_{ nullptr }; class PropertyBrowser* propertyBrowser_{ nullptr };
class QWebEngineView* webEngineView_{ nullptr }; class QWebEngineView* webEngineView_{ nullptr };
class QtOsgViewWidget* qtOsgViewWidget_{ nullptr }; class ViewWidget* qtOsgViewWidget_{ nullptr };
//class OsgOpenGLWindow* qtOsgViewWidget_{ nullptr };
class FitCurveDialog* fitCurveDlg_{ nullptr }; class FitCurveDialog* fitCurveDlg_{ nullptr };
class FitCurveDialog* fitYLgCurveDlg_{ nullptr }; class FitCurveDialog* fitYLgCurveDlg_{ nullptr };

View File

@ -5,7 +5,7 @@
#include <QVariant> #include <QVariant>
#include <QMenu> #include <QMenu>
#include <osgEarth/EarthManipulator> #include <osgEarthUtil/EarthManipulator>
#include "common/RecourceHelper.h" #include "common/RecourceHelper.h"
#include "common/SpdLogger.h" #include "common/SpdLogger.h"

View File

@ -68,9 +68,9 @@ std::string StringUtils::ViewpointToString(const osgEarth::Viewpoint& value) {
double latitude = location->y(); double latitude = location->y();
double altitude = location->z(); double altitude = location->z();
double heading = value.heading().get(); double heading = value.heading().get().getValue();
double pitch = value.pitch().get(); double pitch = value.pitch().get().getValue();
double range = value.range().get(); double range = value.range().get().getValue();
std::stringstream ss; std::stringstream ss;
ss << std::fixed << std::setprecision(6); ss << std::fixed << std::setprecision(6);

View File

@ -1,40 +1,377 @@
#include "viewer/GraphicsWindowEx.h" #include "viewer/GraphicsWindowEx.h"
#include <QOpenGLFrameBufferObjectFormat>
#include <QOpenGLFunctions>
#include <QThread>
#include <QKeyEvent>
#include <QMouseEvent>
#include <QWheelEvent>
#include "viewer/StateEx.h" #include "viewer/StateEx.h"
#include "config.h"
#include "common/SpdLogger.h"
//
//GraphicsWindowEx::GraphicsWindowEx(osg::GraphicsContext::Traits* traits)
// : osgViewer::GraphicsWindowEmbedded(traits) {
// _traits = traits;
//
// init();
//}
namespace {
class QtKeyboardMap {
public:
QtKeyboardMap() {
mKeyMap[Qt::Key_Escape] = osgGA::GUIEventAdapter::KEY_Escape;
mKeyMap[Qt::Key_Delete] = osgGA::GUIEventAdapter::KEY_Delete;
mKeyMap[Qt::Key_Home] = osgGA::GUIEventAdapter::KEY_Home;
mKeyMap[Qt::Key_Enter] = osgGA::GUIEventAdapter::KEY_KP_Enter;
mKeyMap[Qt::Key_End] = osgGA::GUIEventAdapter::KEY_End;
mKeyMap[Qt::Key_Return] = osgGA::GUIEventAdapter::KEY_Return;
mKeyMap[Qt::Key_PageUp] = osgGA::GUIEventAdapter::KEY_Page_Up;
mKeyMap[Qt::Key_PageDown] = osgGA::GUIEventAdapter::KEY_Page_Down;
mKeyMap[Qt::Key_Left] = osgGA::GUIEventAdapter::KEY_Left;
mKeyMap[Qt::Key_Right] = osgGA::GUIEventAdapter::KEY_Right;
mKeyMap[Qt::Key_Up] = osgGA::GUIEventAdapter::KEY_Up;
mKeyMap[Qt::Key_Down] = osgGA::GUIEventAdapter::KEY_Down;
mKeyMap[Qt::Key_Backspace] = osgGA::GUIEventAdapter::KEY_BackSpace;
mKeyMap[Qt::Key_Tab] = osgGA::GUIEventAdapter::KEY_Tab;
mKeyMap[Qt::Key_Space] = osgGA::GUIEventAdapter::KEY_Space;
mKeyMap[Qt::Key_Delete] = osgGA::GUIEventAdapter::KEY_Delete;
mKeyMap[Qt::Key_Alt] = osgGA::GUIEventAdapter::KEY_Alt_L;
mKeyMap[Qt::Key_Shift] = osgGA::GUIEventAdapter::KEY_Shift_L;
mKeyMap[Qt::Key_Control] = osgGA::GUIEventAdapter::KEY_Control_L;
mKeyMap[Qt::Key_Meta] = osgGA::GUIEventAdapter::KEY_Meta_L;
mKeyMap[Qt::Key_F1] = osgGA::GUIEventAdapter::KEY_F1;
mKeyMap[Qt::Key_F2] = osgGA::GUIEventAdapter::KEY_F2;
mKeyMap[Qt::Key_F3] = osgGA::GUIEventAdapter::KEY_F3;
mKeyMap[Qt::Key_F4] = osgGA::GUIEventAdapter::KEY_F4;
mKeyMap[Qt::Key_F5] = osgGA::GUIEventAdapter::KEY_F5;
mKeyMap[Qt::Key_F6] = osgGA::GUIEventAdapter::KEY_F6;
mKeyMap[Qt::Key_F7] = osgGA::GUIEventAdapter::KEY_F7;
mKeyMap[Qt::Key_F8] = osgGA::GUIEventAdapter::KEY_F8;
mKeyMap[Qt::Key_F9] = osgGA::GUIEventAdapter::KEY_F9;
mKeyMap[Qt::Key_F10] = osgGA::GUIEventAdapter::KEY_F10;
mKeyMap[Qt::Key_F11] = osgGA::GUIEventAdapter::KEY_F11;
mKeyMap[Qt::Key_F12] = osgGA::GUIEventAdapter::KEY_F12;
mKeyMap[Qt::Key_F13] = osgGA::GUIEventAdapter::KEY_F13;
mKeyMap[Qt::Key_F14] = osgGA::GUIEventAdapter::KEY_F14;
mKeyMap[Qt::Key_F15] = osgGA::GUIEventAdapter::KEY_F15;
mKeyMap[Qt::Key_F16] = osgGA::GUIEventAdapter::KEY_F16;
mKeyMap[Qt::Key_F17] = osgGA::GUIEventAdapter::KEY_F17;
mKeyMap[Qt::Key_F18] = osgGA::GUIEventAdapter::KEY_F18;
mKeyMap[Qt::Key_F19] = osgGA::GUIEventAdapter::KEY_F19;
mKeyMap[Qt::Key_F20] = osgGA::GUIEventAdapter::KEY_F20;
mKeyMap[Qt::Key_hyphen] = '-';
mKeyMap[Qt::Key_Equal] = '=';
mKeyMap[Qt::Key_division] = osgGA::GUIEventAdapter::KEY_KP_Divide;
mKeyMap[Qt::Key_multiply] = osgGA::GUIEventAdapter::KEY_KP_Multiply;
mKeyMap[Qt::Key_Minus] = '-';
mKeyMap[Qt::Key_Plus] = '+';
mKeyMap[Qt::Key_Insert] = osgGA::GUIEventAdapter::KEY_KP_Insert;
}
~QtKeyboardMap() {}
int remapKey(QKeyEvent* event) {
KeyMap::iterator itr = mKeyMap.find(event->key());
if (itr == mKeyMap.end()) {
return int(*(event->text().toLatin1().data()));
} else
return itr->second;
}
private:
typedef std::map<unsigned int, int> KeyMap;
KeyMap mKeyMap;
};
static QtKeyboardMap s_QtKeyboardMap;
static void setKeyboardModifiers(osgGA::EventQueue* eventQueue, QInputEvent* event) {
unsigned int modkey = event->modifiers() & (Qt::ShiftModifier |
Qt::ControlModifier |
Qt::AltModifier);
unsigned int mask = 0;
if (modkey & Qt::ShiftModifier) mask |= osgGA::GUIEventAdapter::MODKEY_SHIFT;
if (modkey & Qt::ControlModifier) mask |= osgGA::GUIEventAdapter::MODKEY_CTRL;
if (modkey & Qt::AltModifier) mask |= osgGA::GUIEventAdapter::MODKEY_ALT;
eventQueue->getCurrentEventState()->setModKeyMask(mask);
}
} // namespace
GraphicsWindowEx::GraphicsWindowEx(osg::GraphicsContext::Traits* traits) GraphicsWindowEx::GraphicsWindowEx(osg::GraphicsContext::Traits* traits)
{ : osgViewer::GraphicsWindowEmbedded(traits) {
_traits = traits; LOG_INFO("actor, self={}", spdlog::fmt_lib::ptr(this));
init();
} }
GraphicsWindowEx::GraphicsWindowEx(int x, int y, int width, int height) GraphicsWindowEx::GraphicsWindowEx(int x, int y, int width, int height)
{ : osgViewer::GraphicsWindowEmbedded(x, y, width == 0 ? 1 : width, height == 0 ? 1 : height) {
_traits = new osg::GraphicsContext::Traits(); LOG_INFO("actor, self={}", spdlog::fmt_lib::ptr(this));
_traits->x = x;
_traits->x = y;
_traits->width = width;
_traits->height = height;
init();
} }
void GraphicsWindowEx::init() GraphicsWindowEx::~GraphicsWindowEx() {
{ LOG_INFO("dctor isSharedContextSet_:{}, self={}", isSharedContextSet_, spdlog::fmt_lib::ptr(this));
if(valid())
{
// inject our "extended" state
setState(new StateEx());
getState()->setGraphicsContext(this);
if(_traits.valid() && _traits->sharedContext.valid()) }
{
getState()->setContextID(_traits->sharedContext->getState()->getContextID()); bool GraphicsWindowEx::realizeImplementation() {
incrementContextIDUsageCount(getState()->getContextID()); //LOG_INFO("realizeImplementation, isRealized_:{}, self={}", isRealized_, spdlog::fmt_lib::ptr(this));
} //if (isRealized_) {
else // return true;
{ //}
getState()->setContextID(osg::GraphicsContext::createNewContextID());
} //dyt_check(nullptr != _state);
//_state->resetVertexAttributeAlias(false);
//_state->setModeValidity(GL_LIGHTING, false);
//_state->setModeValidity(GL_NORMALIZE, false);
//_state->setModeValidity(GL_RESCALE_NORMAL, false);
//_state->setModeValidity(GL_LINE_STIPPLE, false);
//_state->setModeValidity(GL_LINE_SMOOTH, false);
//isRealized_ = true;
return true;
}
bool GraphicsWindowEx::makeCurrentImplementation() {
//LOG_INFO("makeCurrentImplementation, isRealized_:{}, self={}", isRealized_, spdlog::fmt_lib::ptr(this));
//
//if (nullptr != offScreenContext_) {
// offScreenContext_->makeCurrent(offScreenSurface_.get());
//}
//InitFrameBuffer();
//setDefaultFboId(renderFramebuffer_->handle());
//renderFramebuffer_->bind();
//
return true;
}
void GraphicsWindowEx::closeImplementation() {
//if (!isSharedContextSet_) {
// return;
//}
//if (isFrameBufferInitialized_) {
// offScreenContext_->makeCurrent(offScreenSurface_.get());
// renderFramebuffer_.reset();
// sharedFrameBuffer_.reset();
// offScreenContext_->doneCurrent();
//}
//offScreenContext_.reset();
//offScreenSurface_.reset();
}
bool GraphicsWindowEx::releaseContextImplementation() {
//LOG_INFO("releaseContextImplementation, self={}", spdlog::fmt_lib::ptr(this));
//QOpenGLFramebufferObject::bindDefault();
//offScreenContext_->doneCurrent();
return true;
}
void GraphicsWindowEx::swapBuffersImplementation() {
//offScreenContext_->functions()->glFinish();
//frameBufferId_ = renderFramebuffer_->texture();
//if (!isRenderDonwn_) {
// return;
//}
//qSwap(renderFramebuffer_, sharedFrameBuffer_);
//isRenderDonwn_ = false;
}
bool GraphicsWindowEx::SetSharedContext(QOpenGLContext* sharedContext) {
sharedContext_ = sharedContext;
InitOffScreenContext();
return true;
}
void GraphicsWindowEx::ReizeWindow(int width, int height) {
if (width == _traits->width && height == _traits->height) {
return;
}
getEventQueue()->windowResize(0, 0, width, height);
resized(0, 0, width, height);
isFrameBufferInitialized_ = false;
}
void GraphicsWindowEx::keyPressEvent(QKeyEvent* event) {
setKeyboardModifiers(getEventQueue(), event);
int value = s_QtKeyboardMap.remapKey(event);
getEventQueue()->keyPress(value);
}
void GraphicsWindowEx::keyReleaseEvent(QKeyEvent* event) {
if (event->isAutoRepeat()) {
event->ignore();
} else {
setKeyboardModifiers(getEventQueue(), event);
int value = s_QtKeyboardMap.remapKey(event);
getEventQueue()->keyPress(value);
} }
} }
void GraphicsWindowEx::mousePressEvent(QMouseEvent* event) {
int button = 0;
switch (event->button()) {
case Qt::LeftButton:
button = 1;
break;
case Qt::MidButton:
button = 2;
break;
case Qt::RightButton:
button = 3;
break;
case Qt::NoButton:
button = 0;
break;
default:
button = 0;
break;
}
setKeyboardModifiers(getEventQueue(), event);
getEventQueue()->mouseButtonPress(event->x() * windowScale_,
event->y() * windowScale_, button);
}
void GraphicsWindowEx::mouseReleaseEvent(QMouseEvent* event) {
int button = 0;
switch (event->button()) {
case Qt::LeftButton:
button = 1;
break;
case Qt::MidButton:
button = 2;
break;
case Qt::RightButton:
button = 3;
break;
case Qt::NoButton:
button = 0;
break;
default:
button = 0;
break;
}
setKeyboardModifiers(getEventQueue(), event);
getEventQueue()->mouseButtonRelease(event->x() * windowScale_,
event->y() * windowScale_, button);
}
void GraphicsWindowEx::mouseDoubleClickEvent(QMouseEvent* event) {
int button = 0;
switch (event->button()) {
case Qt::LeftButton:
button = 1;
break;
case Qt::MidButton:
button = 2;
break;
case Qt::RightButton:
button = 3;
break;
case Qt::NoButton:
button = 0;
break;
default:
button = 0;
break;
}
setKeyboardModifiers(getEventQueue(), event);
getEventQueue()->mouseDoubleButtonPress(event->x() * windowScale_,
event->y() * windowScale_, button);
}
void GraphicsWindowEx::mouseMoveEvent(QMouseEvent* event) {
setKeyboardModifiers(getEventQueue(), event);
getEventQueue()->mouseMotion(event->x() * windowScale_,
event->y() * windowScale_);
}
void GraphicsWindowEx::wheelEvent(QWheelEvent* event) {
setKeyboardModifiers(getEventQueue(), event);
getEventQueue()->mouseMotion(event->x() * windowScale_,
event->y() * windowScale_);
getEventQueue()->mouseScroll(
event->orientation() == Qt::Vertical ?
(event->delta() > 0 ? osgGA::GUIEventAdapter::SCROLL_UP :
osgGA::GUIEventAdapter::SCROLL_DOWN) :
(event->delta() > 0 ? osgGA::GUIEventAdapter::SCROLL_LEFT :
osgGA::GUIEventAdapter::SCROLL_RIGHT));
}
void GraphicsWindowEx::InitOffScreenContext() {
if (isSharedContextSet_) {
return;
}
if (!offScreenSurface_) {
offScreenSurface_.reset(new QOffscreenSurface);
}
if (!offScreenContext_) {
offScreenContext_.reset(new QOpenGLContext);
}
LOG_INFO("Set shared context");
dyt_check(nullptr != sharedContext_);
offScreenContext_->setFormat(sharedContext_->format());
offScreenContext_->setShareContext(sharedContext_);
isSharedContextSet_ = offScreenContext_->create();
if (!isSharedContextSet_) {
LOG_ERROR("Failed to create offscreen context");
return;
}
offScreenSurface_->setFormat(offScreenContext_->format());
offScreenSurface_->create();
}
void GraphicsWindowEx::InitFrameBuffer() {
if (isFrameBufferInitialized_) {
return;
}
QOpenGLFramebufferObjectFormat format;
format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
dyt_check(nullptr != _traits);
renderFramebuffer_.reset(new QOpenGLFramebufferObject(_traits->width, _traits->height, format));
sharedFrameBuffer_.reset(new QOpenGLFramebufferObject(_traits->width, _traits->height, format));
isFrameBufferInitialized_ = true;
}

View File

@ -1,18 +1,21 @@
#ifndef GRAPHICSWINDOWEX_H #ifndef GRAPHICSWINDOWEX_H
#define GRAPHICSWINDOWEX_H #define GRAPHICSWINDOWEX_H
#include <QObject>
#include <osgViewer/GraphicsWindow> #include <osgViewer/GraphicsWindow>
#include <QOffscreenSurface>
#include <QOpenGLContext>
#include <QOpenGLFramebufferObject>
/// Needed for mixing osg rendering with Qt 2D drawing using QPainter... /// Needed for mixing osg rendering with Qt 2D drawing using QPainter...
/// See http://forum.openscenegraph.org/viewtopic.php?t=15627&view=previous /// See http://forum.openscenegraph.org/viewtopic.php?t=15627&view=previous
class GraphicsWindowEx : public osgViewer::GraphicsWindowEmbedded class GraphicsWindowEx : public osgViewer::GraphicsWindowEmbedded {
{
public: public:
GraphicsWindowEx(osg::GraphicsContext::Traits* traits); GraphicsWindowEx(osg::GraphicsContext::Traits* traits);
GraphicsWindowEx(int x, int y, int width, int height); GraphicsWindowEx(int x, int y, int width, int height);
~GraphicsWindowEx() override;
void init();
virtual bool isSameKindAs(const osg::Object* object) const virtual bool isSameKindAs(const osg::Object* object) const
{ {
@ -32,27 +35,55 @@ public:
{ {
return true; return true;
} }
virtual bool realizeImplementation() bool isRealizedImplementation() const override {
{ return isRealized_;
return true;
} }
virtual bool isRealizedImplementation() const bool realizeImplementation() override;
{ bool makeCurrentImplementation() override;
return true; void closeImplementation() override;
bool releaseContextImplementation() override;
void swapBuffersImplementation() override;
bool SetSharedContext(QOpenGLContext* sharedContext);
void UpdateWindowScale(float scale) {
windowScale_ = scale;
} }
virtual void closeImplementation() {} unsigned int GetFrameBufferId() {
virtual bool makeCurrentImplementation() isRenderDonwn_ = true;
{ return frameBufferId_;
return true;
} }
virtual bool releaseContextImplementation()
{ void ReizeWindow(int width, int height);
return true;
} public:
virtual void swapBuffersImplementation() {} void keyPressEvent(class QKeyEvent* event);
virtual void grabFocus() {} void keyReleaseEvent(class QKeyEvent* event);
virtual void grabFocusIfPointerInWindow() {} void mousePressEvent(class QMouseEvent* event);
virtual void raiseWindow() {} void mouseReleaseEvent(class QMouseEvent* event);
void mouseDoubleClickEvent(class QMouseEvent* event);
void mouseMoveEvent(class QMouseEvent* event);
void wheelEvent(class QWheelEvent* event);
protected:
void InitOffScreenContext();
void InitFrameBuffer();
private:
std::unique_ptr<QOffscreenSurface> offScreenSurface_{nullptr};
std::unique_ptr<QOpenGLContext> offScreenContext_{ nullptr };
std::unique_ptr<QOpenGLFramebufferObject> renderFramebuffer_{ nullptr };
std::unique_ptr<QOpenGLFramebufferObject> sharedFrameBuffer_{ nullptr };
QOpenGLContext* sharedContext_{ nullptr };
bool isSharedContextSet_{ false };
bool isRealized_{ false };
bool isFrameBufferInitialized_{ false };
bool isRenderDonwn_{ false };
unsigned int frameBufferId_{ 0 };
float windowScale_{ 1.0f };
}; };
#endif // GRAPHICSWINDOWEX_H #endif // GRAPHICSWINDOWEX_H

57
src/viewer/OSGEnv.cpp Normal file
View File

@ -0,0 +1,57 @@
#include "viewer/OSGEnv.h"
#include <QSurfaceFormat>
#include <osgDB/Registry>
#include <osgEarth/Capabilities>
#include <osgEarth/Registry>
bool s_gBChecked = false;
bool OSGEnv::init() {
//osgEarth::initialize();
//osgEarth::Registry::instance()->getCapabilities();
/*const osgEarth::Capabilities& csCapabilities = osgEarth::Registry::instance()->getCapabilities();
s_gBChecked = csCapabilities.supportsGLSL();
if (!s_gBChecked) {
return(s_gBChecked);
}
int nMax, nMin;
sscanf(csCapabilities.getVersion().data(), "%d.%d", &nMax, &nMin);*/
//QSurfaceFormat format = QSurfaceFormat::defaultFormat();
//osg::GraphicsContext::Traits traits(osg::DisplaySettings::instance().get());
//int nHttpThreads = osg::DisplaySettings::instance()->getNumOfDatabaseThreadsHint();
//nHttpThreads = nHttpThreads < 1 ? 1 : nHttpThreads;
//osg::DisplaySettings::instance()->setNumOfHttpDatabaseThreadsHint(nHttpThreads);
//format.setAlphaBufferSize(traits.alpha);
//format.setRedBufferSize(traits.red);
//format.setGreenBufferSize(traits.green);
//format.setBlueBufferSize(traits.blue);
//format.setDepthBufferSize(traits.depth);
//format.setStencilBufferSize(traits.stencil);
//format.setSamples(traits.samples);
//format.setVersion(nMax, nMin);
///// ÅжÏÊÇ·ñÖ§³ÖºËÐÄģʽ
//if (csCapabilities.isCoreProfile()) {
// format.setProfile(QSurfaceFormat::CoreProfile);
//} else {
// format.setProfile(QSurfaceFormat::CompatibilityProfile);
//}
//format.setSwapInterval(traits.vsync ? 1 : 0);
//format.setStereo(traits.quadBufferStereo ? 1 : 0);
//QSurfaceFormat::setDefaultFormat(format);
osgDB::Registry::instance()->getObjectWrapperManager()->findWrapper("osg::Image");
return true;
}
void OSGEnv::destroy() {
}

7
src/viewer/OSGEnv.h Normal file
View File

@ -0,0 +1,7 @@
#pragma once
class OSGEnv {
public:
static bool init();
static void destroy();
};

View File

@ -15,7 +15,7 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "viewer/OSGRenderer.h" #include "viewer/OSGRenderer.h"
#include "viewer/osgQOpenGLWindow.h" #include "viewer/OsgOpenGLWindow.h"
#include "viewer/osgQOpenGLWidget.h" #include "viewer/osgQOpenGLWidget.h"
//#include <osgQOpenGL/CullVisitorEx> //#include <osgQOpenGL/CullVisitorEx>
@ -32,481 +32,85 @@
#include <QMouseEvent> #include <QMouseEvent>
#include <QWheelEvent> #include <QWheelEvent>
#include <QThread> #include <osgViewer/GraphicsWindow>
#include <osgEarth/GLUtils>
namespace #include "config.h"
{ #include "common/SpdLogger.h"
#include "workspace/WorkSpaceManager.h"
class QtKeyboardMap
{
public:
QtKeyboardMap()
{
mKeyMap[Qt::Key_Escape ] = osgGA::GUIEventAdapter::KEY_Escape;
mKeyMap[Qt::Key_Delete ] = osgGA::GUIEventAdapter::KEY_Delete;
mKeyMap[Qt::Key_Home ] = osgGA::GUIEventAdapter::KEY_Home;
mKeyMap[Qt::Key_Enter ] = osgGA::GUIEventAdapter::KEY_KP_Enter;
mKeyMap[Qt::Key_End ] = osgGA::GUIEventAdapter::KEY_End;
mKeyMap[Qt::Key_Return ] = osgGA::GUIEventAdapter::KEY_Return;
mKeyMap[Qt::Key_PageUp ] = osgGA::GUIEventAdapter::KEY_Page_Up;
mKeyMap[Qt::Key_PageDown ] = osgGA::GUIEventAdapter::KEY_Page_Down;
mKeyMap[Qt::Key_Left ] = osgGA::GUIEventAdapter::KEY_Left;
mKeyMap[Qt::Key_Right ] = osgGA::GUIEventAdapter::KEY_Right;
mKeyMap[Qt::Key_Up ] = osgGA::GUIEventAdapter::KEY_Up;
mKeyMap[Qt::Key_Down ] = osgGA::GUIEventAdapter::KEY_Down;
mKeyMap[Qt::Key_Backspace ] = osgGA::GUIEventAdapter::KEY_BackSpace;
mKeyMap[Qt::Key_Tab ] = osgGA::GUIEventAdapter::KEY_Tab;
mKeyMap[Qt::Key_Space ] = osgGA::GUIEventAdapter::KEY_Space;
mKeyMap[Qt::Key_Delete ] = osgGA::GUIEventAdapter::KEY_Delete;
mKeyMap[Qt::Key_Alt ] = osgGA::GUIEventAdapter::KEY_Alt_L;
mKeyMap[Qt::Key_Shift ] = osgGA::GUIEventAdapter::KEY_Shift_L;
mKeyMap[Qt::Key_Control ] = osgGA::GUIEventAdapter::KEY_Control_L;
mKeyMap[Qt::Key_Meta ] = osgGA::GUIEventAdapter::KEY_Meta_L;
mKeyMap[Qt::Key_F1 ] = osgGA::GUIEventAdapter::KEY_F1;
mKeyMap[Qt::Key_F2 ] = osgGA::GUIEventAdapter::KEY_F2;
mKeyMap[Qt::Key_F3 ] = osgGA::GUIEventAdapter::KEY_F3;
mKeyMap[Qt::Key_F4 ] = osgGA::GUIEventAdapter::KEY_F4;
mKeyMap[Qt::Key_F5 ] = osgGA::GUIEventAdapter::KEY_F5;
mKeyMap[Qt::Key_F6 ] = osgGA::GUIEventAdapter::KEY_F6;
mKeyMap[Qt::Key_F7 ] = osgGA::GUIEventAdapter::KEY_F7;
mKeyMap[Qt::Key_F8 ] = osgGA::GUIEventAdapter::KEY_F8;
mKeyMap[Qt::Key_F9 ] = osgGA::GUIEventAdapter::KEY_F9;
mKeyMap[Qt::Key_F10 ] = osgGA::GUIEventAdapter::KEY_F10;
mKeyMap[Qt::Key_F11 ] = osgGA::GUIEventAdapter::KEY_F11;
mKeyMap[Qt::Key_F12 ] = osgGA::GUIEventAdapter::KEY_F12;
mKeyMap[Qt::Key_F13 ] = osgGA::GUIEventAdapter::KEY_F13;
mKeyMap[Qt::Key_F14 ] = osgGA::GUIEventAdapter::KEY_F14;
mKeyMap[Qt::Key_F15 ] = osgGA::GUIEventAdapter::KEY_F15;
mKeyMap[Qt::Key_F16 ] = osgGA::GUIEventAdapter::KEY_F16;
mKeyMap[Qt::Key_F17 ] = osgGA::GUIEventAdapter::KEY_F17;
mKeyMap[Qt::Key_F18 ] = osgGA::GUIEventAdapter::KEY_F18;
mKeyMap[Qt::Key_F19 ] = osgGA::GUIEventAdapter::KEY_F19;
mKeyMap[Qt::Key_F20 ] = osgGA::GUIEventAdapter::KEY_F20;
mKeyMap[Qt::Key_hyphen ] = '-';
mKeyMap[Qt::Key_Equal ] = '=';
mKeyMap[Qt::Key_division ] = osgGA::GUIEventAdapter::KEY_KP_Divide;
mKeyMap[Qt::Key_multiply ] = osgGA::GUIEventAdapter::KEY_KP_Multiply;
mKeyMap[Qt::Key_Minus ] = '-';
mKeyMap[Qt::Key_Plus ] = '+';
mKeyMap[Qt::Key_Insert ] = osgGA::GUIEventAdapter::KEY_KP_Insert;
}
~QtKeyboardMap()
{
}
int remapKey(QKeyEvent* event)
{
KeyMap::iterator itr = mKeyMap.find(event->key());
if(itr == mKeyMap.end())
{
return int(*(event->text().toLatin1().data()));
}
else
return itr->second;
}
private:
typedef std::map<unsigned int, int> KeyMap;
KeyMap mKeyMap;
};
static QtKeyboardMap s_QtKeyboardMap;
} // namespace
OSGRenderer::OSGRenderer(QObject* parent) OSGRenderer::OSGRenderer(QObject* parent)
: QObject(parent), osgViewer::Viewer() : QObject(parent), osgViewer::Viewer() {
{ setThreadingModel(osgViewer::Viewer::SingleThreaded);
// QObject::connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, connect(this, &OSGRenderer::Initialized, &WorkSpaceManager::Get(), &WorkSpaceManager::OnRendererLoaded);
// [this]() setRealizeOperation(new osgEarth::GL3RealizeOperation());
// {
// _applicationAboutToQuit = true;
// killTimer(_timerId);
// _timerId = 0;
// });
}
OSGRenderer::OSGRenderer(osg::ArgumentParser* arguments, QObject* parent)
: QObject(parent), osgViewer::Viewer(*arguments)
{
// QObject::connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit,
// [this]()
// {
// _applicationAboutToQuit = true;
// killTimer(_timerId);
// _timerId = 0;
// });
} }
OSGRenderer::~OSGRenderer() OSGRenderer::~OSGRenderer()
{ {
} }
void OSGRenderer::update() void OSGRenderer::Init(osg::GraphicsContext* gc) {
{ LOG_INFO("OSGRenderer::Init {}, gc:{}", isInited_, spdlog::fmt_lib::ptr(gc));
osgQOpenGLWindow* osgWidgetRendered = dynamic_cast<osgQOpenGLWindow*>(parent()); if (!gc) {
if(osgWidgetRendered != nullptr)
{
osgWidgetRendered->_osgWantsToRenderFrame = true;
osgWidgetRendered->update();
}
else
{
osgQOpenGLWidget* osgWidget = dynamic_cast<osgQOpenGLWidget*>(parent());
osgWidget->_osgWantsToRenderFrame = true;
osgWidget->update();
}
}
void OSGRenderer::resize(int windowWidth, int windowHeight, float windowScale)
{
if(!m_osgInitialized)
return;
m_windowScale = windowScale;
/* _camera->setViewport(new osg::Viewport(0, 0, windowWidth * windowScale,
windowHeight * windowScale));*/
m_osgWinEmb->resized(0, 0,
windowWidth * windowScale,
windowHeight * windowScale);
m_osgWinEmb->getEventQueue()->windowResize(0, 0,
windowWidth * windowScale,
windowHeight * windowScale);
update();
}
void OSGRenderer::setupOSG(int windowWidth, int windowHeight, float windowScale)
{
m_osgInitialized = true;
m_windowScale = windowScale;
m_osgWinEmb = new osgViewer::GraphicsWindowEmbedded(0, 0,
windowWidth * windowScale, windowHeight * windowScale);
//m_osgWinEmb = new osgViewer::GraphicsWindowEmbedded(0, 0, windowWidth * windowScale, windowHeight * windowScale);
// make sure the event queue has the correct window rectangle size and input range
m_osgWinEmb->getEventQueue()->syncWindowRectangleWithGraphicsContext();
_camera->setViewport(new osg::Viewport(0, 0, windowWidth * windowScale,
windowHeight * windowScale));
_camera->setGraphicsContext(m_osgWinEmb.get());
// disable key event (default is Escape key) that the viewer checks on each
// frame to see
// if the viewer's done flag should be set to signal end of viewers main
// loop.
setKeyEventSetsDone(0);
setReleaseContextAtEndOfFrameHint(false);
setThreadingModel(osgViewer::Viewer::SingleThreaded);
osgViewer::Viewer::Windows windows;
getWindows(windows);
_timerId = startTimer(10, Qt::PreciseTimer);
_lastFrameStartTime.setStartTick(0);
}
void OSGRenderer::setKeyboardModifiers(QInputEvent* event)
{
unsigned int modkey = event->modifiers() & (Qt::ShiftModifier |
Qt::ControlModifier |
Qt::AltModifier);
unsigned int mask = 0;
if(modkey & Qt::ShiftModifier) mask |= osgGA::GUIEventAdapter::MODKEY_SHIFT;
if(modkey & Qt::ControlModifier) mask |= osgGA::GUIEventAdapter::MODKEY_CTRL;
if(modkey & Qt::AltModifier) mask |= osgGA::GUIEventAdapter::MODKEY_ALT;
m_osgWinEmb->getEventQueue()->getCurrentEventState()->setModKeyMask(mask);
}
void OSGRenderer::keyPressEvent(QKeyEvent* event)
{
setKeyboardModifiers(event);
int value = s_QtKeyboardMap.remapKey(event);
m_osgWinEmb->getEventQueue()->keyPress(value);
}
void OSGRenderer::keyReleaseEvent(QKeyEvent* event)
{
if(event->isAutoRepeat())
{
event->ignore();
}
else
{
setKeyboardModifiers(event);
int value = s_QtKeyboardMap.remapKey(event);
m_osgWinEmb->getEventQueue()->keyRelease(value);
}
}
void OSGRenderer::mousePressEvent(QMouseEvent* event)
{
int button = 0;
switch(event->button())
{
case Qt::LeftButton:
button = 1;
break;
case Qt::MidButton:
button = 2;
break;
case Qt::RightButton:
button = 3;
break;
case Qt::NoButton:
button = 0;
break;
default:
button = 0;
break;
}
setKeyboardModifiers(event);
m_osgWinEmb->getEventQueue()->mouseButtonPress(event->x() * m_windowScale,
event->y() * m_windowScale, button);
}
void OSGRenderer::mouseReleaseEvent(QMouseEvent* event)
{
int button = 0;
switch(event->button())
{
case Qt::LeftButton:
button = 1;
break;
case Qt::MidButton:
button = 2;
break;
case Qt::RightButton:
button = 3;
break;
case Qt::NoButton:
button = 0;
break;
default:
button = 0;
break;
}
setKeyboardModifiers(event);
m_osgWinEmb->getEventQueue()->mouseButtonRelease(event->x() * m_windowScale,
event->y() * m_windowScale, button);
}
void OSGRenderer::mouseDoubleClickEvent(QMouseEvent* event)
{
int button = 0;
switch(event->button())
{
case Qt::LeftButton:
button = 1;
break;
case Qt::MidButton:
button = 2;
break;
case Qt::RightButton:
button = 3;
break;
case Qt::NoButton:
button = 0;
break;
default:
button = 0;
break;
}
setKeyboardModifiers(event);
m_osgWinEmb->getEventQueue()->mouseDoubleButtonPress(event->x() * m_windowScale,
event->y() * m_windowScale, button);
}
void OSGRenderer::mouseMoveEvent(QMouseEvent* event)
{
setKeyboardModifiers(event);
m_osgWinEmb->getEventQueue()->mouseMotion(event->x() * m_windowScale,
event->y() * m_windowScale);
}
void OSGRenderer::wheelEvent(QWheelEvent* event)
{
setKeyboardModifiers(event);
m_osgWinEmb->getEventQueue()->mouseMotion(event->x() * m_windowScale,
event->y() * m_windowScale);
m_osgWinEmb->getEventQueue()->mouseScroll(
event->orientation() == Qt::Vertical ?
(event->delta() > 0 ? osgGA::GUIEventAdapter::SCROLL_UP :
osgGA::GUIEventAdapter::SCROLL_DOWN) :
(event->delta() > 0 ? osgGA::GUIEventAdapter::SCROLL_LEFT :
osgGA::GUIEventAdapter::SCROLL_RIGHT));
}
bool OSGRenderer::checkEvents()
{
// check events from any attached sources
for(Devices::iterator eitr = _eventSources.begin();
eitr != _eventSources.end();
++eitr)
{
osgGA::Device* es = eitr->get();
if(es->getCapabilities() & osgGA::Device::RECEIVE_EVENTS)
{
if(es->checkEvents())
return true;
}
}
// get events from all windows attached to Viewer.
Windows windows;
getWindows(windows);
for(Windows::iterator witr = windows.begin();
witr != windows.end();
++witr)
{
if((*witr)->checkEvents())
return true;
}
return false;
}
bool OSGRenderer::checkNeedToDoFrame()
{
// check if any event handler has prompted a redraw
if(_requestRedraw)
return true;
if(_requestContinousUpdate)
return true;
// check if the view needs to update the scene graph
// this check if camera has update callback and if scene requires to update scene graph
if(requiresUpdateSceneGraph())
return true;
// check if the database pager needs to update the scene
if(getDatabasePager()->requiresUpdateSceneGraph())
return true;
// check if the image pager needs to update the scene
if(getImagePager()->requiresUpdateSceneGraph())
return true;
// check if the scene needs to be redrawn
if(requiresRedraw())
return true;
// check if events are available and need processing
if(checkEvents())
return true;
// and check again if any event handler has prompted a redraw
if(_requestRedraw)
return true;
if(_requestContinousUpdate)
return true;
return false;
}
// called from ViewerWidget paintGL() method
void OSGRenderer::frame(double simulationTime)
{
// limit the frame rate
if(getRunMaxFrameRate() > 0.0)
{
double dt = _lastFrameStartTime.time_s();
double minFrameTime = 1.0 / getRunMaxFrameRate();
if(dt < minFrameTime)
QThread::usleep(static_cast<unsigned int>(1000000.0 * (minFrameTime - dt)));
}
// avoid excessive CPU loading when no frame is required in ON_DEMAND mode
if(getRunFrameScheme() == osgViewer::ViewerBase::ON_DEMAND)
{
double dt = _lastFrameStartTime.time_s();
if(dt < 0.01)
OpenThreads::Thread::microSleep(static_cast<unsigned int>(1000000.0 *
(0.01 - dt)));
}
// record start frame time
_lastFrameStartTime.setStartTick();
// make frame
#if 1
osgViewer::Viewer::frame(simulationTime);
#else
if(_done) return;
// OSG_NOTICE<<std::endl<<"CompositeViewer::frame()"<<std::endl<<std::endl;
if(_firstFrame)
{
viewerInit();
if(!isRealized())
{
realize();
}
_firstFrame = false;
}
advance(simulationTime);
eventTraversal();
updateTraversal();
// renderingTraversals();
#endif
}
void OSGRenderer::requestRedraw()
{
osgViewer::Viewer::requestRedraw();
}
void OSGRenderer::timerEvent(QTimerEvent* /*event*/)
{
// application is about to quit, just return
if(_applicationAboutToQuit)
{
return; return;
} }
// ask ViewerWidget to update 3D view if (isInited_) {
if(getRunFrameScheme() != osgViewer::ViewerBase::ON_DEMAND || return;
checkNeedToDoFrame())
{
update();
} }
getCamera()->setGraphicsContext(gc);
getCamera()->setViewport(new osg::Viewport(0, 0, gc->getTraits()->width, gc->getTraits()->height));
getCamera()->setDrawBuffer(GL_BACK);
getCamera()->setReadBuffer(GL_BACK);
getCamera()->setProjectionMatrixAsPerspective(45, 1.0, 0.01, 100.);
isInited_ = true;
emit Initialized(this);
} }
void OSGRenderer::Resize(GraphicsWindowEx* gc, int width, int height) {
if (!isInited_) {
return;
}
LOG_INFO("OSGRenderer::Resize {}, gc:{}", isInited_, spdlog::fmt_lib::ptr(gc));
dyt_check(nullptr != gc);
gc->ReizeWindow(width, height);
}
void OSGRenderer::Render() {
frame();
emit RenderFlush();
}
void OSGRenderer::Destoy() {
done();
}
bool OSGRenderer::event(QEvent* event) {
switch (event->type()) {
case INIT: {
RenderBindGraphicsContextEvent* e = reinterpret_cast<RenderBindGraphicsContextEvent*>(event);
Init(e->gc_.get());
return true;
}
case RENDER: {
Render();
return true;
}
case RESIZE: {
GraphicsWindowResizeEvent* e = reinterpret_cast<GraphicsWindowResizeEvent*>(event);
Resize(e->gc_.get(), e->width_, e->height_);
return true;
}
case DESTROY: {
GraphicsWindowResizeEvent* e = reinterpret_cast<GraphicsWindowResizeEvent*>(event);
Resize(e->gc_.get(), e->width_, e->height_);
return true;
}
}
return QObject::event(event);
}

View File

@ -18,79 +18,64 @@
#define OSGRENDERER_H #define OSGRENDERER_H
#include <QObject> #include <QObject>
#include <QEvent>
#include <osgViewer/Viewer> #include <osgViewer/Viewer>
class QInputEvent; #include "GraphicsWindowEx.h"
class QKeyEvent;
class QMouseEvent; namespace {
class QWheelEvent; enum RenderEvent {
namespace eveBIM INIT = QEvent::Type(QEvent::User + 1),
{ RENDER,
class ViewerWidget; RESIZE,
DESTROY
};
struct RenderBindGraphicsContextEvent : public QEvent {
RenderBindGraphicsContextEvent(osg::GraphicsContext* gc)
: QEvent(QEvent::Type(INIT))
, gc_(gc) {}
osg::observer_ptr<osg::GraphicsContext> gc_;
};
struct GraphicsWindowResizeEvent : public QEvent {
GraphicsWindowResizeEvent(GraphicsWindowEx* gc, int width, int height)
: QEvent(QEvent::Type(RESIZE))
, gc_(gc)
, width_(width)
, height_(height) {}
osg::observer_ptr<GraphicsWindowEx> gc_;
int width_;
int height_;
};
} }
class OSGRenderer : public QObject, public osgViewer::Viewer class OSGRenderer : public QObject, public osgViewer::Viewer {
{
bool m_osgInitialized {false};
osg::ref_ptr<osgViewer::GraphicsWindow> m_osgWinEmb;
float m_windowScale {1.0f};
bool m_continuousUpdate {true};
int _timerId{0};
osg::Timer _lastFrameStartTime;
bool _applicationAboutToQuit {false};
bool _osgWantsToRenderFrame{true};
Q_OBJECT Q_OBJECT
friend class eveBIM::ViewerWidget;
public: public:
explicit OSGRenderer(QObject* parent = nullptr); explicit OSGRenderer(QObject* parent = nullptr);
explicit OSGRenderer(osg::ArgumentParser* arguments, QObject* parent = nullptr);
~OSGRenderer() override; ~OSGRenderer() override;
bool continuousUpdate() const bool event(QEvent* event) override;
{
return m_continuousUpdate;
}
void setContinuousUpdate(bool continuousUpdate)
{
m_continuousUpdate = continuousUpdate;
}
virtual void keyPressEvent(QKeyEvent* event); Q_SIGNALS:
virtual void keyReleaseEvent(QKeyEvent* event); void Initialized(OSGRenderer* viewer);
virtual void mousePressEvent(QMouseEvent* event); void RenderFlush();
virtual void mouseReleaseEvent(QMouseEvent* event);
virtual void mouseDoubleClickEvent(QMouseEvent* event);
virtual void mouseMoveEvent(QMouseEvent* event);
virtual void wheelEvent(QWheelEvent* event);
virtual void resize(int windowWidth, int windowHeight, float windowScale); private:
void Init(osg::GraphicsContext* gc);
void setupOSG(int windowWidth, int windowHeight, float windowScale); void Resize(GraphicsWindowEx* gc, int width, int height);
void Render();
// overrided from osgViewer::Viewer void Destoy();
virtual bool checkNeedToDoFrame() override;
// overrided from osgViewer::ViewerBase
void frame(double simulationTime = USE_REFERENCE_TIME) override;
// overrided from osgViewer::Viewer
void requestRedraw() override;
// overrided from osgViewer::Viewer
bool checkEvents() override;
void update();
protected:
void timerEvent(QTimerEvent* event) override;
void setKeyboardModifiers(QInputEvent* event);
private:
bool isInited_{ false };
}; };
#endif // OSGRENDERER_H #endif // OSGRENDERER_H

View File

@ -0,0 +1,195 @@
#include "viewer/OsgOpenGLWindow.h"
#include "viewer/OSGRenderer.h"
#include <osgViewer/Viewer>
#include <osg/GL>
#include <QApplication>
#include <QKeyEvent>
#include <QInputDialog>
#include <QLayout>
#include <QMainWindow>
#include <QScreen>
#include <QWindow>
#include <QOpenGLShaderProgram>
#include <QOpenGLVertexArrayObject>
#include "config.h"
#include "common/SpdLogger.h"
#include "viewer/GraphicsWindowEx.h"
static const char* vertexShaderSource =
"#version 330\n"
"out vec2 uv;\n"
"void main(void)\n"
"{\n"
"vec2 pos[] = vec2[](vec2(-1.0, -1.0),\n"
"vec2( 1.0, -1.0),\n"
"vec2(-1.0, 1.0),\n"
"vec2( 1.0, 1.0));\n"
"vec2 uvpos[] = vec2[](vec2(0, 0.0),\n"
"vec2( 1.0, 0.0),\n"
"vec2(0.0, 1.0),\n"
"vec2( 1.0, 1.0));\n"
"gl_Position = vec4(pos[gl_VertexID], 0.0, 1.0);\n"
"uv = uvpos[gl_VertexID];\n"
"}\n";
static const char* fragmentShaderSource =
"#version 330\n"
"in vec2 uv;\n"
"uniform sampler2D tex;\n"
"out vec4 vFragColor;"
"void main() {\n"
" vFragColor = vec4(texture(tex, uv).rgb, 1.0);\n"
"}\n";
OsgOpenGLWindow::OsgOpenGLWindow(QWidget* parent)
: QOpenGLWindow(QOpenGLWindow::NoPartialUpdate, nullptr) {
widget_ = QWidget::createWindowContainer(this);
widget_->setAttribute(Qt::WA_PaintOnScreen, true);
widget_->setAttribute(Qt::WA_StaticContents, true);
widget_->setAttribute(Qt::WA_NoSystemBackground, true);
widget_->setAttribute(Qt::WA_OpaquePaintEvent, true);
widget_->setAttribute(Qt::WA_DontCreateNativeAncestors, false);
gw_ = new GraphicsWindowEx(0, 0, width(), height());
renderer_ = new OSGRenderer(this);
connect(renderer_, &OSGRenderer::RenderFlush, this, &OsgOpenGLWindow::OnRenderFlush, Qt::QueuedConnection);
connect(&timer_, &QTimer::timeout, this, &OsgOpenGLWindow::OnRender);
}
OsgOpenGLWindow::~OsgOpenGLWindow() {}
osgViewer::Viewer* OsgOpenGLWindow::getOsgViewer() {
return renderer_;
}
void OsgOpenGLWindow::initializeGL() {
//// Initializes OpenGL function resolution for the current context.
//initializeOpenGLFunctions();
//createRenderer();
//emit initialized();
QOpenGLContext* ctx = context();
dyt_check(nullptr != ctx);
ctx->doneCurrent();
gw_->SetSharedContext(context());
QApplication::postEvent(renderer_, new RenderBindGraphicsContextEvent(gw_));
setDefaultDisplaySettings();
double pixelRatio = screen()->devicePixelRatio();
gw_->UpdateWindowScale(pixelRatio);
QApplication::postEvent(renderer_, new GraphicsWindowResizeEvent(gw_, width() * pixelRatio, height() * pixelRatio));
QApplication::postEvent(renderer_, new QEvent(QEvent::Type(RENDER)));
context()->makeCurrent(this);
shaderProgram_ = new QOpenGLShaderProgram(this);
vao_ = new QOpenGLVertexArrayObject(this);
if (!vao_->create()) {
LOG_ERROR("Failed to create VAO");
return;
}
if (!shaderProgram_->addCacheableShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource)) {
LOG_ERROR("Failed to add vertex shader");
return;
}
if (!shaderProgram_->addCacheableShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource)) {
LOG_ERROR("Failed to add fragment shader");
return;
}
if (!shaderProgram_->link()) {
LOG_ERROR("Failed to link shader program, {}", shaderProgram_->log().toLocal8Bit().constData());
return;
}
timer_.start(1000 / 60);
}
void OsgOpenGLWindow::resizeGL(int w, int h) {
double pixelRatio = screen()->devicePixelRatio();
gw_->UpdateWindowScale(pixelRatio);
QApplication::postEvent(renderer_, new GraphicsWindowResizeEvent(gw_, w * pixelRatio, h * pixelRatio));
}
void OsgOpenGLWindow::paintUnderGL() {
if (0 == shaderTextureId_) {
return;
}
QOpenGLFunctions* f = QOpenGLContext::currentContext()->functions();
f->glViewport(0, 0, width() * devicePixelRatio(), height() * devicePixelRatio());
f->glBindTexture(GL_TEXTURE_2D, shaderTextureId_);
dyt_check(nullptr != shaderProgram_);
dyt_check(shaderProgram_->bind());
QOpenGLVertexArrayObject::Binder vaoBinder(vao_);
f->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
shaderProgram_->release();
if (updateTexture_) {
updateTexture_ = false;
QApplication::postEvent(renderer_, new QEvent(QEvent::Type(RENDER)));
}
}
void OsgOpenGLWindow::keyPressEvent(QKeyEvent* event) {
Q_ASSERT(gw_);
// forward event to renderer
gw_->keyPressEvent(event);
}
void OsgOpenGLWindow::keyReleaseEvent(QKeyEvent* event) {
Q_ASSERT(gw_);
// forward event to renderer
gw_->keyReleaseEvent(event);
}
void OsgOpenGLWindow::mousePressEvent(QMouseEvent* event) {
Q_ASSERT(gw_);
// forward event to renderer
gw_->mousePressEvent(event);
}
void OsgOpenGLWindow::mouseReleaseEvent(QMouseEvent* event) {
Q_ASSERT(gw_);
// forward event to renderer
gw_->mouseReleaseEvent(event);
}
void OsgOpenGLWindow::mouseDoubleClickEvent(QMouseEvent* event) {
Q_ASSERT(gw_);
// forward event to renderer
gw_->mouseDoubleClickEvent(event);
}
void OsgOpenGLWindow::mouseMoveEvent(QMouseEvent* event) {
Q_ASSERT(gw_);
// forward event to renderer
gw_->mouseMoveEvent(event);
}
void OsgOpenGLWindow::wheelEvent(QWheelEvent* event) {
Q_ASSERT(gw_);
// forward event to renderer
gw_->wheelEvent(event);
}
void OsgOpenGLWindow::setDefaultDisplaySettings() {
osg::DisplaySettings* ds = osg::DisplaySettings::instance().get();
ds->setNvOptimusEnablement(1);
ds->setStereo(false);
}
void OsgOpenGLWindow::OnRenderFlush() {
shaderTextureId_ = gw_->GetFrameBufferId();
updateTexture_ = true;
}
void OsgOpenGLWindow::OnRender() {
requestUpdate();
}

View File

@ -17,7 +17,9 @@
#include <QOpenGLWindow> #include <QOpenGLWindow>
#include <QOpenGLFunctions> #include <QOpenGLFunctions>
#include <QReadWriteLock> #include <QTimer>
#include <osg/ref_ptr>
class OSGRenderer; class OSGRenderer;
class QWidget; class QWidget;
@ -27,50 +29,32 @@ namespace osgViewer
class Viewer; class Viewer;
} }
class osgQOpenGLWindow : public QOpenGLWindow, class OsgOpenGLWindow : public QOpenGLWindow {
protected QOpenGLFunctions
{
Q_OBJECT Q_OBJECT
protected:
OSGRenderer* m_renderer {nullptr};
bool _osgWantsToRenderFrame{true};
OpenThreads::ReadWriteMutex _osgMutex;
bool _isFirstFrame {true};
friend class OSGRenderer;
QWidget* _widget = nullptr;
public: public:
osgQOpenGLWindow(QWidget* parent = nullptr); OsgOpenGLWindow(QWidget* parent = nullptr);
virtual ~osgQOpenGLWindow(); ~OsgOpenGLWindow() override;
/** Get osgViewer View */ /** Get osgViewer View */
virtual osgViewer::Viewer* getOsgViewer(); virtual osgViewer::Viewer* getOsgViewer();
//! get mutex
virtual OpenThreads::ReadWriteMutex* mutex();
QWidget* asWidget() QWidget* AsWidget()
{ {
return _widget; return widget_;
} }
signals: signals:
void initialized(); void initialized();
protected: protected:
//! call createRender. If overloaded, this method must send initialized signal at end
void initializeGL() override; void initializeGL() override;
void resizeGL(int w, int h) override; void resizeGL(int w, int h) override;
void paintUnderGL() override;
//! lock scene graph and call osgViewer::frame() void setDefaultDisplaySettings();
void paintGL() override;
//! called before creating renderer
virtual void setDefaultDisplaySettings();
void keyPressEvent(QKeyEvent* event) override; void keyPressEvent(QKeyEvent* event) override;
void keyReleaseEvent(QKeyEvent* event) override; void keyReleaseEvent(QKeyEvent* event) override;
@ -80,7 +64,19 @@ protected:
void mouseMoveEvent(QMouseEvent* event) override; void mouseMoveEvent(QMouseEvent* event) override;
void wheelEvent(QWheelEvent* event) override; void wheelEvent(QWheelEvent* event) override;
void createRenderer(); private:
void OnRenderFlush();
void OnRender();
private:
QWidget* widget_{ nullptr };
osg::ref_ptr<class GraphicsWindowEx> gw_;
OSGRenderer* renderer_{ nullptr };
class QOpenGLShaderProgram* shaderProgram_{nullptr};
class QOpenGLVertexArrayObject* vao_{ nullptr };
uint32_t shaderTextureId_{ 0 };
bool updateTexture_{ false };
QTimer timer_;
}; };
#endif // OSGQOPENGLWINDOW_H #endif // OSGQOPENGLWINDOW_H

View File

@ -0,0 +1,189 @@
#include "viewer/OsgViewWidget.h"
#include <QWheelEvent>
#include <QMouseEvent>
#include <QKeyEvent>
#include <QOpenGLContext>
#include <QOpenGLFunctions>
#include <QGridLayout>
#include <QDebug>
#include <QPainter>
#include <QResizeEvent>
#include <QMessageBox>
#include <QScreen>
#include <QWindow>
#include <osgEarthUtil/EarthManipulator>
#include <osgEarth/Viewpoint>
#include <osgEarth/GeoMath>
#include "config.h"
#include "app/Application.h"
#include "common/SpdLogger.h"
#include "viewer/OsgView.h"
#include "viewer/OsgViewer.h"
#include "viewer/OsgCameraManipulator.h"
#include "viewer/CameraControlManipulator.h"
#include "viewer/OsgViewUI.h"
#include "scene/OsgScene.h"
#include "workspace/WorkSpace.h"
#include "workspace/WorkSpaceManager.h"
#include "scene/SceneContent.h"
#include "scene/ui/OESceneUI.h"
#include "ui/MainFrame.h"
OsgViewWidget::OsgViewWidget(QWidget* parent /*= nullptr*/)
: QOpenGLWidget(parent) {
//osgEarth::initialize();
/* osg::ref_ptr<osg::DisplaySettings> ds = osg::DisplaySettings::instance();
osg::ref_ptr<osg::GraphicsContext::Traits> traits
= new osg::GraphicsContext::Traits(ds);
traits->x = 0;
traits->y = 0;
traits->width = width();
traits->height = height();
traits->alpha = ds->getMinimumNumAlphaBits();
traits->stencil = ds->getMinimumNumStencilBits();
traits->sampleBuffers = ds->getMultiSamples();
traits->samples = ds->getNumMultiSamples();*/
//gw_ = new GraphicsWindowEx(traits);
//gw_ = new GraphicsWindowEx(0, 0, width(), height());
//setAttribute(Qt::WA_PaintOnScreen, true);
//setAttribute(Qt::WA_StaticContents, true);
//setAttribute(Qt::WA_NoSystemBackground, true);
//setAttribute(Qt::WA_OpaquePaintEvent, true);
//setAttribute(Qt::WA_DontCreateNativeAncestors, false);
setFocusPolicy(Qt::ClickFocus);
connect(this, &OsgViewWidget::signalInitialized, &WorkSpaceManager::Get(), &WorkSpaceManager::OnRendererLoaded);
}
void OsgViewWidget::Initialize(void) {
}
void OsgViewWidget::Uninitialize(void) {
}
void OsgViewWidget::LoadDefaultScene(void) {
}
void OsgViewWidget::OnLoadDyt(const QString& path) {
}
void OsgViewWidget::initializeGL() {
//QOpenGLWidget::initializeGL();
//osgViewer::Viewer* viewer = OsgViewer::Get().GetViewer();
//dyt_check(nullptr != viewer);
//osg::Camera* camera = viewer->getCamera();
//camera->setGraphicsContext(gw_);
//camera->setViewport(new osg::Viewport(0, 0, width(), height()));
////camera->setDrawBuffer(GL_BACK);
////camera->setReadBuffer(GL_BACK);
//camera->setProjectionMatrixAsPerspective(45, 1.0, 0.01, 100.);
OsgViewer::Get().Initialize();
emit signalInitialized();
}
void OsgViewWidget::resizeGL(int width, int height) {
//gw_->getEventQueue()->windowResize(0, 0, width, height);
//gw_->resized(0, 0, width, height);
}
void OsgViewWidget::paintGL() {
OsgViewer::Get().OnFrame();
update();
}
void OsgViewWidget::keyPressEvent(QKeyEvent* event) {
switch (event->key()) {
case Qt::Key_Escape:
//emit quitFullScreen(); //for operation
break;
default:
gw_->getEventQueue()->keyPress((osgGA::GUIEventAdapter::KeySymbol) * (event->text().toLatin1().data()));
}
}
void OsgViewWidget::keyReleaseEvent(QKeyEvent* event) {
gw_->getEventQueue()->keyRelease((osgGA::GUIEventAdapter::KeySymbol) * (event->text()./*toAscii()*/toLatin1().data()));
}
void OsgViewWidget::mouseMoveEvent(QMouseEvent* event) {
gw_->getEventQueue()->mouseMotion(event->x(), event->y());
}
void OsgViewWidget::mousePressEvent(QMouseEvent* event) {
int button = 0;
switch (event->button()) {
case(Qt::LeftButton): button = 1; break;
case(Qt::MidButton): button = 2; break;
case(Qt::RightButton): button = 3; break;
case(Qt::NoButton): button = 0; break;
default: button = 0; break;
}
//gw_->getEventQueue()->mouseButtonPress(event->x(), event->y(), button);
}
void OsgViewWidget::mouseReleaseEvent(QMouseEvent* event) {
int button = 0;
switch (event->button()) {
case(Qt::LeftButton): button = 1; break;
case(Qt::MidButton): button = 2; break;
case(Qt::RightButton): button = 3; break;
case(Qt::NoButton): button = 0; break;
default: button = 0; break;
}
//gw_->getEventQueue()->mouseButtonRelease(event->x(), event->y(), button);
}
void OsgViewWidget::mouseDoubleClickEvent(QMouseEvent* event) {
QPoint pos = QCursor::pos();
// QList<QGraphicsItem*> listItems = items(mapToScene(pos.x(), pos.y()).toPoint());
// if (listItems.size() > 0)
// {
// return;
// }
int button = 0;
switch (event->button()) {
case Qt::LeftButton: button = 1; break;
case Qt::MidButton: button = 2; break;
case Qt::RightButton: button = 3; break;
case Qt::NoButton: button = 0; break;
default: button = 0; break;
}
setKeyboardModifiers(event);
//gw_->getEventQueue()->mouseDoubleButtonPress(event->x(), event->y(), button);
QOpenGLWidget::mouseDoubleClickEvent(event);
}
void OsgViewWidget::wheelEvent(QWheelEvent* event) {
setKeyboardModifiers(event);
//gw_->getEventQueue()->mouseScroll(
// event->orientation() == Qt::Vertical ?
// (event->delta() > 0 ? osgGA::GUIEventAdapter::SCROLL_UP : osgGA::GUIEventAdapter::SCROLL_DOWN) :
// (event->delta() > 0 ? osgGA::GUIEventAdapter::SCROLL_LEFT : osgGA::GUIEventAdapter::SCROLL_RIGHT));
QOpenGLWidget::wheelEvent(event);
}
void OsgViewWidget::setKeyboardModifiers(QInputEvent* event) {
int modkey = event->modifiers() & (Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier);
unsigned int mask = 0;
if (modkey & Qt::ShiftModifier) mask |= osgGA::GUIEventAdapter::MODKEY_SHIFT;
if (modkey & Qt::ControlModifier) mask |= osgGA::GUIEventAdapter::MODKEY_CTRL;
if (modkey & Qt::AltModifier) mask |= osgGA::GUIEventAdapter::MODKEY_ALT;
//gw_->getEventQueue()->getCurrentEventState()->setModKeyMask(mask);
}

View File

@ -0,0 +1,70 @@
#pragma once
#include <QOpenGLWidget>
#include "scene/OEScene.h"
#include "viewer/GraphicsWindowEx.h"
class QMouseEvent;
class QWheelEvent;
class QKeyEvent;
class QInputEvent;
class QResizeEvent;
class OsgViewWidget : public QOpenGLWidget {
Q_OBJECT
public:
explicit OsgViewWidget(QWidget* parent = nullptr);
~OsgViewWidget() override = default;
//void setKeyboardModifiers(QInputEvent* event) override;
QPaintEngine* paintEngine() const override {
return nullptr;
}
GraphicsWindowEx* getGraphicsWindow() {
return gw_.get();
}
const GraphicsWindowEx* getGraphicsWindow() const {
return gw_.get();
}
osg::GraphicsContext* getGraphicsContext() {
return gc_.get();
}
const osg::GraphicsContext* getGraphicsContext() const {
return gc_.get();
}
virtual void Initialize(void);
virtual void Uninitialize(void);
void LoadDefaultScene(void);
void OnLoadDyt(const QString& path);
//void setKeyboardModifiers(QInputEvent* event);
signals:
void signalResetWorkSpace();
void signalScaleInfo(const QString&);
void signalInitialized();
protected:
void initializeGL();
void resizeGL(int width, int height) override;
void paintGL() override;
void keyPressEvent(QKeyEvent* event) override;
void keyReleaseEvent(QKeyEvent* event) override;
void mousePressEvent(QMouseEvent* event) override;
void mouseReleaseEvent(QMouseEvent* event) override;
void mouseMoveEvent(QMouseEvent* event) override;
void mouseDoubleClickEvent(QMouseEvent* event) override;
void wheelEvent(QWheelEvent* event) override;
private:
void setKeyboardModifiers(QInputEvent* event);
private:
osg::ref_ptr<GraphicsWindowEx> gw_;
osg::ref_ptr<osg::GraphicsContext> gc_;
};

View File

@ -4,32 +4,26 @@
#include <QApplication> #include <QApplication>
#include <osg/BlendFunc> #include <osg/BlendFunc>
#include <osgEarth/GLUtils> //#include <osgEarth/GLUtils>
#include <osgDB/Registry> #include <osgDB/Registry>
#include "common/SpdLogger.h" #include "common/SpdLogger.h"
#include "viewer/OsgView.h" #include "viewer/OsgView.h"
#include "viewer/IUpdateRender.h" #include "viewer/IUpdateRender.h"
#include "workspace/WorkSpaceManager.h" #include "workspace/WorkSpaceManager.h"
#include <osgEarth/GLUtils>
template<> OsgViewer* Singleton<OsgViewer>::instance_ = nullptr; template<> OsgViewer* Singleton<OsgViewer>::instance_ = nullptr;
constexpr QEvent::Type sOsgViewUpdateEvent{ QEvent::Type(QEvent::User + 1) }; constexpr QEvent::Type sOsgViewUpdateEvent{ QEvent::Type(QEvent::User + 1) };
OsgViewer::OsgViewer(QObject* parent) noexcept OsgViewer::OsgViewer(QObject* parent) noexcept
: QObject(parent) : QObject(parent) {
, compositeViewer_(new osgViewer::CompositeViewer) {
LOG_INFO("actor, self={}", fmt::ptr(this)); LOG_INFO("actor, self={}", fmt::ptr(this));
compositeViewer_->setKeyEventSetsDone(0);
compositeViewer_->getDatabasePager()->setUnrefImageDataAfterApplyPolicy(true, false);
osgEarth::initialize();
osgDB::Registry::instance()->getObjectWrapperManager()->findWrapper("osg::Image");
compositeViewer_->setThreadingModel(osgViewer::ViewerBase::ThreadingModel::SingleThreaded);
} }
OsgViewer::~OsgViewer() { OsgViewer::~OsgViewer() {
compositeViewer_ = nullptr; viewer_ = nullptr;
LOG_INFO("dctor, self={}", fmt::ptr(this)); LOG_INFO("dctor, self={}", fmt::ptr(this));
} }
@ -37,18 +31,22 @@ void OsgViewer::OnDestory() {
} }
osgViewer::Viewer* OsgViewer::GetViewer(void) const {
return viewer_;
}
void OsgViewer::OnFrame(void) { void OsgViewer::OnFrame(void) {
assert(nullptr != compositeViewer_); assert(nullptr != viewer_);
WorkSpaceManager::Get().OnFrame(); WorkSpaceManager::Get().OnFrame();
if (IsDone()) { if (IsDone()) {
RenderUpdate(); RenderUpdate();
compositeViewer_->frame(); viewer_->frame();
} }
qApp->postEvent(this, new QEvent(sOsgViewUpdateEvent)); //qApp->postEvent(this, new QEvent(sOsgViewUpdateEvent));
} }
OsgView* OsgViewer::CreateView(int x, int y, int width, int height, void* winHandle) { OsgView* OsgViewer::CreateView(int x, int y, int width, int height, void* winHandle) {
@ -59,7 +57,7 @@ OsgView* OsgViewer::CreateView(int x, int y, int width, int height, void* winHan
view->InitGraphiceWindow(x, y, width, height, reinterpret_cast<WId>(winHandle), "dytView"); view->InitGraphiceWindow(x, y, width, height, reinterpret_cast<WId>(winHandle), "dytView");
OnAddView(view, x, y, width, height); //OnAddView(view, x, y, width, height);
//compositeViewer_->setRealizeOperation(new osgEarth::GL3RealizeOperation()); //compositeViewer_->setRealizeOperation(new osgEarth::GL3RealizeOperation());
return view; return view;
} }
@ -69,12 +67,12 @@ void OsgViewer::DestroyView(OsgView* osgView) {
return; return;
} }
OnRemoveView(osgView); //OnRemoveView(osgView);
} }
bool OsgViewer::IsDone() const { bool OsgViewer::IsDone() const {
assert(nullptr != compositeViewer_); assert(nullptr != viewer_);
bool done = compositeViewer_->done(); bool done = viewer_->done();
return !done && initalized_; return !done && initalized_;
} }
@ -90,8 +88,15 @@ bool OsgViewer::Initialize(void) {
if (initalized_) { if (initalized_) {
return initalized_; return initalized_;
} }
viewer_ = new osgViewer::Viewer;
viewer_->setKeyEventSetsDone(0);
//compositeViewer_->getDatabasePager()->setUnrefImageDataAfterApplyPolicy(true, false);
//osgDB::Registry::instance()->getObjectWrapperManager()->findWrapper("osg::Image");
//viewer_->setThreadingModel(osgViewer::ViewerBase::ThreadingModel::SingleThreaded);
viewer_->setRealizeOperation(new osgEarth::GL3RealizeOperation());
initalized_ = true; initalized_ = true;
compositeViewer_->setRealizeOperation(new osgEarth::GL3RealizeOperation()); //compositeViewer_->setRealizeOperation(new osgEarth::GL3RealizeOperation());
return initalized_; return initalized_;
} }
@ -137,29 +142,29 @@ void OsgViewer::customEvent(QEvent* event) {
} }
void OsgViewer::OnStartPlay() { void OsgViewer::OnStartPlay() {
compositeViewer_->setStartTick(0); viewer_->setStartTick(0);
} }
void OsgViewer::OnAddView(OsgView* osgView, int x, int y, int width, int height) { //void OsgViewer::OnAddView(OsgView* osgView, int x, int y, int width, int height) {
osgViewer::View* view = new osgViewer::View; // osgViewer::View* view = new osgViewer::View;
osgView->InitView(view); // osgView->InitView(view);
//
compositeViewer_->addView(view); // viewer_->addView(view);
osgViews_.insert(osgView); // osgViews_.insert(osgView);
} //}
//
void OsgViewer::OnRemoveView(OsgView* osgView) { //void OsgViewer::OnRemoveView(OsgView* osgView) {
if (nullptr == osgView || nullptr == osgView->GetView()) { // if (nullptr == osgView || nullptr == osgView->GetView()) {
LOG_WARN("osgview is nullptr or getview is nullptr"); // LOG_WARN("osgview is nullptr or getview is nullptr");
return; // return;
} // }
//
osgViews_.erase(osgView); // osgViews_.erase(osgView);
compositeViewer_->removeView(osgView->GetView()); // compositeViewer_->removeView(osgView->GetView());
} //}
void OsgViewer::RenderUpdate() { void OsgViewer::RenderUpdate() {
osg::FrameStamp* frameStamp = compositeViewer_->getFrameStamp(); osg::FrameStamp* frameStamp = viewer_->getFrameStamp();
double dt = frameStamp->getSimulationTime(); double dt = frameStamp->getSimulationTime();
for (auto render : updateRenderList_) { for (auto render : updateRenderList_) {
render->Render(dt); render->Render(dt);

View File

@ -4,7 +4,7 @@
#include <QObject> #include <QObject>
#include <osgViewer/CompositeViewer> #include <osgViewer/Viewer>
#include <osgViewer/GraphicsWindow> #include <osgViewer/GraphicsWindow>
#include "app/Singleton.h" #include "app/Singleton.h"
@ -20,6 +20,7 @@ public:
~OsgViewer() override; ~OsgViewer() override;
void OnDestory(); void OnDestory();
osgViewer::Viewer* GetViewer(void) const;
void OnFrame(void); void OnFrame(void);
class OsgView* CreateView(int x, int y, int width, int height, void* winHandle); class OsgView* CreateView(int x, int y, int width, int height, void* winHandle);
void DestroyView(OsgView* view); void DestroyView(OsgView* view);
@ -38,12 +39,12 @@ protected:
void OnStartPlay(); void OnStartPlay();
void OnAddView(OsgView* view, int x, int y, int width, int height); //void OnAddView(OsgView* view, int x, int y, int width, int height);
void OnRemoveView(OsgView* view); //void OnRemoveView(OsgView* view);
void RenderUpdate(); void RenderUpdate();
private: private:
osg::ref_ptr<osgViewer::CompositeViewer> compositeViewer_; osg::ref_ptr<osgViewer::Viewer> viewer_;
bool initalized_{ false }; bool initalized_{ false };
using OsgViewSet = std::set<OsgView*>; using OsgViewSet = std::set<OsgView*>;

View File

@ -13,7 +13,7 @@
#include <QScreen> #include <QScreen>
#include <QWindow> #include <QWindow>
#include <osgEarth/EarthManipulator> #include <osgEarthUtil/EarthManipulator>
#include <osgEarth/Viewpoint> #include <osgEarth/Viewpoint>
#include <osgEarth/GeoMath> #include <osgEarth/GeoMath>
@ -196,108 +196,6 @@ void QtOsgViewWidget::keyReleaseEvent(QKeyEvent* event) {
view_->KeyRelease(event); view_->KeyRelease(event);
} }
void QtOsgViewWidget::OnComputeScale() {
osgEarth::MapNode* mapNode = activeScene_->GetMapNode();
if (nullptr == mapNode || nullptr == mapNode->getTerrain()) {
return;
}
dyt_check(nullptr != view_);
float x = 0.0f, y = 0.0f;
osg::Vec3d world1, world2;
if (!mapNode->getTerrain()->getWorldCoordsUnderMouse(view_->GetView(), x, y, world1)) {
emit signalScaleInfo("");
return;
}
x += devicePixelRatio_;
if (!mapNode->getTerrain()->getWorldCoordsUnderMouse(view_->GetView(), x, y, world2)) {
emit signalScaleInfo("");
return;
}
#if 0
TRACE("w1: %g %g %g w2: %g %g %g",
world1.x(), world1.y(), world1.z(),
world2.x(), world2.y(), world2.z());
#endif
double meters;
double radius = 6378137.0;
dyt_check(nullptr != g_srs_);
radius = g_srs_->getEllipsoid().getRadiusEquator();
if (!g_srs_->isGeocentric() ) {
// TRACE("Map is geographic");
// World cords are already lat/long
// Compute great circle distance
meters = osgEarth::GeoMath::distance(world1, world2, g_srs_);
} else {
osgEarth::GeoPoint mapPoint1, mapPoint2;
mapPoint1.fromWorld(g_srs_, world1);
mapPoint1.makeGeographic();
mapPoint2.fromWorld(g_srs_, world2);
mapPoint2.makeGeographic();
// Compute great circle distance
meters = osgEarth::GeoMath::distance(osg::DegreesToRadians(mapPoint1.y()),
osg::DegreesToRadians(mapPoint1.x()),
osg::DegreesToRadians(mapPoint2.y()),
osg::DegreesToRadians(mapPoint2.x()),
radius);
}
double scale = meters / devicePixelRatio_;
double pixelWidth = devicePixelRatio_ * 2.0;
// 1mi = 5280 feet
//double scaleMiles = scale / 1609.344; // International mile = 1609.344m
//double scaleNauticalMiles = scale / 1852.0; // nautical mile = 1852m
//double scaleUSSurveyMiles = scale / 1609.347218694; // US survey mile = 5280 US survey feet
//double scaleUSSurveyFeet = scale * 3937.0/1200.0; // US survey foot = 1200/3937 m
#if 0
TRACE("m: %g px: %g m/px: %g", meters, pixelWidth, scale);
#endif
switch (scaleUnits_) {
case ScaleBarHandler::Delegate::Units::UNITS_NAUTICAL_MILES: {
double nmi = meters / 1852.0;
scale = nmi / devicePixelRatio_;
nmi = normalizeScaleNauticalMiles(nmi);
pixelWidth = nmi / scale;
emit signalScaleInfo(QString("%1 nmi").arg(nmi));
} break;
case ScaleBarHandler::Delegate::Units::UNITS_US_SURVEY_FEET: {
double feet = meters * 3937.0 / 1200.0;
scale = feet / pixelWidth;
feet = normalizeScaleFeet(feet);
pixelWidth = feet / scale;
if (feet >= 5280) {
emit signalScaleInfo(QString("%1 miUS").arg(feet / 5280.0));
} else {
emit signalScaleInfo(QString("%1 ftUS").arg(feet));
}
} break;
case ScaleBarHandler::Delegate::Units::UNITS_INTL_FEET: {
double feet = 5280.0 * meters / 1609.344;
scale = feet / pixelWidth;
feet = normalizeScaleFeet(feet);
pixelWidth = feet / scale;
if (feet >= 5280) {
emit signalScaleInfo(QString("%1 mi").arg(feet / 5280.0));
} else {
emit signalScaleInfo(QString("%1 ft").arg(feet));
}
} break;
case ScaleBarHandler::Delegate::Units::UNITS_METERS:
default: {
meters = normalizeScaleMeters(meters);
pixelWidth = meters / scale;
if (meters >= 1000) {
emit signalScaleInfo(QString("%1 km").arg(meters * 0.001));
} else {
emit signalScaleInfo(QString("%1 m").arg(meters));
}
} break;
}
}
void QtOsgViewWidget::Initialize(void) { void QtOsgViewWidget::Initialize(void) {
if (view_) { if (view_) {
LOG_INFO("view is created"); LOG_INFO("view is created");
@ -314,40 +212,38 @@ void QtOsgViewWidget::Initialize(void) {
setMouseTracking(true); setMouseTracking(true);
activeScene_ = new OEScene;
activeScene_->AttachView(view_);
activeScene_->InitEventHandle(view_);
osgEarth::Util::EarthManipulator* manipulator = new osgEarth::Util::EarthManipulator;
connect(&WorkSpaceManager::Get(), &WorkSpaceManager::WorkSpaceChanged, [](WorkSpace* workspace) {
LOG_INFO("WorkSpaceChanged");
if (nullptr == workspace) {
return;
}
OsgCameraManipulator* manipulator = OsgViewer::Get().GetView()->GetCameraManipulator();
if (nullptr == manipulator) {
LOG_WARN("manipulator is nullptr");
return;
}
osgGA::CameraManipulator* gaManipulator = manipulator->GetManipulator();
osgEarth::Util::EarthManipulator* ccm = dynamic_cast<osgEarth::Util::EarthManipulator*>(gaManipulator);
if (nullptr == ccm) {
LOG_WARN("ccm is nullptr");
return;
}
ccm->setViewpoint(workspace->GetHomeViewpoint(), 3.0); //osgEarth::Util::EarthManipulator* manipulator = new osgEarth::Util::EarthManipulator;
} //connect(&WorkSpaceManager::Get(), &WorkSpaceManager::WorkSpaceChanged, [](WorkSpace* workspace) {
); // LOG_INFO("WorkSpaceChanged");
// if (nullptr == workspace) {
// return;
// }
// OsgCameraManipulator* manipulator = OsgViewer::Get().GetView()->GetCameraManipulator();
// if (nullptr == manipulator) {
// LOG_WARN("manipulator is nullptr");
// return;
// }
// osgGA::CameraManipulator* gaManipulator = manipulator->GetManipulator();
// osgEarth::Util::EarthManipulator* ccm = dynamic_cast<osgEarth::Util::EarthManipulator*>(gaManipulator);
// if (nullptr == ccm) {
// LOG_WARN("ccm is nullptr");
// return;
// }
// ccm->setViewpoint(workspace->GetHomeViewpoint(), 3.0);
// }
//);
OsgCameraManipulator* cameraManipulator = new OsgCameraManipulator(manipulator, this); //OsgCameraManipulator* cameraManipulator = new OsgCameraManipulator(manipulator, this);
view_->Initialize(cameraManipulator); //view_->Initialize(cameraManipulator);
OsgViewUI* viewUI = view_->GetViewUI(); //OsgViewUI* viewUI = view_->GetViewUI();
dyt_check(nullptr != viewUI); //dyt_check(nullptr != viewUI);
viewUI->AddUI(activeScene_->GetOrCreateSceneUI()); //viewUI->AddUI(activeScene_->GetOrCreateSceneUI());
} }
void QtOsgViewWidget::Uninitialize(void) { void QtOsgViewWidget::Uninitialize(void) {
@ -362,13 +258,13 @@ void QtOsgViewWidget::Uninitialize(void) {
} }
} }
void QtOsgViewWidget::LoadDefaultScene(void) { //void QtOsgViewWidget::LoadDefaultScene(void) {
dyt_check(nullptr != activeScene_); // dyt_check(nullptr != activeScene_);
if (nullptr == WorkSpaceManager::Get().LoadDefaultWorkspace(activeScene_)) { // if (nullptr == WorkSpaceManager::Get().LoadDefaultWorkspace(activeScene_)) {
LOG_ERROR("load default workspace failed"); // LOG_ERROR("load default workspace failed");
QMessageBox::warning(this, tr("warning"), tr("default workspace failed")); // QMessageBox::warning(this, tr("warning"), tr("default workspace failed"));
} // }
} //}
void QtOsgViewWidget::OnLoadDyt(const QString& path) { void QtOsgViewWidget::OnLoadDyt(const QString& path) {
LOG_INFO("load dyt path:{}", path.toStdString()); LOG_INFO("load dyt path:{}", path.toStdString());

View File

@ -3,9 +3,6 @@
// #include <QGLWidget> // #include <QGLWidget>
#include <QWidget> #include <QWidget>
#include "scene/OEScene.h"
#include "scene/ScaleBarHandler.h"
class QMouseEvent; class QMouseEvent;
class QWheelEvent; class QWheelEvent;
@ -13,7 +10,7 @@ class QKeyEvent;
class QInputEvent; class QInputEvent;
class QResizeEvent; class QResizeEvent;
class QtOsgViewWidget : public QWidget, public ScaleBarHandler::Delegate { class QtOsgViewWidget : public QWidget {
Q_OBJECT Q_OBJECT
public: public:
explicit QtOsgViewWidget(QWidget* parent = nullptr); explicit QtOsgViewWidget(QWidget* parent = nullptr);
@ -24,12 +21,10 @@ public:
return nullptr; return nullptr;
} }
void OnComputeScale() override;
void Initialize(void); void Initialize(void);
void Uninitialize(void); void Uninitialize(void);
void LoadDefaultScene(void); //void LoadDefaultScene(void);
void OnLoadDyt(const QString& path); void OnLoadDyt(const QString& path);
//void setKeyboardModifiers(QInputEvent* event); //void setKeyboardModifiers(QInputEvent* event);
@ -47,8 +42,6 @@ protected:
private: private:
class OsgView* view_{ nullptr }; class OsgView* view_{ nullptr };
osg::ref_ptr<OEScene> activeScene_;
class WorkSpace* workspace_{ nullptr }; class WorkSpace* workspace_{ nullptr };
ScaleBarHandler::Delegate::Units scaleUnits_{ ScaleBarHandler::Delegate::Units::UNITS_METERS };
float devicePixelRatio_{ 1.0f }; float devicePixelRatio_{ 1.0f };
}; };

101
src/viewer/ViewWidget.cpp Normal file
View File

@ -0,0 +1,101 @@
#include "viewer/ViewWidget.h"
#include <QWheelEvent>
#include <QMouseEvent>
#include <QKeyEvent>
#include <QOpenGLContext>
#include <QOpenGLFunctions>
#include <QGridLayout>
#include <QDebug>
#include <QPainter>
#include <QResizeEvent>
#include <QMessageBox>
#include <QScreen>
#include <QWindow>
#include <osgEarthUtil/EarthManipulator>
#include <osgEarth/Viewpoint>
#include <osgEarth/GeoMath>
#include <osgEarth/GLUtils>
#include "config.h"
#include "app/Application.h"
#include "common/SpdLogger.h"
#include "viewer/OsgView.h"
#include "viewer/OsgViewer.h"
#include "viewer/OsgCameraManipulator.h"
#include "viewer/CameraControlManipulator.h"
#include "viewer/OsgViewUI.h"
#include "scene/OsgScene.h"
#include "workspace/WorkSpace.h"
#include "workspace/WorkSpaceManager.h"
#include "scene/SceneContent.h"
#include "scene/ui/OESceneUI.h"
#include "ui/MainFrame.h"
ViewWidget::ViewWidget(QWidget* parent /*= nullptr*/)
: OsgViewWidget(parent) {
//osg::DisplaySettings::instance()->setNumMultiSamples(16);
//setKeyEventSetsDone(0);
//
////osg::ref_ptr<osg::Viewport> viewPort = new osg::Viewport(0, 0, width(), height());
////getCamera()->setViewport(viewPort);
//getCamera()->setProjectionMatrixAsPerspective(30.0f,
// static_cast<double>(width()) / static_cast<double>(height()), 1.0f, 10000.0f);
//getCamera()->setGraphicsContext(getGraphicsWindow());
//setRealizeOperation(new osgEarth::GL3RealizeOperation());
//setThreadingModel(osgViewer::ViewerBase::SingleThreaded);
//getCamera()->setNearFarRatio(0.0000001);
//getCamera()->setComputeNearFarMode(osg::CullSettings::COMPUTE_NEAR_FAR_USING_BOUNDING_VOLUMES);//);
}
void ViewWidget::Initialize(void) {
// OEScene* activeScene_ = new OEScene;
// activeScene_->AttachView(this);
// activeScene_->InitEventHandle(this);
// const osg::Viewport* viewport = getCamera()->getViewport();
// osg::Viewport::value_type width = viewport->width();
// osg::Viewport::value_type height = viewport->height();
// viewUI_ = new OsgViewUI(this, width, height);
// osg::Group* root = getSceneData()->asGroup();
// dyt_check(nullptr != root);
// root->addChild(viewUI_.get());
// osgEarth::Util::EarthManipulator* manipulator = new osgEarth::Util::EarthManipulator;
///* connect(&WorkSpaceManager::Get(), &WorkSpaceManager::WorkSpaceChanged, [](WorkSpace* workspace) {
// LOG_INFO("WorkSpaceChanged");
// if (nullptr == workspace) {
// return;
// }
// OsgCameraManipulator* manipulator = OsgViewer::Get().GetView()->GetCameraManipulator();
// if (nullptr == manipulator) {
// LOG_WARN("manipulator is nullptr");
// return;
// }
// osgGA::CameraManipulator* gaManipulator = manipulator->GetManipulator();
// osgEarth::Util::EarthManipulator* ccm = dynamic_cast<osgEarth::Util::EarthManipulator*>(gaManipulator);
// if (nullptr == ccm) {
// LOG_WARN("ccm is nullptr");
// return;
// }
// ccm->setViewpoint(workspace->GetHomeViewpoint(), 3.0);
// }
// );
// OsgCameraManipulator* cameraManipulator = new OsgCameraManipulator(manipulator, this);
// view_->Initialize(cameraManipulator);*/
// setCameraManipulator(manipulator);
//
// viewUI_->AddUI(activeScene_->GetOrCreateSceneUI());
}
void ViewWidget::Uninitialize(void) {
}

18
src/viewer/ViewWidget.h Normal file
View File

@ -0,0 +1,18 @@
#pragma once
#include <osgViewer/Viewer>
#include "scene/OEScene.h"
#include "viewer/OsgViewWidget.h"
class ViewWidget : public OsgViewWidget {
Q_OBJECT
public:
explicit ViewWidget(QWidget* parent = nullptr);
~ViewWidget() override = default;
void Initialize(void) override;
void Uninitialize(void) override;
};

View File

@ -12,6 +12,8 @@
#include <QScreen> #include <QScreen>
#include <QWindow> #include <QWindow>
#if 0
osgQOpenGLWidget::osgQOpenGLWidget(QWidget* parent) osgQOpenGLWidget::osgQOpenGLWidget(QWidget* parent)
: QOpenGLWidget(parent) : QOpenGLWidget(parent)
{ {
@ -221,3 +223,4 @@ void osgQOpenGLWidget::createRenderer()
qApp->screens().front(); qApp->screens().front();
m_renderer->setupOSG(width(), height(), screen->devicePixelRatio()); m_renderer->setupOSG(width(), height(), screen->devicePixelRatio());
} }
#endif

View File

@ -1,5 +1,6 @@
#ifndef OSGQOPENGLWIDGET_H #pragma once
#define OSGQOPENGLWIDGET_H
#if 0
#ifdef __APPLE__ #ifdef __APPLE__
# define __glext_h_ # define __glext_h_
@ -84,5 +85,4 @@ protected:
private: private:
}; };
#endif
#endif // OSGQOPENGLWIDGET_H

View File

@ -1,126 +0,0 @@
#include "viewer/osgQOpenGLWindow.h"
#include "viewer/OSGRenderer.h"
#include <osgViewer/Viewer>
#include <osg/GL>
#include <QApplication>
#include <QKeyEvent>
#include <QInputDialog>
#include <QLayout>
#include <QMainWindow>
#include <QScreen>
#include <QWindow>
osgQOpenGLWindow::osgQOpenGLWindow(QWidget* parent)
: QOpenGLWindow(QOpenGLWindow::NoPartialUpdate, nullptr)
{
_widget = QWidget::createWindowContainer(this);
}
osgQOpenGLWindow::~osgQOpenGLWindow()
{
}
osgViewer::Viewer* osgQOpenGLWindow::getOsgViewer()
{
return m_renderer;
}
OpenThreads::ReadWriteMutex* osgQOpenGLWindow::mutex()
{
return &_osgMutex;
}
void osgQOpenGLWindow::initializeGL()
{
// Initializes OpenGL function resolution for the current context.
initializeOpenGLFunctions();
createRenderer();
emit initialized();
}
void osgQOpenGLWindow::resizeGL(int w, int h)
{
Q_ASSERT(m_renderer);
double pixelRatio = screen()->devicePixelRatio();
m_renderer->resize(w, h, pixelRatio);
}
void osgQOpenGLWindow::paintGL()
{
OpenThreads::ScopedReadLock locker(_osgMutex);
if (_isFirstFrame) {
_isFirstFrame = false;
m_renderer->getCamera()->getGraphicsContext()->setDefaultFboId(defaultFramebufferObject());
}
m_renderer->frame();
}
void osgQOpenGLWindow::keyPressEvent(QKeyEvent* event)
{
Q_ASSERT(m_renderer);
// forward event to renderer
m_renderer->keyPressEvent(event);
}
void osgQOpenGLWindow::keyReleaseEvent(QKeyEvent* event)
{
Q_ASSERT(m_renderer);
// forward event to renderer
m_renderer->keyReleaseEvent(event);
}
void osgQOpenGLWindow::mousePressEvent(QMouseEvent* event)
{
Q_ASSERT(m_renderer);
// forward event to renderer
m_renderer->mousePressEvent(event);
}
void osgQOpenGLWindow::mouseReleaseEvent(QMouseEvent* event)
{
Q_ASSERT(m_renderer);
// forward event to renderer
m_renderer->mouseReleaseEvent(event);
}
void osgQOpenGLWindow::mouseDoubleClickEvent(QMouseEvent* event)
{
Q_ASSERT(m_renderer);
// forward event to renderer
m_renderer->mouseDoubleClickEvent(event);
}
void osgQOpenGLWindow::mouseMoveEvent(QMouseEvent* event)
{
Q_ASSERT(m_renderer);
// forward event to renderer
m_renderer->mouseMoveEvent(event);
}
void osgQOpenGLWindow::wheelEvent(QWheelEvent* event)
{
Q_ASSERT(m_renderer);
// forward event to renderer
m_renderer->wheelEvent(event);
}
void osgQOpenGLWindow::setDefaultDisplaySettings()
{
osg::DisplaySettings* ds = osg::DisplaySettings::instance().get();
ds->setNvOptimusEnablement(1);
ds->setStereo(false);
}
void osgQOpenGLWindow::createRenderer()
{
// call this before creating a View...
setDefaultDisplaySettings();
m_renderer = new OSGRenderer(this);
double pixelRatio = screen()->devicePixelRatio();
m_renderer->setupOSG(width(), height(), pixelRatio);
}

View File

@ -6,6 +6,7 @@
#include "app/Application.h" #include "app/Application.h"
#include "workspace/WorkSpace.h" #include "workspace/WorkSpace.h"
#include "viewer/OsgViewer.h"
#include "workspace/Timestep.h" #include "workspace/Timestep.h"
#include "common/SpdLogger.h" #include "common/SpdLogger.h"
@ -169,6 +170,18 @@ void WorkSpaceManager::OnFrame() {
lastTime_ = t; lastTime_ = t;
} }
void WorkSpaceManager::OnRendererLoaded() {
if (scene_) {
LOG_INFO("activeScene_ loaded");
return;
}
return;
osgViewer::Viewer* renderer = OsgViewer::Get().GetViewer();
scene_ = new OEScene;
scene_->AttachView(renderer);
scene_->InitEventHandle(renderer);
}
QString WorkSpaceManager::GetDefaultWorkSpaceName() { QString WorkSpaceManager::GetDefaultWorkSpaceName() {
#if _DEBUG #if _DEBUG
const QString iniFile = QString("%1workspace/config.ini").arg(QString(CONFIG_PATH)).arg(skin); const QString iniFile = QString("%1workspace/config.ini").arg(QString(CONFIG_PATH)).arg(skin);

View File

@ -5,7 +5,8 @@
#include <QObject> #include <QObject>
#include "app/Singleton.h" #include "app/Singleton.h"
#include "scene/OEScene.h"
#include "viewer/OSGRenderer.h"
#include "ui/chartPlot/DYTChart.h" #include "ui/chartPlot/DYTChart.h"
#include "ui/Table/targetlistwgt.h" #include "ui/Table/targetlistwgt.h"
@ -31,6 +32,8 @@ public:
void OnFrame(); void OnFrame();
void OnRendererLoaded();
signals: signals:
void WorkSpaceChanged(WorkSpace*); void WorkSpaceChanged(WorkSpace*);
@ -38,8 +41,9 @@ private:
QString GetDefaultWorkSpaceName(); QString GetDefaultWorkSpaceName();
private: private:
osg::ref_ptr<class OEScene> scene_;
osg::observer_ptr<OSGRenderer> renderer_;
std::unordered_map<QString, WorkSpace*> workSpaces_; std::unordered_map<QString, WorkSpace*> workSpaces_;
class OEScene* scene_{ nullptr };
WorkSpace* current_{ nullptr }; WorkSpace* current_{ nullptr };
int64_t lastTime_{ 0 }; int64_t lastTime_{ 0 };
}; };