Compare commits
6 Commits
main
...
new_osg_re
Author | SHA1 | Date | |
---|---|---|---|
2f52548074 | |||
ad02144014 | |||
32ed1bf037 | |||
c3bb7a8054 | |||
7effa0e8f4 | |||
7237c650a3 |
@ -9,7 +9,7 @@ SET(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
SET(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
|
||||
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)
|
||||
|
||||
message("qt VERSION " ${QT_VERSION_MAJOR})
|
||||
@ -85,8 +85,7 @@ INCLUDE_DIRECTORIES(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${Thirdparty}/spdlog/include
|
||||
${Thirdparty}/breakpad/include
|
||||
${Thirdparty}/3rdParty_x64/include
|
||||
${Thirdparty}/OpenSceneGraph-3.6.5/include
|
||||
${Thirdparty}/3rdParty/include
|
||||
${Thirdparty}/TritonSDK/PublicHeaders
|
||||
${Thirdparty}/matlab/include
|
||||
# ${Thirdparty}/Python39/include
|
||||
@ -94,8 +93,7 @@ INCLUDE_DIRECTORIES(
|
||||
|
||||
LINK_DIRECTORIES(
|
||||
${Thirdparty}/spdlog/lib
|
||||
${Thirdparty}/3rdParty_x64/lib
|
||||
${Thirdparty}/OpenSceneGraph-3.6.5/lib
|
||||
${Thirdparty}/3rdParty/lib
|
||||
${Thirdparty}/matlab/lib/win64/microsoft
|
||||
${Thirdparty}/TritonSDK/lib/vc143/x64
|
||||
# ${Thirdparty}/Python39/libs
|
||||
@ -146,6 +144,7 @@ target_link_libraries(
|
||||
${PROJECT_NAME}
|
||||
PRIVATE
|
||||
Qt${QT_VERSION_MAJOR}::Core
|
||||
Qt${QT_VERSION_MAJOR}::Gui
|
||||
Qt${QT_VERSION_MAJOR}::Widgets
|
||||
Qt${QT_VERSION_MAJOR}::Charts
|
||||
Qt${QT_VERSION_MAJOR}::DataVisualization
|
||||
@ -166,6 +165,9 @@ target_link_libraries(
|
||||
osgSim
|
||||
osgWidget
|
||||
osgEarth
|
||||
osgEarthUtil
|
||||
osgEarthAnnotation
|
||||
osgEarthTriton
|
||||
Triton-MT-DLL
|
||||
libeng
|
||||
libmx
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "CrashHandler.h"
|
||||
|
||||
#if 0
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QMessageBox>
|
||||
#include <QDir>
|
||||
@ -110,3 +112,4 @@ void TestCrash() {
|
||||
volatile int* a = (int*)(nullptr);
|
||||
*a = 1;
|
||||
}
|
||||
#endif
|
||||
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#if 0
|
||||
bool InstallCrashHandler();
|
||||
void TestCrash();
|
||||
#endif
|
||||
|
729
src/main.cpp
729
src/main.cpp
@ -1,3 +1,4 @@
|
||||
#if 0
|
||||
#include "app/Application.h"
|
||||
|
||||
#include "common/SpdLogger.h"
|
||||
@ -5,10 +6,16 @@
|
||||
#include "common/CrashHandler.h"
|
||||
|
||||
#include "ui/MainFrame.h"
|
||||
#include "viewer/OSGEnv.h"
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
SpdLogger logger("logs/log.txt", 5);
|
||||
|
||||
if (!OSGEnv::init()) {
|
||||
LOG_ERROR("OSGEnv::init() failed!");
|
||||
return 1;
|
||||
}
|
||||
|
||||
Application::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||
|
||||
Application app(argc, argv);
|
||||
@ -23,5 +30,727 @@ int main(int argc, char* argv[]) {
|
||||
mainWindow.showMaximized();
|
||||
|
||||
ret = app.exec();
|
||||
OSGEnv::destroy();
|
||||
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
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include <osg/LightSource>
|
||||
#include <osgDB/ReadFile>
|
||||
#include <osgEarth/GLUtils>
|
||||
#include <osgEarth/EarthManipulator>
|
||||
#include <osgEarthUtil/EarthManipulator>
|
||||
|
||||
#include <osgShadow/ShadowedScene>
|
||||
#include <osgShadow/ViewDependentShadowMap>
|
||||
@ -40,8 +40,12 @@ void OEScene::InitEventHandle(class OsgView* view) {
|
||||
|
||||
//view->GetView()->addEventHandler(new osgEarth::Util::EarthManipulator());
|
||||
|
||||
view->GetView()->addEventHandler(new osgViewer::HelpHandler);
|
||||
view->GetView()->addEventHandler(new osgViewer::StatsHandler);
|
||||
InitEventHandle(view->GetView());
|
||||
}
|
||||
|
||||
void OEScene::InitEventHandle(osgViewer::View* view) {
|
||||
view->addEventHandler(new osgViewer::HelpHandler);
|
||||
view->addEventHandler(new osgViewer::StatsHandler);
|
||||
}
|
||||
|
||||
void OEScene::AttachView(OsgView* view) {
|
||||
@ -50,6 +54,11 @@ void OEScene::AttachView(OsgView* view) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//AttachView(view->GetView());
|
||||
}
|
||||
|
||||
void OEScene::AttachView(osgViewer::Viewer* view) {
|
||||
earthRootNode_ = osgDB::readNodeFile("triton.earth");
|
||||
if (!earthRootNode_) {
|
||||
LOG_ERROR("read earth node(triton.earth) failed");
|
||||
@ -67,7 +76,7 @@ void OEScene::AttachView(OsgView* view) {
|
||||
dyt_check(nullptr != g_srs_);
|
||||
}
|
||||
|
||||
skyDome_ = osgEarth::SkyNode::create();
|
||||
skyDome_ = osgEarth::Util::SkyNode::create();
|
||||
if (!earthMapNode_) {
|
||||
LOG_WARN("eart map node is nullptr");
|
||||
return;
|
||||
@ -75,10 +84,10 @@ void OEScene::AttachView(OsgView* view) {
|
||||
|
||||
skyDome_->addChild(earthMapNode_);
|
||||
|
||||
osg::Node* node = view->GetView()->getSceneData();
|
||||
osg::Node* node = view->getSceneData();
|
||||
if (nullptr == node) {
|
||||
LOG_INFO("view scene data is nullptr, root valid:{}", skyDome_.valid());
|
||||
view->GetView()->setSceneData(skyDome_);
|
||||
view->setSceneData(skyDome_);
|
||||
} else {
|
||||
osg::Group* group = node->asGroup();
|
||||
if (nullptr != group) {
|
||||
@ -89,7 +98,7 @@ void OEScene::AttachView(OsgView* view) {
|
||||
}
|
||||
}
|
||||
|
||||
skyDome_->attach(view->GetView());
|
||||
skyDome_->attach(view);
|
||||
|
||||
skyDome_->setAtmosphereVisible(true);
|
||||
skyDome_->setSunVisible(true);
|
||||
@ -97,10 +106,9 @@ void OEScene::AttachView(OsgView* view) {
|
||||
skyDome_->setStarsVisible(true);
|
||||
|
||||
skyDome_->setDateTime(osgEarth::DateTime(2024, 12, 24, 3));
|
||||
skyDome_->setSimulationTimeTracksDateTime(true);
|
||||
|
||||
logarithmicDepthBuffer_->install(view->GetView()->getCamera());
|
||||
//skyDome_->setSimulationTimeTracksDateTime(true);
|
||||
|
||||
logarithmicDepthBuffer_->install(view->getCamera());
|
||||
}
|
||||
|
||||
void OEScene::DetachView(OsgView* view) {
|
||||
|
@ -4,9 +4,10 @@
|
||||
#include <osg/TextureCubeMap>
|
||||
|
||||
#include <osgText/Text>
|
||||
#include <osgEarth/ModelNode>
|
||||
#include <osgEarth/Sky>
|
||||
#include <osgEarth/LogarithmicDepthBuffer>
|
||||
#include <osgEarth/MapNode>
|
||||
#include <osgEarthUtil/Sky>
|
||||
#include <osgEarthUtil/LogarithmicDepthBuffer>
|
||||
#include <osgViewer/Viewer>
|
||||
|
||||
//#include "scene/SkyDome.h"
|
||||
|
||||
@ -20,7 +21,9 @@ class OEScene : public osg::Referenced {
|
||||
public:
|
||||
OEScene();
|
||||
void InitEventHandle(OsgView* view);
|
||||
void InitEventHandle(osgViewer::View* view);
|
||||
void AttachView(OsgView* view);
|
||||
void AttachView(osgViewer::Viewer* view);
|
||||
void DetachView(OsgView* view);
|
||||
|
||||
osg::ref_ptr<osg::TextureCubeMap> LoadCubeMapTextures(const std::string& dir);
|
||||
@ -49,7 +52,7 @@ private:
|
||||
osg::ref_ptr<osg::Node> earthRootNode_;
|
||||
osg::ref_ptr<osgEarth::MapNode> earthMapNode_;
|
||||
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_;
|
||||
osg::ref_ptr<OESceneUI> sceneUI_;
|
||||
};
|
||||
|
@ -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(); }
|
@ -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
|
@ -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
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
@ -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();
|
||||
}
|
@ -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
|
@ -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;
|
||||
}
|
@ -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
|
@ -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;
|
||||
}
|
@ -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
|
@ -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;
|
||||
}
|
@ -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
|
@ -489,143 +489,143 @@
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/MainWindow.cpp" line="114"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="115"/>
|
||||
<source>Wave Curve</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/MainWindow.cpp" line="122"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="123"/>
|
||||
<source>Speed Curve</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/MainWindow.cpp" line="131"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="132"/>
|
||||
<source>3D Curve</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/MainWindow.cpp" line="143"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="168"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="144"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="169"/>
|
||||
<source>Target number</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/MainWindow.cpp" line="143"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="168"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="144"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="169"/>
|
||||
<source>Signal-to-noise ratio</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/MainWindow.cpp" line="144"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="169"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="145"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="170"/>
|
||||
<source>Azimuth line of sight</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/MainWindow.cpp" line="144"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="169"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="145"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="170"/>
|
||||
<source>Pitch gaze angle</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/MainWindow.cpp" line="145"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="170"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="146"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="171"/>
|
||||
<source>azimuth</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/MainWindow.cpp" line="145"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="170"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="146"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="171"/>
|
||||
<source>Pitch angle</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/MainWindow.cpp" line="146"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="171"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="147"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="172"/>
|
||||
<source>attribute</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/MainWindow.cpp" line="146"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="171"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="147"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="172"/>
|
||||
<source>Doppler</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/MainWindow.cpp" line="147"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="172"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="148"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="173"/>
|
||||
<source>course</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/MainWindow.cpp" line="147"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="172"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="148"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="173"/>
|
||||
<source>Speed</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/MainWindow.cpp" line="148"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="173"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="149"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="174"/>
|
||||
<source>longitude</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/MainWindow.cpp" line="148"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="173"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="149"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="174"/>
|
||||
<source>latitude</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/MainWindow.cpp" line="149"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="174"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="150"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="175"/>
|
||||
<source>distance</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/MainWindow.cpp" line="149"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="174"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="150"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="175"/>
|
||||
<source>velocity</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/MainWindow.cpp" line="150"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="175"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="151"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="176"/>
|
||||
<source>Radial dimensions</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/MainWindow.cpp" line="150"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="175"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="151"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="176"/>
|
||||
<source>Target RCS</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/MainWindow.cpp" line="156"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="157"/>
|
||||
<source>Report Table</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/MainWindow.cpp" line="181"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="182"/>
|
||||
<source>Report</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/MainWindow.cpp" line="190"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="191"/>
|
||||
<source>Signal Indicator Lamp</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/MainWindow.cpp" line="197"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="198"/>
|
||||
<source>ParamSetting</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/MainWindow.cpp" line="202"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="203"/>
|
||||
<source>Matlab File</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/MainWindow.cpp" line="207"/>
|
||||
<location filename="../ui/MainWindow.cpp" line="208"/>
|
||||
<source>name: 5year 0412</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
@ -840,12 +840,12 @@
|
||||
<context>
|
||||
<name>QObject</name>
|
||||
<message>
|
||||
<location filename="../common/CrashHandler.cpp" line="69"/>
|
||||
<location filename="../common/CrashHandler.cpp" line="71"/>
|
||||
<source>error</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../common/CrashHandler.cpp" line="70"/>
|
||||
<location filename="../common/CrashHandler.cpp" line="72"/>
|
||||
<source>the appliaction is crash</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
@ -1254,18 +1254,12 @@
|
||||
<context>
|
||||
<name>QtOsgViewWidget</name>
|
||||
<message>
|
||||
<location filename="../viewer/QtOsgViewWidget.cpp" line="369"/>
|
||||
<location filename="../viewer/QtOsgViewWidget.cpp" line="377"/>
|
||||
<location filename="../viewer/QtOsgViewWidget.cpp" line="273"/>
|
||||
<source>warning</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../viewer/QtOsgViewWidget.cpp" line="369"/>
|
||||
<source>default workspace failed</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../viewer/QtOsgViewWidget.cpp" line="377"/>
|
||||
<location filename="../viewer/QtOsgViewWidget.cpp" line="273"/>
|
||||
<source>open dyt file failed</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
@ -1838,17 +1832,17 @@
|
||||
<context>
|
||||
<name>osgQOpenGLWidget</name>
|
||||
<message>
|
||||
<location filename="../viewer/osgQOpenGLWidget.cpp" line="104"/>
|
||||
<location filename="../viewer/osgQOpenGLWidget.cpp" line="106"/>
|
||||
<source>Screen %1</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../viewer/osgQOpenGLWidget.cpp" line="114"/>
|
||||
<location filename="../viewer/osgQOpenGLWidget.cpp" line="116"/>
|
||||
<source>Choose fullscreen target screen</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../viewer/osgQOpenGLWidget.cpp" line="114"/>
|
||||
<location filename="../viewer/osgQOpenGLWidget.cpp" line="116"/>
|
||||
<source>Screen</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
@ -113,9 +113,9 @@ void MainFrame::InitUI() {
|
||||
MainWindow* mainWindow = new MainWindow(this);
|
||||
layout->addWidget(mainWindow);
|
||||
|
||||
QtOsgViewWidget* viewWidget = mainWindow->GetViewWidget();
|
||||
/* QtOsgViewWidget* viewWidget = mainWindow->GetViewWidget();
|
||||
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);
|
||||
|
||||
|
@ -13,7 +13,8 @@
|
||||
#include "ModelBrowser.h"
|
||||
#include "DockWidget.h"
|
||||
|
||||
#include "viewer/QtOsgViewWidget.h"
|
||||
#include "viewer/ViewWidget.h"
|
||||
#include "viewer/OsgOpenGLWindow.h"
|
||||
#include "viewer/OsgViewer.h"
|
||||
|
||||
#include "chartPlot/FitCurveDialog.h"
|
||||
@ -44,7 +45,6 @@ MainWindow::MainWindow(QWidget* parent)
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow() {
|
||||
OsgViewer::Get().Uninitialize();
|
||||
delete ui;
|
||||
}
|
||||
|
||||
@ -83,8 +83,9 @@ void MainWindow::InitUI() {
|
||||
connect(modelBrowser_, &ModelBrowser::WorkSpaceChange, propertyBrowser_, &PropertyBrowser::OnWorkSpaceChange);
|
||||
connect(modelBrowser_, &ModelBrowser::EntityChange, propertyBrowser_, &PropertyBrowser::OnEntityChange);
|
||||
|
||||
qtOsgViewWidget_ = new QtOsgViewWidget;
|
||||
qtOsgViewWidget_->Initialize();
|
||||
qtOsgViewWidget_ = new ViewWidget;
|
||||
//qtOsgViewWidget_ = new OsgOpenGLWindow;
|
||||
//qtOsgViewWidget_->Initialize();
|
||||
m_mapDockWidget.insert("PropertyBrowser", attribte);
|
||||
|
||||
QString wavePath ="", speedPath = "", rdPath = "", matlabParam="";
|
||||
@ -210,9 +211,8 @@ void MainWindow::InitUI() {
|
||||
InitDockLayout();
|
||||
|
||||
//ui->viewWidget->layout()->addWidget(qtOsgViewWidget_);
|
||||
qtOsgViewWidget_->LoadDefaultScene();
|
||||
OsgViewer::Get().Initialize();
|
||||
OsgViewer::Get().OnFrame();
|
||||
//qtOsgViewWidget_->LoadDefaultScene();
|
||||
|
||||
|
||||
#if 0
|
||||
MatlabObject* mtlb = new MatlabObject;
|
||||
@ -237,8 +237,9 @@ void MainWindow::InitDockLayout() {
|
||||
tabWidget_->insertTab(i, mainWindow_, strTabName);
|
||||
if (listDocArea[0].toList().size() > 0) {
|
||||
mainWindow_->setCentralWidget(qtOsgViewWidget_);
|
||||
OsgViewer::Get().Initialize();
|
||||
OsgViewer::Get().OnFrame();
|
||||
//mainWindow_->setCentralWidget(qtOsgViewWidget_->AsWidget());
|
||||
//OsgViewer::Get().Initialize();
|
||||
//OsgViewer::Get().OnFrame();
|
||||
} else {
|
||||
mainWindow_->takeCentralWidget();
|
||||
}
|
||||
|
@ -21,9 +21,9 @@ public:
|
||||
class ModelBrowser* GetModelBrowser() const {
|
||||
return modelBrowser_;
|
||||
}
|
||||
class QtOsgViewWidget* GetViewWidget() const {
|
||||
/*class ViewWidget* GetViewWidget() const {
|
||||
return qtOsgViewWidget_;
|
||||
}
|
||||
}*/
|
||||
|
||||
class FitCurveDialog* GetFitCurveDlg() const {
|
||||
return fitCurveDlg_;
|
||||
@ -55,7 +55,8 @@ private:
|
||||
class ModelBrowser* modelBrowser_{ nullptr };
|
||||
class PropertyBrowser* propertyBrowser_{ nullptr };
|
||||
class QWebEngineView* webEngineView_{ nullptr };
|
||||
class QtOsgViewWidget* qtOsgViewWidget_{ nullptr };
|
||||
class ViewWidget* qtOsgViewWidget_{ nullptr };
|
||||
//class OsgOpenGLWindow* qtOsgViewWidget_{ nullptr };
|
||||
|
||||
class FitCurveDialog* fitCurveDlg_{ nullptr };
|
||||
class FitCurveDialog* fitYLgCurveDlg_{ nullptr };
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include <QVariant>
|
||||
#include <QMenu>
|
||||
|
||||
#include <osgEarth/EarthManipulator>
|
||||
#include <osgEarthUtil/EarthManipulator>
|
||||
|
||||
#include "common/RecourceHelper.h"
|
||||
#include "common/SpdLogger.h"
|
||||
|
@ -68,9 +68,9 @@ std::string StringUtils::ViewpointToString(const osgEarth::Viewpoint& value) {
|
||||
double latitude = location->y();
|
||||
double altitude = location->z();
|
||||
|
||||
double heading = value.heading().get();
|
||||
double pitch = value.pitch().get();
|
||||
double range = value.range().get();
|
||||
double heading = value.heading().get().getValue();
|
||||
double pitch = value.pitch().get().getValue();
|
||||
double range = value.range().get().getValue();
|
||||
|
||||
std::stringstream ss;
|
||||
ss << std::fixed << std::setprecision(6);
|
||||
|
@ -1,40 +1,377 @@
|
||||
#include "viewer/GraphicsWindowEx.h"
|
||||
|
||||
#include <QOpenGLFrameBufferObjectFormat>
|
||||
#include <QOpenGLFunctions>
|
||||
#include <QThread>
|
||||
#include <QKeyEvent>
|
||||
#include <QMouseEvent>
|
||||
#include <QWheelEvent>
|
||||
|
||||
#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)
|
||||
{
|
||||
_traits = traits;
|
||||
|
||||
init();
|
||||
: osgViewer::GraphicsWindowEmbedded(traits) {
|
||||
LOG_INFO("actor, self={}", spdlog::fmt_lib::ptr(this));
|
||||
}
|
||||
|
||||
GraphicsWindowEx::GraphicsWindowEx(int x, int y, int width, int height)
|
||||
{
|
||||
_traits = new osg::GraphicsContext::Traits();
|
||||
_traits->x = x;
|
||||
_traits->x = y;
|
||||
_traits->width = width;
|
||||
_traits->height = height;
|
||||
|
||||
init();
|
||||
: osgViewer::GraphicsWindowEmbedded(x, y, width == 0 ? 1 : width, height == 0 ? 1 : height) {
|
||||
LOG_INFO("actor, self={}", spdlog::fmt_lib::ptr(this));
|
||||
}
|
||||
|
||||
void GraphicsWindowEx::init()
|
||||
{
|
||||
if(valid())
|
||||
{
|
||||
// inject our "extended" state
|
||||
setState(new StateEx());
|
||||
getState()->setGraphicsContext(this);
|
||||
GraphicsWindowEx::~GraphicsWindowEx() {
|
||||
LOG_INFO("dctor isSharedContextSet_:{}, self={}", isSharedContextSet_, spdlog::fmt_lib::ptr(this));
|
||||
|
||||
if(_traits.valid() && _traits->sharedContext.valid())
|
||||
{
|
||||
getState()->setContextID(_traits->sharedContext->getState()->getContextID());
|
||||
incrementContextIDUsageCount(getState()->getContextID());
|
||||
}
|
||||
else
|
||||
{
|
||||
getState()->setContextID(osg::GraphicsContext::createNewContextID());
|
||||
}
|
||||
|
||||
bool GraphicsWindowEx::realizeImplementation() {
|
||||
//LOG_INFO("realizeImplementation, isRealized_:{}, self={}", isRealized_, spdlog::fmt_lib::ptr(this));
|
||||
//if (isRealized_) {
|
||||
// return true;
|
||||
//}
|
||||
|
||||
//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;
|
||||
}
|
||||
|
@ -1,18 +1,21 @@
|
||||
#ifndef GRAPHICSWINDOWEX_H
|
||||
#define GRAPHICSWINDOWEX_H
|
||||
|
||||
#include <QObject>
|
||||
#include <osgViewer/GraphicsWindow>
|
||||
|
||||
#include <QOffscreenSurface>
|
||||
#include <QOpenGLContext>
|
||||
#include <QOpenGLFramebufferObject>
|
||||
|
||||
/// Needed for mixing osg rendering with Qt 2D drawing using QPainter...
|
||||
/// See http://forum.openscenegraph.org/viewtopic.php?t=15627&view=previous
|
||||
|
||||
class GraphicsWindowEx : public osgViewer::GraphicsWindowEmbedded
|
||||
{
|
||||
class GraphicsWindowEx : public osgViewer::GraphicsWindowEmbedded {
|
||||
public:
|
||||
GraphicsWindowEx(osg::GraphicsContext::Traits* traits);
|
||||
GraphicsWindowEx(int x, int y, int width, int height);
|
||||
|
||||
void init();
|
||||
~GraphicsWindowEx() override;
|
||||
|
||||
virtual bool isSameKindAs(const osg::Object* object) const
|
||||
{
|
||||
@ -32,27 +35,55 @@ public:
|
||||
{
|
||||
return true;
|
||||
}
|
||||
virtual bool realizeImplementation()
|
||||
{
|
||||
return true;
|
||||
bool isRealizedImplementation() const override {
|
||||
return isRealized_;
|
||||
}
|
||||
virtual bool isRealizedImplementation() const
|
||||
{
|
||||
return true;
|
||||
bool realizeImplementation() override;
|
||||
bool makeCurrentImplementation() override;
|
||||
void closeImplementation() override;
|
||||
bool releaseContextImplementation() override;
|
||||
void swapBuffersImplementation() override;
|
||||
|
||||
bool SetSharedContext(QOpenGLContext* sharedContext);
|
||||
void UpdateWindowScale(float scale) {
|
||||
windowScale_ = scale;
|
||||
}
|
||||
virtual void closeImplementation() {}
|
||||
virtual bool makeCurrentImplementation()
|
||||
{
|
||||
return true;
|
||||
unsigned int GetFrameBufferId() {
|
||||
isRenderDonwn_ = true;
|
||||
return frameBufferId_;
|
||||
}
|
||||
virtual bool releaseContextImplementation()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
virtual void swapBuffersImplementation() {}
|
||||
virtual void grabFocus() {}
|
||||
virtual void grabFocusIfPointerInWindow() {}
|
||||
virtual void raiseWindow() {}
|
||||
|
||||
void ReizeWindow(int width, int height);
|
||||
|
||||
public:
|
||||
void keyPressEvent(class QKeyEvent* event);
|
||||
void keyReleaseEvent(class QKeyEvent* event);
|
||||
void mousePressEvent(class QMouseEvent* event);
|
||||
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
|
||||
|
57
src/viewer/OSGEnv.cpp
Normal file
57
src/viewer/OSGEnv.cpp
Normal 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
7
src/viewer/OSGEnv.h
Normal file
@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
class OSGEnv {
|
||||
public:
|
||||
static bool init();
|
||||
static void destroy();
|
||||
};
|
@ -15,7 +15,7 @@
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
#include "viewer/OSGRenderer.h"
|
||||
#include "viewer/osgQOpenGLWindow.h"
|
||||
#include "viewer/OsgOpenGLWindow.h"
|
||||
#include "viewer/osgQOpenGLWidget.h"
|
||||
|
||||
//#include <osgQOpenGL/CullVisitorEx>
|
||||
@ -32,481 +32,85 @@
|
||||
#include <QMouseEvent>
|
||||
#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)
|
||||
: QObject(parent), osgViewer::Viewer()
|
||||
{
|
||||
// QObject::connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit,
|
||||
// [this]()
|
||||
// {
|
||||
// _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;
|
||||
// });
|
||||
: QObject(parent), osgViewer::Viewer() {
|
||||
setThreadingModel(osgViewer::Viewer::SingleThreaded);
|
||||
connect(this, &OSGRenderer::Initialized, &WorkSpaceManager::Get(), &WorkSpaceManager::OnRendererLoaded);
|
||||
setRealizeOperation(new osgEarth::GL3RealizeOperation());
|
||||
}
|
||||
|
||||
OSGRenderer::~OSGRenderer()
|
||||
{
|
||||
}
|
||||
|
||||
void OSGRenderer::update()
|
||||
{
|
||||
osgQOpenGLWindow* osgWidgetRendered = dynamic_cast<osgQOpenGLWindow*>(parent());
|
||||
|
||||
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)
|
||||
{
|
||||
void OSGRenderer::Init(osg::GraphicsContext* gc) {
|
||||
LOG_INFO("OSGRenderer::Init {}, gc:{}", isInited_, spdlog::fmt_lib::ptr(gc));
|
||||
if (!gc) {
|
||||
return;
|
||||
}
|
||||
|
||||
// ask ViewerWidget to update 3D view
|
||||
if(getRunFrameScheme() != osgViewer::ViewerBase::ON_DEMAND ||
|
||||
checkNeedToDoFrame())
|
||||
{
|
||||
update();
|
||||
if (isInited_) {
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -18,79 +18,64 @@
|
||||
#define OSGRENDERER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QEvent>
|
||||
|
||||
#include <osgViewer/Viewer>
|
||||
|
||||
class QInputEvent;
|
||||
class QKeyEvent;
|
||||
class QMouseEvent;
|
||||
class QWheelEvent;
|
||||
namespace eveBIM
|
||||
{
|
||||
class ViewerWidget;
|
||||
#include "GraphicsWindowEx.h"
|
||||
|
||||
namespace {
|
||||
enum RenderEvent {
|
||||
INIT = QEvent::Type(QEvent::User + 1),
|
||||
RENDER,
|
||||
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
|
||||
{
|
||||
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};
|
||||
|
||||
class OSGRenderer : public QObject, public osgViewer::Viewer {
|
||||
Q_OBJECT
|
||||
|
||||
friend class eveBIM::ViewerWidget;
|
||||
|
||||
public:
|
||||
|
||||
explicit OSGRenderer(QObject* parent = nullptr);
|
||||
explicit OSGRenderer(osg::ArgumentParser* arguments, QObject* parent = nullptr);
|
||||
|
||||
~OSGRenderer() override;
|
||||
|
||||
bool continuousUpdate() const
|
||||
{
|
||||
return m_continuousUpdate;
|
||||
}
|
||||
void setContinuousUpdate(bool continuousUpdate)
|
||||
{
|
||||
m_continuousUpdate = continuousUpdate;
|
||||
}
|
||||
bool event(QEvent* event) override;
|
||||
|
||||
virtual void keyPressEvent(QKeyEvent* event);
|
||||
virtual void keyReleaseEvent(QKeyEvent* event);
|
||||
virtual void mousePressEvent(QMouseEvent* event);
|
||||
virtual void mouseReleaseEvent(QMouseEvent* event);
|
||||
virtual void mouseDoubleClickEvent(QMouseEvent* event);
|
||||
virtual void mouseMoveEvent(QMouseEvent* event);
|
||||
virtual void wheelEvent(QWheelEvent* event);
|
||||
Q_SIGNALS:
|
||||
void Initialized(OSGRenderer* viewer);
|
||||
void RenderFlush();
|
||||
|
||||
virtual void resize(int windowWidth, int windowHeight, float windowScale);
|
||||
|
||||
void setupOSG(int windowWidth, int windowHeight, float windowScale);
|
||||
|
||||
// overrided from osgViewer::Viewer
|
||||
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:
|
||||
void Init(osg::GraphicsContext* gc);
|
||||
void Resize(GraphicsWindowEx* gc, int width, int height);
|
||||
void Render();
|
||||
void Destoy();
|
||||
|
||||
private:
|
||||
bool isInited_{ false };
|
||||
};
|
||||
|
||||
#endif // OSGRENDERER_H
|
||||
|
195
src/viewer/OsgOpenGLWindow.cpp
Normal file
195
src/viewer/OsgOpenGLWindow.cpp
Normal 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();
|
||||
}
|
@ -17,7 +17,9 @@
|
||||
|
||||
#include <QOpenGLWindow>
|
||||
#include <QOpenGLFunctions>
|
||||
#include <QReadWriteLock>
|
||||
#include <QTimer>
|
||||
|
||||
#include <osg/ref_ptr>
|
||||
|
||||
class OSGRenderer;
|
||||
class QWidget;
|
||||
@ -27,50 +29,32 @@ namespace osgViewer
|
||||
class Viewer;
|
||||
}
|
||||
|
||||
class osgQOpenGLWindow : public QOpenGLWindow,
|
||||
protected QOpenGLFunctions
|
||||
{
|
||||
class OsgOpenGLWindow : public QOpenGLWindow {
|
||||
Q_OBJECT
|
||||
|
||||
protected:
|
||||
OSGRenderer* m_renderer {nullptr};
|
||||
bool _osgWantsToRenderFrame{true};
|
||||
OpenThreads::ReadWriteMutex _osgMutex;
|
||||
bool _isFirstFrame {true};
|
||||
friend class OSGRenderer;
|
||||
|
||||
QWidget* _widget = nullptr;
|
||||
|
||||
public:
|
||||
osgQOpenGLWindow(QWidget* parent = nullptr);
|
||||
virtual ~osgQOpenGLWindow();
|
||||
OsgOpenGLWindow(QWidget* parent = nullptr);
|
||||
~OsgOpenGLWindow() override;
|
||||
|
||||
/** Get osgViewer View */
|
||||
virtual osgViewer::Viewer* getOsgViewer();
|
||||
|
||||
//! get mutex
|
||||
virtual OpenThreads::ReadWriteMutex* mutex();
|
||||
|
||||
QWidget* asWidget()
|
||||
QWidget* AsWidget()
|
||||
{
|
||||
return _widget;
|
||||
return widget_;
|
||||
}
|
||||
|
||||
signals:
|
||||
void initialized();
|
||||
|
||||
protected:
|
||||
|
||||
//! call createRender. If overloaded, this method must send initialized signal at end
|
||||
void initializeGL() override;
|
||||
|
||||
void resizeGL(int w, int h) override;
|
||||
void paintUnderGL() override;
|
||||
|
||||
//! lock scene graph and call osgViewer::frame()
|
||||
void paintGL() override;
|
||||
|
||||
//! called before creating renderer
|
||||
virtual void setDefaultDisplaySettings();
|
||||
void setDefaultDisplaySettings();
|
||||
|
||||
void keyPressEvent(QKeyEvent* event) override;
|
||||
void keyReleaseEvent(QKeyEvent* event) override;
|
||||
@ -80,7 +64,19 @@ protected:
|
||||
void mouseMoveEvent(QMouseEvent* 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
|
189
src/viewer/OsgViewWidget.cpp
Normal file
189
src/viewer/OsgViewWidget.cpp
Normal 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);
|
||||
}
|
||||
|
70
src/viewer/OsgViewWidget.h
Normal file
70
src/viewer/OsgViewWidget.h
Normal 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_;
|
||||
};
|
@ -4,32 +4,26 @@
|
||||
|
||||
#include <QApplication>
|
||||
#include <osg/BlendFunc>
|
||||
#include <osgEarth/GLUtils>
|
||||
//#include <osgEarth/GLUtils>
|
||||
#include <osgDB/Registry>
|
||||
|
||||
#include "common/SpdLogger.h"
|
||||
#include "viewer/OsgView.h"
|
||||
#include "viewer/IUpdateRender.h"
|
||||
#include "workspace/WorkSpaceManager.h"
|
||||
#include <osgEarth/GLUtils>
|
||||
|
||||
template<> OsgViewer* Singleton<OsgViewer>::instance_ = nullptr;
|
||||
|
||||
constexpr QEvent::Type sOsgViewUpdateEvent{ QEvent::Type(QEvent::User + 1) };
|
||||
|
||||
OsgViewer::OsgViewer(QObject* parent) noexcept
|
||||
: QObject(parent)
|
||||
, compositeViewer_(new osgViewer::CompositeViewer) {
|
||||
: QObject(parent) {
|
||||
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() {
|
||||
compositeViewer_ = nullptr;
|
||||
viewer_ = nullptr;
|
||||
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) {
|
||||
assert(nullptr != compositeViewer_);
|
||||
assert(nullptr != viewer_);
|
||||
|
||||
WorkSpaceManager::Get().OnFrame();
|
||||
|
||||
if (IsDone()) {
|
||||
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) {
|
||||
@ -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");
|
||||
|
||||
OnAddView(view, x, y, width, height);
|
||||
//OnAddView(view, x, y, width, height);
|
||||
//compositeViewer_->setRealizeOperation(new osgEarth::GL3RealizeOperation());
|
||||
return view;
|
||||
}
|
||||
@ -69,12 +67,12 @@ void OsgViewer::DestroyView(OsgView* osgView) {
|
||||
return;
|
||||
}
|
||||
|
||||
OnRemoveView(osgView);
|
||||
//OnRemoveView(osgView);
|
||||
}
|
||||
|
||||
bool OsgViewer::IsDone() const {
|
||||
assert(nullptr != compositeViewer_);
|
||||
bool done = compositeViewer_->done();
|
||||
assert(nullptr != viewer_);
|
||||
bool done = viewer_->done();
|
||||
return !done && initalized_;
|
||||
}
|
||||
|
||||
@ -90,8 +88,15 @@ bool OsgViewer::Initialize(void) {
|
||||
if (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;
|
||||
compositeViewer_->setRealizeOperation(new osgEarth::GL3RealizeOperation());
|
||||
//compositeViewer_->setRealizeOperation(new osgEarth::GL3RealizeOperation());
|
||||
return initalized_;
|
||||
}
|
||||
|
||||
@ -137,29 +142,29 @@ void OsgViewer::customEvent(QEvent* event) {
|
||||
}
|
||||
|
||||
void OsgViewer::OnStartPlay() {
|
||||
compositeViewer_->setStartTick(0);
|
||||
viewer_->setStartTick(0);
|
||||
}
|
||||
|
||||
void OsgViewer::OnAddView(OsgView* osgView, int x, int y, int width, int height) {
|
||||
osgViewer::View* view = new osgViewer::View;
|
||||
osgView->InitView(view);
|
||||
|
||||
compositeViewer_->addView(view);
|
||||
osgViews_.insert(osgView);
|
||||
}
|
||||
|
||||
void OsgViewer::OnRemoveView(OsgView* osgView) {
|
||||
if (nullptr == osgView || nullptr == osgView->GetView()) {
|
||||
LOG_WARN("osgview is nullptr or getview is nullptr");
|
||||
return;
|
||||
}
|
||||
|
||||
osgViews_.erase(osgView);
|
||||
compositeViewer_->removeView(osgView->GetView());
|
||||
}
|
||||
//void OsgViewer::OnAddView(OsgView* osgView, int x, int y, int width, int height) {
|
||||
// osgViewer::View* view = new osgViewer::View;
|
||||
// osgView->InitView(view);
|
||||
//
|
||||
// viewer_->addView(view);
|
||||
// osgViews_.insert(osgView);
|
||||
//}
|
||||
//
|
||||
//void OsgViewer::OnRemoveView(OsgView* osgView) {
|
||||
// if (nullptr == osgView || nullptr == osgView->GetView()) {
|
||||
// LOG_WARN("osgview is nullptr or getview is nullptr");
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// osgViews_.erase(osgView);
|
||||
// compositeViewer_->removeView(osgView->GetView());
|
||||
//}
|
||||
|
||||
void OsgViewer::RenderUpdate() {
|
||||
osg::FrameStamp* frameStamp = compositeViewer_->getFrameStamp();
|
||||
osg::FrameStamp* frameStamp = viewer_->getFrameStamp();
|
||||
double dt = frameStamp->getSimulationTime();
|
||||
for (auto render : updateRenderList_) {
|
||||
render->Render(dt);
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include <osgViewer/CompositeViewer>
|
||||
#include <osgViewer/Viewer>
|
||||
#include <osgViewer/GraphicsWindow>
|
||||
|
||||
#include "app/Singleton.h"
|
||||
@ -20,6 +20,7 @@ public:
|
||||
~OsgViewer() override;
|
||||
void OnDestory();
|
||||
|
||||
osgViewer::Viewer* GetViewer(void) const;
|
||||
void OnFrame(void);
|
||||
class OsgView* CreateView(int x, int y, int width, int height, void* winHandle);
|
||||
void DestroyView(OsgView* view);
|
||||
@ -38,12 +39,12 @@ protected:
|
||||
|
||||
void OnStartPlay();
|
||||
|
||||
void OnAddView(OsgView* view, int x, int y, int width, int height);
|
||||
void OnRemoveView(OsgView* view);
|
||||
//void OnAddView(OsgView* view, int x, int y, int width, int height);
|
||||
//void OnRemoveView(OsgView* view);
|
||||
void RenderUpdate();
|
||||
|
||||
private:
|
||||
osg::ref_ptr<osgViewer::CompositeViewer> compositeViewer_;
|
||||
osg::ref_ptr<osgViewer::Viewer> viewer_;
|
||||
bool initalized_{ false };
|
||||
|
||||
using OsgViewSet = std::set<OsgView*>;
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include <QScreen>
|
||||
#include <QWindow>
|
||||
|
||||
#include <osgEarth/EarthManipulator>
|
||||
#include <osgEarthUtil/EarthManipulator>
|
||||
#include <osgEarth/Viewpoint>
|
||||
#include <osgEarth/GeoMath>
|
||||
|
||||
@ -196,108 +196,6 @@ void QtOsgViewWidget::keyReleaseEvent(QKeyEvent* 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) {
|
||||
if (view_) {
|
||||
LOG_INFO("view is created");
|
||||
@ -314,40 +212,38 @@ void QtOsgViewWidget::Initialize(void) {
|
||||
|
||||
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);
|
||||
view_->Initialize(cameraManipulator);
|
||||
//OsgCameraManipulator* cameraManipulator = new OsgCameraManipulator(manipulator, this);
|
||||
//view_->Initialize(cameraManipulator);
|
||||
|
||||
OsgViewUI* viewUI = view_->GetViewUI();
|
||||
dyt_check(nullptr != viewUI);
|
||||
viewUI->AddUI(activeScene_->GetOrCreateSceneUI());
|
||||
//OsgViewUI* viewUI = view_->GetViewUI();
|
||||
//dyt_check(nullptr != viewUI);
|
||||
//viewUI->AddUI(activeScene_->GetOrCreateSceneUI());
|
||||
}
|
||||
|
||||
void QtOsgViewWidget::Uninitialize(void) {
|
||||
@ -362,13 +258,13 @@ void QtOsgViewWidget::Uninitialize(void) {
|
||||
}
|
||||
}
|
||||
|
||||
void QtOsgViewWidget::LoadDefaultScene(void) {
|
||||
dyt_check(nullptr != activeScene_);
|
||||
if (nullptr == WorkSpaceManager::Get().LoadDefaultWorkspace(activeScene_)) {
|
||||
LOG_ERROR("load default workspace failed");
|
||||
QMessageBox::warning(this, tr("warning"), tr("default workspace failed"));
|
||||
}
|
||||
}
|
||||
//void QtOsgViewWidget::LoadDefaultScene(void) {
|
||||
// dyt_check(nullptr != activeScene_);
|
||||
// if (nullptr == WorkSpaceManager::Get().LoadDefaultWorkspace(activeScene_)) {
|
||||
// LOG_ERROR("load default workspace failed");
|
||||
// QMessageBox::warning(this, tr("warning"), tr("default workspace failed"));
|
||||
// }
|
||||
//}
|
||||
|
||||
void QtOsgViewWidget::OnLoadDyt(const QString& path) {
|
||||
LOG_INFO("load dyt path:{}", path.toStdString());
|
||||
|
@ -3,9 +3,6 @@
|
||||
// #include <QGLWidget>
|
||||
#include <QWidget>
|
||||
|
||||
#include "scene/OEScene.h"
|
||||
#include "scene/ScaleBarHandler.h"
|
||||
|
||||
|
||||
class QMouseEvent;
|
||||
class QWheelEvent;
|
||||
@ -13,7 +10,7 @@ class QKeyEvent;
|
||||
class QInputEvent;
|
||||
class QResizeEvent;
|
||||
|
||||
class QtOsgViewWidget : public QWidget, public ScaleBarHandler::Delegate {
|
||||
class QtOsgViewWidget : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit QtOsgViewWidget(QWidget* parent = nullptr);
|
||||
@ -24,12 +21,10 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void OnComputeScale() override;
|
||||
|
||||
void Initialize(void);
|
||||
void Uninitialize(void);
|
||||
|
||||
void LoadDefaultScene(void);
|
||||
//void LoadDefaultScene(void);
|
||||
|
||||
void OnLoadDyt(const QString& path);
|
||||
//void setKeyboardModifiers(QInputEvent* event);
|
||||
@ -47,8 +42,6 @@ protected:
|
||||
|
||||
private:
|
||||
class OsgView* view_{ nullptr };
|
||||
osg::ref_ptr<OEScene> activeScene_;
|
||||
class WorkSpace* workspace_{ nullptr };
|
||||
ScaleBarHandler::Delegate::Units scaleUnits_{ ScaleBarHandler::Delegate::Units::UNITS_METERS };
|
||||
float devicePixelRatio_{ 1.0f };
|
||||
};
|
101
src/viewer/ViewWidget.cpp
Normal file
101
src/viewer/ViewWidget.cpp
Normal 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
18
src/viewer/ViewWidget.h
Normal 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;
|
||||
|
||||
};
|
@ -12,6 +12,8 @@
|
||||
#include <QScreen>
|
||||
#include <QWindow>
|
||||
|
||||
#if 0
|
||||
|
||||
osgQOpenGLWidget::osgQOpenGLWidget(QWidget* parent)
|
||||
: QOpenGLWidget(parent)
|
||||
{
|
||||
@ -221,3 +223,4 @@ void osgQOpenGLWidget::createRenderer()
|
||||
qApp->screens().front();
|
||||
m_renderer->setupOSG(width(), height(), screen->devicePixelRatio());
|
||||
}
|
||||
#endif
|
@ -1,5 +1,6 @@
|
||||
#ifndef OSGQOPENGLWIDGET_H
|
||||
#define OSGQOPENGLWIDGET_H
|
||||
#pragma once
|
||||
|
||||
#if 0
|
||||
|
||||
#ifdef __APPLE__
|
||||
# define __glext_h_
|
||||
@ -84,5 +85,4 @@ protected:
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
#endif // OSGQOPENGLWIDGET_H
|
||||
#endif
|
||||
|
@ -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);
|
||||
}
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include "app/Application.h"
|
||||
#include "workspace/WorkSpace.h"
|
||||
#include "viewer/OsgViewer.h"
|
||||
#include "workspace/Timestep.h"
|
||||
#include "common/SpdLogger.h"
|
||||
|
||||
@ -169,6 +170,18 @@ void WorkSpaceManager::OnFrame() {
|
||||
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() {
|
||||
#if _DEBUG
|
||||
const QString iniFile = QString("%1workspace/config.ini").arg(QString(CONFIG_PATH)).arg(skin);
|
||||
|
@ -5,7 +5,8 @@
|
||||
#include <QObject>
|
||||
|
||||
#include "app/Singleton.h"
|
||||
|
||||
#include "scene/OEScene.h"
|
||||
#include "viewer/OSGRenderer.h"
|
||||
#include "ui/chartPlot/DYTChart.h"
|
||||
#include "ui/Table/targetlistwgt.h"
|
||||
|
||||
@ -31,6 +32,8 @@ public:
|
||||
|
||||
void OnFrame();
|
||||
|
||||
void OnRendererLoaded();
|
||||
|
||||
signals:
|
||||
void WorkSpaceChanged(WorkSpace*);
|
||||
|
||||
@ -38,8 +41,9 @@ private:
|
||||
QString GetDefaultWorkSpaceName();
|
||||
|
||||
private:
|
||||
osg::ref_ptr<class OEScene> scene_;
|
||||
osg::observer_ptr<OSGRenderer> renderer_;
|
||||
std::unordered_map<QString, WorkSpace*> workSpaces_;
|
||||
class OEScene* scene_{ nullptr };
|
||||
WorkSpace* current_{ nullptr };
|
||||
int64_t lastTime_{ 0 };
|
||||
};
|
Loading…
Reference in New Issue
Block a user