Compare commits
123 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5204e3be10 | |||
| c1337ffe49 | |||
| d74a02e0c4 | |||
| afe42180ce | |||
| 0776e0aa07 | |||
| 8c03d98849 | |||
| a6d8351546 | |||
| c840f4ff3f | |||
| 4bfd45d287 | |||
| 51a7bbf301 | |||
| 6040a3f698 | |||
| 06a91d4cf1 | |||
| f65ea8dcd8 | |||
| 6617e2f46e | |||
| 7a0a0b7495 | |||
| 0b5fa3746a | |||
| 630552b156 | |||
| 7597087fb7 | |||
| e3117d6687 | |||
| 596d60f6bc | |||
| 5c5143e6c2 | |||
| 743565fd75 | |||
| 9df23631c8 | |||
| 00b9093481 | |||
| 0fb6395f06 | |||
| 0ad5e59955 | |||
| 885212c7d2 | |||
| 96e1eb328f | |||
| 7d336212ea | |||
| 1014d934f9 | |||
| 02b47acb1b | |||
| b7e775ef33 | |||
| ff5e3e74ad | |||
| eea7b2a3ee | |||
| 06697b4476 | |||
| 87c2f23446 | |||
| cedda254e5 | |||
| 843d2cf158 | |||
| 863e0867ce | |||
| fafd290244 | |||
| 7de04d4c34 | |||
| c2c88b4ebc | |||
| 1ac2c4d797 | |||
| 42fd885400 | |||
| 06358b4bca | |||
| bee7b6f8ec | |||
| d734d33e0a | |||
| 02ad3dbe4b | |||
| 707c02e8a0 | |||
| 52769cb830 | |||
| 87091abf12 | |||
| 18963d4dea | |||
| e693562387 | |||
| b79754b443 | |||
| 1e7538796a | |||
| 8c0f345454 | |||
| 05d2968d41 | |||
| 71444e3a41 | |||
| bbb9323e09 | |||
| 6fb3bd9c59 | |||
| 32eaf74017 | |||
| db7e71e44a | |||
| e69d916779 | |||
| 2240f02a62 | |||
| 1eb367d265 | |||
| 963fe4fa76 | |||
| dc83646fab | |||
| e6b2472203 | |||
| 962d72bde9 | |||
| 5c41cf02cd | |||
| 5bafe0d383 | |||
| c3f7978df9 | |||
| cc471e30a4 | |||
| 387792620a | |||
| 06efe914f7 | |||
| 51d84229da | |||
| ddd69461dd | |||
| 252db1fc9f | |||
| c638cbbe19 | |||
| 0e8d2aaf7d | |||
| bfd45c3a4a | |||
| 209d3efe02 | |||
| 8aa83b7a5f | |||
| 36d99e8762 | |||
| 32748eb36a | |||
| 36667bb144 | |||
| fc4dd95e72 | |||
| d2627b1527 | |||
| 37b0259579 | |||
| cdb7894e64 | |||
| 8f0a32869e | |||
| 63eeca0086 | |||
| 57f8c1b6af | |||
| 69caff5ce7 | |||
| cf189a7600 | |||
| eba320eaeb | |||
| 9cf724588a | |||
| 0f6d6e3a72 | |||
| 17449baf1e | |||
| 13345128f5 | |||
| a88557220b | |||
| 09767ecdbd | |||
| 1d7ba7c418 | |||
| 8d957bbbb2 | |||
| 22ae2a57d2 | |||
| 52c20bd297 | |||
| e271e78200 | |||
| d2a724bde6 | |||
| 2e8a12ba34 | |||
| 36ba2b1009 | |||
| da535ac8c3 | |||
| 474e853f2e | |||
| cee15ff862 | |||
| b6a60713e9 | |||
| 43a30fefe3 | |||
| 8bbf971540 | |||
| 286a48a658 | |||
| a3fc986d4e | |||
| 4acbf05ae0 | |||
| 8a15b09464 | |||
| 65cbe121bf | |||
| 9b47b518d5 | |||
| ea260fcaaa |
5
.gitignore
vendored
@ -2,3 +2,8 @@
|
|||||||
build/
|
build/
|
||||||
bin/
|
bin/
|
||||||
thirdparty/
|
thirdparty/
|
||||||
|
tritoin/
|
||||||
|
CMakeFiles/
|
||||||
|
logs/
|
||||||
|
QWEN.md
|
||||||
|
CMakeCache.txt
|
||||||
|
|||||||
BIN
doc/dyttu.docx
Normal file
@ -1,6 +1,7 @@
|
|||||||
1.参数编辑时候崩溃bug。参数编辑窗口,添加,点击参数名称,在蓝色状态时候点击字母按键会崩溃。后续进行过某些操作就不会崩溃了。
|
1.参数编辑时候崩溃bug。参数编辑窗口,添加,点击参数名称,在蓝色状态时候点击字母按键会崩溃。后续进行过某些操作就不会崩溃了。
|
||||||
解决方案
|
解决方案
|
||||||
a、修改当前的crash(解决)
|
a、修改当前的crash(解决)
|
||||||
|
b、参数编辑关闭之后无法再次打开
|
||||||
2.参数编辑,第一次生成matlabparam还是在workspace下,后续生成在release下,simmatlab文件需要保存在release下才能运行。参数文件和运行的.m文件路径需要统一
|
2.参数编辑,第一次生成matlabparam还是在workspace下,后续生成在release下,simmatlab文件需要保存在release下才能运行。参数文件和运行的.m文件路径需要统一
|
||||||
解决方案
|
解决方案
|
||||||
a、放到想定空间所在的目录
|
a、放到想定空间所在的目录
|
||||||
@ -8,7 +9,7 @@
|
|||||||
3.窗口1的Report和窗口2的Report Table 展示的是不是同样的内容,如果是可以删除一个。需要在窗口1或2看的report时候通过窗口管理拖动实现。
|
3.窗口1的Report和窗口2的Report Table 展示的是不是同样的内容,如果是可以删除一个。需要在窗口1或2看的report时候通过窗口管理拖动实现。
|
||||||
解决方案
|
解决方案
|
||||||
a、保留窗口2的Report Table (解决)
|
a、保留窗口2的Report Table (解决)
|
||||||
b、窗口2中的Report Table, 可以拖动变成dock模式添加到其他的窗口中
|
b、窗口2中的Report Table, 可以拖动变成dock模式添加到其他的窗口中(暂定)
|
||||||
c、有缩放属性的控件,鼠标都显示为双箭头 (解决)
|
c、有缩放属性的控件,鼠标都显示为双箭头 (解决)
|
||||||
d、所有的窗口表头可以采用拖动的形式调整列的位置 (解决)
|
d、所有的窗口表头可以采用拖动的形式调整列的位置 (解决)
|
||||||
|
|
||||||
@ -16,6 +17,7 @@
|
|||||||
功能控制一样的:窗口管理和ui设置都是控制界面的放到同一个栏目
|
功能控制一样的:窗口管理和ui设置都是控制界面的放到同一个栏目
|
||||||
解决方案
|
解决方案
|
||||||
a、窗口管理放到系统管理里面,点击按钮,弹出菜单可以勾选 (解决)
|
a、窗口管理放到系统管理里面,点击按钮,弹出菜单可以勾选 (解决)
|
||||||
|
b、仿真管理-》参数编辑-》仿真。参数编辑的窗口下面的添加,删除,应用(暂定)
|
||||||
|
|
||||||
操作步骤连续的:①参数编辑②MatlabParam文件关联③SimMatlab关联④运行.m文件。这些放到一块方便操作
|
操作步骤连续的:①参数编辑②MatlabParam文件关联③SimMatlab关联④运行.m文件。这些放到一块方便操作
|
||||||
解决方案
|
解决方案
|
||||||
|
|||||||
26
doc/交互设计.md
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# 交互设计
|
||||||
|
## 拖拽式添加实体
|
||||||
|
## 图表数据格式
|
||||||
|
### WAVE图表
|
||||||
|
按照一个文件多个曲线来,一行一个曲线
|
||||||
|
|
||||||
|
|
||||||
|
曲线、曲面每一个类型一个tab页面 最大可以显示9宫格
|
||||||
|
|
||||||
|
表格、灯 灯在上方,表格在下方(待定)
|
||||||
|
|
||||||
|
## 菜单
|
||||||
|
### 文件
|
||||||
|
* 新建wordspace
|
||||||
|
* 打开wordspace
|
||||||
|
* 保存wordspace
|
||||||
|
----
|
||||||
|
* 新建曲线
|
||||||
|
* 新建曲面
|
||||||
|
* 新建表格
|
||||||
|
* 新建灯
|
||||||
|
|
||||||
|
### 仿真管理
|
||||||
|
* 命令运行(手动编辑xml: <commond "delfeile" exe="cmd.exe" path="d:/1.bat"/>)
|
||||||
|
* 参数编辑:弹出编辑框
|
||||||
|
|
||||||
BIN
doc/流程图.vsdx
Normal file
15
doc/预设实体清单.txt
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
船:
|
||||||
|
驱逐机(阿利伯克)、航母(尼米兹)
|
||||||
|
|
||||||
|
卫星:
|
||||||
|
高轨(静止)
|
||||||
|
|
||||||
|
弹:
|
||||||
|
高超音速弹(DF21)
|
||||||
|
|
||||||
|
无源干扰:
|
||||||
|
角反、箔条
|
||||||
|
|
||||||
|
有源干扰:
|
||||||
|
弦内、弦外
|
||||||
|
|
||||||
@ -4,7 +4,7 @@ set(CMAKE_AUTOUIC ON)
|
|||||||
set(CMAKE_AUTOMOC ON)
|
set(CMAKE_AUTOMOC ON)
|
||||||
set(CMAKE_AUTORCC ON)
|
set(CMAKE_AUTORCC ON)
|
||||||
|
|
||||||
SET(CMAKE_CXX_STANDARD 17)
|
SET(CMAKE_CXX_STANDARD 11)
|
||||||
SET(CMAKE_CXX_STANDARD_REQUIRED ON)
|
SET(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
SET(CMAKE_INCLUDE_CURRENT_DIR ON)
|
SET(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||||
|
|
||||||
@ -14,8 +14,8 @@ find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Widgets LinguistTools DataVis
|
|||||||
|
|
||||||
message("qt VERSION " ${QT_VERSION_MAJOR})
|
message("qt VERSION " ${QT_VERSION_MAJOR})
|
||||||
|
|
||||||
FILE(GLOB_RECURSE HEADER_FILES ./*.h common/*.h common/*.hpp model/*.h app/*.h)
|
FILE(GLOB_RECURSE HEADER_FILES ./*.h common/*.h common/*.hpp model/*.h app/*.h utils/*.h)
|
||||||
FILE(GLOB_RECURSE CPP_FILES ./*.cpp common/*.cpp model/*.cpp app/*.cpp)
|
FILE(GLOB_RECURSE CPP_FILES ./*.cpp common/*.cpp model/*.cpp app/*.cpp utils/*.cpp)
|
||||||
FILE(GLOB_RECURSE CC_FILES ./*.cc)
|
FILE(GLOB_RECURSE CC_FILES ./*.cc)
|
||||||
FILE(GLOB_RECURSE UI_FILES ./*.ui)
|
FILE(GLOB_RECURSE UI_FILES ./*.ui)
|
||||||
FILE(GLOB_RECURSE QRC_FILES ./*.qrc)
|
FILE(GLOB_RECURSE QRC_FILES ./*.qrc)
|
||||||
@ -25,11 +25,27 @@ SET(
|
|||||||
TS_FILES
|
TS_FILES
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/translations/Dyt_zh_CN.ts
|
${CMAKE_CURRENT_SOURCE_DIR}/translations/Dyt_zh_CN.ts
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# 控制是否在构建时自动运行 lupdate 更新 TS 文件。
|
||||||
|
# 关闭时仅在 TS 变更后编译生成 QM,避免每次构建都重新创建翻译文件。
|
||||||
|
option(UPDATE_TRANSLATIONS "Run lupdate to refresh TS files during build" OFF)
|
||||||
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
|
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
|
||||||
qt6_create_translation(QM_FILES ${CMAKE_CURRENT_SOURCE_DIR} ${TS_FILES})
|
if(UPDATE_TRANSLATIONS)
|
||||||
|
# 运行 lupdate + lrelease:更新 TS 并生成 QM(可能导致每次构建都触发)
|
||||||
|
qt6_create_translation(QM_FILES ${CMAKE_CURRENT_SOURCE_DIR} ${TS_FILES})
|
||||||
|
else()
|
||||||
|
# 仅生成 QM,TS 未变化时不重新创建
|
||||||
|
qt_add_translations(QM_FILES TS_FILES ${TS_FILES})
|
||||||
|
endif()
|
||||||
add_custom_target(translations DEPENDS ${QM_FILES})
|
add_custom_target(translations DEPENDS ${QM_FILES})
|
||||||
else()
|
else()
|
||||||
qt5_create_translation(QM_FILES ${CMAKE_CURRENT_SOURCE_DIR} ${TS_FILES})
|
if(UPDATE_TRANSLATIONS)
|
||||||
|
# 运行 lupdate + lrelease
|
||||||
|
qt5_create_translation(QM_FILES ${CMAKE_CURRENT_SOURCE_DIR} ${TS_FILES})
|
||||||
|
else()
|
||||||
|
# 仅运行 lrelease 生成 QM
|
||||||
|
qt5_add_translation(QM_FILES ${TS_FILES})
|
||||||
|
endif()
|
||||||
add_custom_target(translations DEPENDS ${QM_FILES})
|
add_custom_target(translations DEPENDS ${QM_FILES})
|
||||||
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS WinExtras REQUIRED)
|
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS WinExtras REQUIRED)
|
||||||
endif()
|
endif()
|
||||||
@ -85,8 +101,9 @@ INCLUDE_DIRECTORIES(
|
|||||||
${CMAKE_CURRENT_SOURCE_DIR}
|
${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
${Thirdparty}/spdlog/include
|
${Thirdparty}/spdlog/include
|
||||||
${Thirdparty}/breakpad/include
|
${Thirdparty}/breakpad/include
|
||||||
${Thirdparty}/3rdParty_x64/include
|
${Thirdparty}/3rdparty_vc15/include
|
||||||
${Thirdparty}/OpenSceneGraph-3.6.5/include
|
${Thirdparty}/OSG-3.5.1/include
|
||||||
|
${Thirdparty}/OSGEARTH-2.8/include
|
||||||
${Thirdparty}/TritonSDK/PublicHeaders
|
${Thirdparty}/TritonSDK/PublicHeaders
|
||||||
${Thirdparty}/matlab/include
|
${Thirdparty}/matlab/include
|
||||||
# ${Thirdparty}/Python39/include
|
# ${Thirdparty}/Python39/include
|
||||||
@ -94,8 +111,9 @@ INCLUDE_DIRECTORIES(
|
|||||||
|
|
||||||
LINK_DIRECTORIES(
|
LINK_DIRECTORIES(
|
||||||
${Thirdparty}/spdlog/lib
|
${Thirdparty}/spdlog/lib
|
||||||
${Thirdparty}/3rdParty_x64/lib
|
${Thirdparty}/3rdparty_vc15/lib
|
||||||
${Thirdparty}/OpenSceneGraph-3.6.5/lib
|
${Thirdparty}/OSG-3.5.1/lib
|
||||||
|
${Thirdparty}/OSGEARTH-2.8/lib
|
||||||
${Thirdparty}/matlab/lib/win64/microsoft
|
${Thirdparty}/matlab/lib/win64/microsoft
|
||||||
${Thirdparty}/TritonSDK/lib/vc143/x64
|
${Thirdparty}/TritonSDK/lib/vc143/x64
|
||||||
# ${Thirdparty}/Python39/libs
|
# ${Thirdparty}/Python39/libs
|
||||||
@ -167,6 +185,7 @@ target_link_libraries(
|
|||||||
osgWidget
|
osgWidget
|
||||||
osgText
|
osgText
|
||||||
osgEarth
|
osgEarth
|
||||||
|
osgEarthUtil
|
||||||
Triton-MT-DLL
|
Triton-MT-DLL
|
||||||
libeng
|
libeng
|
||||||
libmx
|
libmx
|
||||||
|
|||||||
61
src/Dyt.qrc
@ -1,34 +1,47 @@
|
|||||||
<RCC>
|
<RCC>
|
||||||
<qresource prefix="/">
|
<qresource prefix="/">
|
||||||
<file>res/sys_close.png</file>
|
<file>res/sys_close.png</file>
|
||||||
|
<file>res/sys_float.png</file>
|
||||||
<file>res/sys_max.png</file>
|
<file>res/sys_max.png</file>
|
||||||
<file>res/sys_min.png</file>
|
<file>res/sys_min.png</file>
|
||||||
<file>res/sys_restore.png</file>
|
<file>res/sys_restore.png</file>
|
||||||
<file>res/sys_icon.png</file>
|
<file>res/sys_icon.png</file>
|
||||||
<file>res/sys_down.png</file>
|
<file>res/sys_down.png</file>
|
||||||
<file>res/sys_up.png</file>
|
<file>res/sys_up.png</file>
|
||||||
<file>res/select_file.ico</file>
|
<file>res/select_file.ico</file>
|
||||||
<file>res/default/menu_new_file.png</file>
|
<file>res/default/menu_new_file.png</file>
|
||||||
<file>res/default/menu_open_file.png</file>
|
<file>res/default/menu_open_file.png</file>
|
||||||
<file>res/default/menu_save_file.png</file>
|
<file>res/default/menu_save_file.png</file>
|
||||||
<file>res/default/menu_save_as_file.png</file>
|
<file>res/default/menu_wave_file.png</file>
|
||||||
<file>res/default/menu_save_shape_file.png</file>
|
<file>res/default/menu_light_file.png</file>
|
||||||
<file>res/default/menu_save_store_file.png</file>
|
<file>res/default/menu_table_file.png</file>
|
||||||
<file>res/default/menu_report_mesh.png</file>
|
<file>res/default/menu_surface_file.png</file>
|
||||||
<file>res/default/menu_exit.png</file>
|
<file>res/default/menu_save_shape_file.png</file>
|
||||||
<file>res/default/menu_helper.png</file>
|
<file>res/default/menu_save_store_file.png</file>
|
||||||
<file>res/default/menu_license.png</file>
|
<file>res/default/menu_report_mesh.png</file>
|
||||||
<file>res/default/menu_logs.png</file>
|
<file>res/default/menu_exit.png</file>
|
||||||
<file>res/default/menu_logs_clean.png</file>
|
<file>res/default/menu_helper.png</file>
|
||||||
<file>res/default/menu_restart.png</file>
|
<file>res/default/menu_license.png</file>
|
||||||
<file>res/default/menu_setting_restore.png</file>
|
<file>res/default/menu_logs.png</file>
|
||||||
<file>res/default/menu_setting.png</file>
|
<file>res/default/menu_logs_clean.png</file>
|
||||||
<file>res/default/menu_uisetting.png</file>
|
<file>res/default/menu_restart.png</file>
|
||||||
<file>res/default/menu_window_manager.png</file>
|
<file>res/default/menu_setting_restore.png</file>
|
||||||
|
<file>res/default/menu_setting.png</file>
|
||||||
|
<file>res/default/menu_uisetting.png</file>
|
||||||
|
<file>res/default/menu_window_manager.png</file>
|
||||||
|
<file>res/default/menu_window_setting.png</file>
|
||||||
|
<file>res/default/Command.png</file>
|
||||||
|
<file>res/default/polar.png</file>
|
||||||
|
<file>res/models/aircraft_carrier.png</file>
|
||||||
|
<file>res/models/chaff_interference.png</file>
|
||||||
|
<file>res/models/missile.png</file>
|
||||||
|
<file>res/models/radar_jamming_station.png</file>
|
||||||
|
<file>res/models/satellite.png</file>
|
||||||
|
<file>res/models/warships.png</file>
|
||||||
|
<file>res/default/menu_image_file.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
<qresource prefix="/qss">
|
<qresource prefix="/qss"/>
|
||||||
|
<qresource prefix="/fonts">
|
||||||
|
<file>res/fonts/fontawesome-webfont.ttf</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
<qresource prefix="/fonts">
|
|
||||||
<file>res/fonts/fontawesome-webfont.ttf</file>
|
|
||||||
</qresource>
|
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|||||||
@ -3,8 +3,10 @@
|
|||||||
#include "common/RecourceHelper.h"
|
#include "common/RecourceHelper.h"
|
||||||
#include "workspace/WorkSpaceManager.h"
|
#include "workspace/WorkSpaceManager.h"
|
||||||
#include "entities/EntitiesManager.h"
|
#include "entities/EntitiesManager.h"
|
||||||
|
#include "entities/EntityFactory.h"
|
||||||
#include "viewer/OsgViewer.h"
|
#include "viewer/OsgViewer.h"
|
||||||
#include "scene/MeshManager.h"
|
#include "scene/MeshManager.h"
|
||||||
|
#include "workspace/PresetModelConfigParser.h"
|
||||||
#include "network/NetDriver.h"
|
#include "network/NetDriver.h"
|
||||||
#include "python/PythonModule.h"
|
#include "python/PythonModule.h"
|
||||||
|
|
||||||
@ -16,7 +18,6 @@ Application::Application(int& argc, char** argv, int /*= ApplicationFlags*/)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Application::~Application() {
|
Application::~Application() {
|
||||||
Uninit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Application::GetWorkSpacePath() {
|
QString Application::GetWorkSpacePath() {
|
||||||
@ -24,22 +25,35 @@ QString Application::GetWorkSpacePath() {
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString Application::GetBinPath() {
|
||||||
|
return applicationDirPath();
|
||||||
|
}
|
||||||
|
|
||||||
void Application::Init() {
|
void Application::Init() {
|
||||||
Singleton<MeshManager>::Create(this);
|
Singleton<MeshManager>::Create(this);
|
||||||
Singleton<OsgViewer>::Create(this);
|
|
||||||
Singleton<RecourceHelper>::Create(this);
|
Singleton<RecourceHelper>::Create(this);
|
||||||
|
Singleton<EntityFactory>::Create(this);
|
||||||
Singleton<EntitiesManager>::Create(this);
|
Singleton<EntitiesManager>::Create(this);
|
||||||
Singleton<WorkSpaceManager>::Create(this);
|
Singleton<WorkSpaceManager>::Create(this);
|
||||||
Singleton<NetDriver>::Create(this);
|
Singleton<NetDriver>::Create(this);
|
||||||
|
Singleton<PresetModelConfigParser>::Create(this);
|
||||||
//Singleton<PythonModule>::Create(this);
|
//Singleton<PythonModule>::Create(this);
|
||||||
|
|
||||||
|
connect(&timer_, &QTimer::timeout, this, &Application::OnTimeout);
|
||||||
|
timer_.start(1000 / 60); // 60 FPS
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::OnTimeout() {
|
||||||
|
WorkSpaceManager::Get().OnFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::Uninit() {
|
void Application::Uninit() {
|
||||||
//Singleton<PythonModule>::Destory();
|
//Singleton<PythonModule>::Destory();
|
||||||
Singleton<NetDriver>::Destory();
|
Singleton<NetDriver>::Destory();
|
||||||
|
Singleton<PresetModelConfigParser>::Destory();
|
||||||
Singleton<WorkSpaceManager>::Destory();
|
Singleton<WorkSpaceManager>::Destory();
|
||||||
Singleton<EntitiesManager>::Destory();
|
Singleton<EntitiesManager>::Destory();
|
||||||
|
Singleton<EntityFactory>::Destory();
|
||||||
Singleton<RecourceHelper>::Destory();
|
Singleton<RecourceHelper>::Destory();
|
||||||
Singleton<OsgViewer>::Destory();
|
|
||||||
Singleton<MeshManager>::Destory();
|
Singleton<MeshManager>::Destory();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
class Application : public QApplication {
|
class Application : public QApplication {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
@ -10,8 +12,14 @@ public:
|
|||||||
~Application() override;
|
~Application() override;
|
||||||
|
|
||||||
static QString GetWorkSpacePath();
|
static QString GetWorkSpacePath();
|
||||||
|
static QString GetBinPath();
|
||||||
|
void Uninit();
|
||||||
protected:
|
protected:
|
||||||
void Init();
|
void Init();
|
||||||
void Uninit();
|
|
||||||
|
private:
|
||||||
|
void OnTimeout();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QTimer timer_;
|
||||||
};
|
};
|
||||||
@ -1,5 +1,6 @@
|
|||||||
#include "CrashHandler.h"
|
#include "CrashHandler.h"
|
||||||
|
|
||||||
|
#if 0
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
@ -79,7 +80,6 @@ std::unique_ptr<google_breakpad::ExceptionHandler> exceptionHandler;
|
|||||||
#endif
|
#endif
|
||||||
bool InstallCrashHandler() {
|
bool InstallCrashHandler() {
|
||||||
#if NDEBUG
|
#if NDEBUG
|
||||||
FindFileForDelete("D:/pcm");
|
|
||||||
QString appDirPath = QCoreApplication::applicationDirPath() + "/crash";
|
QString appDirPath = QCoreApplication::applicationDirPath() + "/crash";
|
||||||
QDir dir;
|
QDir dir;
|
||||||
if (!dir.exists(appDirPath)) {
|
if (!dir.exists(appDirPath)) {
|
||||||
@ -94,7 +94,7 @@ bool InstallCrashHandler() {
|
|||||||
|
|
||||||
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
|
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
|
||||||
exceptionHandler.reset(new google_breakpad::ExceptionHandler(
|
exceptionHandler.reset(new google_breakpad::ExceptionHandler(
|
||||||
appDirPath.toStdWString(), NULL, OnMinidumpCallback, NULL,
|
appDirPath.toStdWString(), nullptr, OnMinidumpCallback, nullptr,
|
||||||
google_breakpad::ExceptionHandler::HANDLER_ALL));
|
google_breakpad::ExceptionHandler::HANDLER_ALL));
|
||||||
#else
|
#else
|
||||||
exceptionHandler.reset(new google_breakpad::ExceptionHandler(
|
exceptionHandler.reset(new google_breakpad::ExceptionHandler(
|
||||||
@ -106,7 +106,10 @@ bool InstallCrashHandler() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestCrash() {
|
#else
|
||||||
volatile int* a = (int*)(nullptr);
|
|
||||||
*a = 1;
|
bool InstallCrashHandler() {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
bool InstallCrashHandler();
|
bool InstallCrashHandler();
|
||||||
void TestCrash();
|
|
||||||
@ -226,6 +226,12 @@ QWidget#SystemManagerMenu > QToolButton#menu_logs {
|
|||||||
QWidget#SystemManagerMenu > QToolButton#menu_logs_clean {
|
QWidget#SystemManagerMenu > QToolButton#menu_logs_clean {
|
||||||
qproperty-icon: url(:/res/default/menu_logs_clean.png);
|
qproperty-icon: url(:/res/default/menu_logs_clean.png);
|
||||||
}
|
}
|
||||||
|
QWidget#SystemManagerMenu > QToolButton#menu_window_manager {
|
||||||
|
qproperty-icon: url(:/res/default/menu_window_manager.png);
|
||||||
|
}
|
||||||
|
QWidget#SystemManagerMenu > QToolButton#menu_uisetting {
|
||||||
|
qproperty-icon: url(:/res/default/menu_window_setting.png);
|
||||||
|
}
|
||||||
|
|
||||||
QWidget#viewDisplay {
|
QWidget#viewDisplay {
|
||||||
border: 5 solid #1C1D1F;
|
border: 5 solid #1C1D1F;
|
||||||
@ -293,7 +299,3 @@ QDockWidget DockTitleWidget QPushButton::menu-indicator,
|
|||||||
QDockWidget DockTitleWidget QToolButton::menu-indicator {
|
QDockWidget DockTitleWidget QToolButton::menu-indicator {
|
||||||
image: none;
|
image: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
QListWidget {
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
@ -72,6 +72,17 @@ QPushButton#sys_close {
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QPushButton#sys_float {
|
||||||
|
max-width:48px;
|
||||||
|
min-width:48px;
|
||||||
|
max-height:28px;
|
||||||
|
min-height:28px;
|
||||||
|
border: none;
|
||||||
|
background: transparent;
|
||||||
|
image: url(:/res/sys_float.png);
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
QPushButton#sys_min {
|
QPushButton#sys_min {
|
||||||
max-width:48px;
|
max-width:48px;
|
||||||
min-width:48px;
|
min-width:48px;
|
||||||
@ -91,17 +102,7 @@ QPushButton#sys_max {
|
|||||||
border: none;
|
border: none;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
image: url(:/res/sys_max.png);
|
image: url(:/res/sys_max.png);
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
QPushButton#sys_restore {
|
|
||||||
max-width:48px;
|
|
||||||
min-width:48px;
|
|
||||||
max-height:28px;
|
|
||||||
min-height:28px;
|
|
||||||
border: none;
|
|
||||||
background: transparent;
|
|
||||||
image: url(:/res/sys_restore.png);
|
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,7 +126,6 @@ QPushButton#sys_close::hover, QPushButton#sys_close::pressed {
|
|||||||
|
|
||||||
QPushButton#sys_min::hover, QPushButton#sys_min::pressed,
|
QPushButton#sys_min::hover, QPushButton#sys_min::pressed,
|
||||||
QPushButton#sys_max::hover, QPushButton#sys_max::pressed,
|
QPushButton#sys_max::hover, QPushButton#sys_max::pressed,
|
||||||
QPushButton#sys_restore::hover, QPushButton#sys_restore::pressed,
|
|
||||||
QToolButton#sys_skin::hover, QToolButton#sys_skin::pressed {
|
QToolButton#sys_skin::hover, QToolButton#sys_skin::pressed {
|
||||||
background: #38C0C0C0;
|
background: #38C0C0C0;
|
||||||
border: 1 solid #C0C0C0;
|
border: 1 solid #C0C0C0;
|
||||||
@ -230,6 +230,18 @@ QWidget#FileManagerMenu > QToolButton#menu_save_shape_file {
|
|||||||
QWidget#FileManagerMenu > QToolButton#menu_save_shape_file {
|
QWidget#FileManagerMenu > QToolButton#menu_save_shape_file {
|
||||||
qproperty-icon: url(:/res/default/menu_report_mesh.png);
|
qproperty-icon: url(:/res/default/menu_report_mesh.png);
|
||||||
}
|
}
|
||||||
|
QWidget#FileManagerMenu > QToolButton#menu_wave_file {
|
||||||
|
qproperty-icon: url(:/res/default/menu_wave_file.png);
|
||||||
|
}
|
||||||
|
QWidget#FileManagerMenu > QToolButton#menu_surface_file {
|
||||||
|
qproperty-icon: url(:/res/default/menu_surface_file.png);
|
||||||
|
}
|
||||||
|
QWidget#FileManagerMenu > QToolButton#menu_table_file {
|
||||||
|
qproperty-icon: url(:/res/default/menu_table_file.png);
|
||||||
|
}
|
||||||
|
QWidget#FileManagerMenu > QToolButton#menu_light_file {
|
||||||
|
qproperty-icon: url(:/res/default/menu_light_file.png);
|
||||||
|
}
|
||||||
|
|
||||||
QWidget#SystemManagerMenu > QToolButton#menu_exit {
|
QWidget#SystemManagerMenu > QToolButton#menu_exit {
|
||||||
qproperty-icon: url(:/res/default/menu_exit.png);
|
qproperty-icon: url(:/res/default/menu_exit.png);
|
||||||
@ -255,6 +267,12 @@ QWidget#SystemManagerMenu > QToolButton#menu_logs {
|
|||||||
QWidget#SystemManagerMenu > QToolButton#menu_logs_clean {
|
QWidget#SystemManagerMenu > QToolButton#menu_logs_clean {
|
||||||
qproperty-icon: url(:/res/default/menu_logs_clean.png);
|
qproperty-icon: url(:/res/default/menu_logs_clean.png);
|
||||||
}
|
}
|
||||||
|
QWidget#SystemManagerMenu > QToolButton#menu_window_manager {
|
||||||
|
qproperty-icon: url(:/res/default/menu_window_manager.png);
|
||||||
|
}
|
||||||
|
QWidget#SystemManagerMenu > QToolButton#menu_uisetting {
|
||||||
|
qproperty-icon: url(:/res/default/menu_window_setting.png);
|
||||||
|
}
|
||||||
|
|
||||||
QWidget#viewDisplay {
|
QWidget#viewDisplay {
|
||||||
border: 5 solid #1C1D1F;
|
border: 5 solid #1C1D1F;
|
||||||
@ -323,6 +341,27 @@ QDockWidget DockTitleWidget QToolButton::menu-indicator {
|
|||||||
image: none;
|
image: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
QListWidget {
|
QMenu {
|
||||||
border: none;
|
background: #212F3C;
|
||||||
|
color: #e0e0e0;
|
||||||
|
padding: 4px;
|
||||||
|
border-radius: 3px;
|
||||||
}
|
}
|
||||||
|
QMenu::item {
|
||||||
|
padding: 6px 30px 6px 20px;
|
||||||
|
margin: 2px;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMenu::item:selected {
|
||||||
|
background:rgb(41, 59, 75);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
QMenu::item:checked {
|
||||||
|
background:rgb(41, 59, 75);
|
||||||
|
}
|
||||||
|
QMenu::separator {
|
||||||
|
height: 1px;
|
||||||
|
background: #555;
|
||||||
|
margin: 5px 10px;
|
||||||
|
}
|
||||||
@ -1,5 +1,5 @@
|
|||||||
#include "effects/ConeWave.h"
|
#include "effects/ConeWave.h"
|
||||||
/*
|
|
||||||
#include <osg/BlendFunc>
|
#include <osg/BlendFunc>
|
||||||
#include <osg/Material>
|
#include <osg/Material>
|
||||||
#include <osg/Texture2D>
|
#include <osg/Texture2D>
|
||||||
@ -11,6 +11,7 @@
|
|||||||
#include <osg/Program>
|
#include <osg/Program>
|
||||||
#include <osg/Uniform>
|
#include <osg/Uniform>
|
||||||
#include <osg/Depth>
|
#include <osg/Depth>
|
||||||
|
#include <osg/Cullface>
|
||||||
#include <osgEarth/Registry>
|
#include <osgEarth/Registry>
|
||||||
|
|
||||||
class WaveSurfaceCallback : public osg::NodeCallback {
|
class WaveSurfaceCallback : public osg::NodeCallback {
|
||||||
@ -20,14 +21,12 @@ public:
|
|||||||
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) {
|
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) {
|
||||||
timeElapsed += (nv->getFrameStamp()->getSimulationTime() - SimulationTime);
|
timeElapsed += (nv->getFrameStamp()->getSimulationTime() - SimulationTime);
|
||||||
|
|
||||||
// 获取并更新geometry的顶点
|
|
||||||
osg::Geode* geode = dynamic_cast<osg::Geode*>(node);
|
osg::Geode* geode = dynamic_cast<osg::Geode*>(node);
|
||||||
if (geode) {
|
if (geode) {
|
||||||
osg::Geometry* geometry = dynamic_cast<osg::Geometry*>(geode->getDrawable(0));
|
osg::Geometry* geometry = dynamic_cast<osg::Geometry*>(geode->getDrawable(0));
|
||||||
if (geometry) {
|
if (geometry) {
|
||||||
osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray());
|
osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray());
|
||||||
if (vertices) {
|
if (vertices) {
|
||||||
// 更新顶点位置来模拟波动
|
|
||||||
float amplitude = 2.0f;
|
float amplitude = 2.0f;
|
||||||
float frequency = 1.0f;
|
float frequency = 1.0f;
|
||||||
for (unsigned int i = 0; i < vertices->size(); ++i) {
|
for (unsigned int i = 0; i < vertices->size(); ++i) {
|
||||||
@ -35,12 +34,11 @@ public:
|
|||||||
vertex.z() = amplitude * sin(frequency * (vertex.x() + timeElapsed));
|
vertex.z() = amplitude * sin(frequency * (vertex.x() + timeElapsed));
|
||||||
}
|
}
|
||||||
geometry->setVertexArray(vertices);
|
geometry->setVertexArray(vertices);
|
||||||
geometry->dirtyBound(); // 更新几何体边界
|
geometry->dirtyBound();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 继续遍历场景图
|
|
||||||
traverse(node, nv);
|
traverse(node, nv);
|
||||||
SimulationTime = nv->getFrameStamp()->getSimulationTime();
|
SimulationTime = nv->getFrameStamp()->getSimulationTime();
|
||||||
}
|
}
|
||||||
@ -50,9 +48,49 @@ private:
|
|||||||
double SimulationTime;
|
double SimulationTime;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class RadarWaveTimeCallback : public osg::NodeCallback {
|
||||||
|
public:
|
||||||
|
RadarWaveTimeCallback(osg::ref_ptr<osg::Uniform> waveTimeUniform)
|
||||||
|
: waveTimeUniform_(waveTimeUniform), startTime_(0.0) {}
|
||||||
|
|
||||||
|
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) {
|
||||||
|
if (nv->getFrameStamp()) {
|
||||||
|
double currentTime = nv->getFrameStamp()->getSimulationTime();
|
||||||
|
if (startTime_ == 0.0) {
|
||||||
|
startTime_ = currentTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
float elapsedTime = static_cast<float>(currentTime - startTime_);
|
||||||
|
|
||||||
|
if (waveTimeUniform_.valid()) {
|
||||||
|
waveTimeUniform_->set(elapsedTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
traverse(node, nv);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
osg::ref_ptr<osg::Uniform> waveTimeUniform_;
|
||||||
|
double startTime_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
ConeWave::ConeWave() {
|
ConeWave::ConeWave() {
|
||||||
osgEarth::Registry::shaderGenerator().run(this);
|
osgEarth::Registry::shaderGenerator().run(this);
|
||||||
|
currentTime_ = 0.0;
|
||||||
|
|
||||||
|
height_ = 1000.0f;
|
||||||
|
radius_ = 50.0f;
|
||||||
|
waveRadius_ = 100.0f;
|
||||||
|
waveSpeed_ = 20.0f;
|
||||||
|
waveCount_ = 3;
|
||||||
|
baseColor_ = osg::Vec4(0.0f, 0.8f, 1.0f, 1.0f);
|
||||||
|
waveColor_ = osg::Vec4(1.0f, 0.5f, 1.0f, 0.8f);
|
||||||
|
|
||||||
|
ringBrightAlpha_ = 0.8f;
|
||||||
|
ringDarkAlpha_ = 0.3f;
|
||||||
|
coneAlpha_ = 0.7f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -61,15 +99,15 @@ ConeWave::~ConeWave(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ConeWave::Render(double dt) {
|
void ConeWave::Render(double dt) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConeWave::InitGeode() {
|
void ConeWave::InitGeode() {
|
||||||
CreateTexturedCone(this);
|
Rebuild();
|
||||||
//getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
|
getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
|
||||||
//getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON);
|
getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON);
|
||||||
//getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
|
getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
|
||||||
//setCullingActive(false);
|
getOrCreateStateSet()->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON);
|
||||||
|
setCullingActive(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConeWave::Destory() {
|
void ConeWave::Destory() {
|
||||||
@ -78,446 +116,253 @@ void ConeWave::Destory() {
|
|||||||
|
|
||||||
void ConeWave::SetHeight(float height) {
|
void ConeWave::SetHeight(float height) {
|
||||||
height_ = height;
|
height_ = height;
|
||||||
if (cone_) {
|
|
||||||
cone_->setHeight(height_);
|
Rebuild();
|
||||||
}
|
|
||||||
// coneDrawable_->build();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConeWave::SetRadius(float radius) {
|
|
||||||
radius_ = radius;
|
|
||||||
if (cone_) {
|
|
||||||
cone_->setRadius(radius);
|
|
||||||
}
|
|
||||||
// coneDrawable_->build();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConeWave::SetBaseColor(const osg::Vec4& color) {
|
void ConeWave::SetBaseColor(const osg::Vec4& color) {
|
||||||
baseColor_ = color;
|
baseColor_ = color;
|
||||||
if (baseColorUniform_) {
|
|
||||||
baseColorUniform_->set(color);
|
if (baseColorUniform_.valid()) {
|
||||||
|
baseColorUniform_->set(baseColor_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConeWave::SetLevelCount(int count) {
|
void ConeWave::SetWaveCount(int count) {
|
||||||
levelCount_ = count;
|
waveCount_ = count;
|
||||||
if (levelCountUniform_) {
|
|
||||||
levelCountUniform_->set(float(levelCount_));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConeWave::SetLevelHeight(float height) {
|
|
||||||
levelHeight_ = height;
|
|
||||||
if (levelHeightUniform_) {
|
|
||||||
levelHeightUniform_->set(levelHeight_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConeWave::CreateTexturedCone(osg::Geode* geode) {
|
|
||||||
// cone_ = new osg::Cone(osg::Vec3(0, 0, 0.), radius_, height_);
|
|
||||||
// osg::TessellationHints* tesselate = new osg::TessellationHints;
|
|
||||||
// tesselate->setCreateBottom(false);
|
|
||||||
// tesselate->setCreateBackFace(false);
|
|
||||||
// coneDrawable_ = new osg::ShapeDrawable(cone_, tesselate);
|
|
||||||
// geode->addDrawable(coneDrawable_);
|
|
||||||
// coneDrawable_->setColor(baseColor_);
|
|
||||||
// osg::StateSet* ss = coneDrawable_->getOrCreateStateSet();
|
|
||||||
// //stateset->setRenderBinDetails(120, "OSGEARTH_SCREEN_SPACE_LAYOUT_BIN");
|
|
||||||
// ss->setRenderBinDetails(120, "RenderBin");
|
|
||||||
// osg::ref_ptr<osg::BlendFunc> bf = new osg::BlendFunc();
|
|
||||||
// ss->setAttributeAndModes(bf, osg::StateAttribute::ON);
|
|
||||||
// ss->setMode(GL_CULL_FACE, osg::StateAttribute::ON);
|
|
||||||
|
|
||||||
|
if (waveCountUniform_.valid()) {
|
||||||
osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry();
|
waveCountUniform_->set(static_cast<float>(waveCount_));
|
||||||
|
} else {
|
||||||
// 创建顶点数组
|
Rebuild();
|
||||||
osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;
|
|
||||||
|
|
||||||
int rows = 20, cols=20;
|
|
||||||
for (unsigned int i = 0; i < rows; ++i) {
|
|
||||||
for (unsigned int j = 0; j < cols; ++j) {
|
|
||||||
// 坐标
|
|
||||||
float x = (float)i / (rows - 1) * 100;
|
|
||||||
float y = (float)j / (cols - 1) * 100;
|
|
||||||
vertices->push_back(osg::Vec3f(x, y, 0.0f));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
geometry->setVertexArray(vertices);
|
void ConeWave::SetWaveSpeed(float speed) {
|
||||||
|
waveSpeed_ = speed;
|
||||||
// 生成索引来连接顶点
|
|
||||||
osg::ref_ptr<osg::DrawElementsUShort> indices = new osg::DrawElementsUShort(osg::PrimitiveSet::QUADS);
|
if (waveSpeedUniform_.valid()) {
|
||||||
for (unsigned int i = 0; i < rows - 1; ++i) {
|
waveSpeedUniform_->set(waveSpeed_);
|
||||||
for (unsigned int j = 0; j < cols - 1; ++j) {
|
|
||||||
unsigned short bottomLeft = i * cols + j;
|
|
||||||
unsigned short bottomRight = bottomLeft + 1;
|
|
||||||
unsigned short topLeft = (i + 1) * cols + j;
|
|
||||||
unsigned short topRight = topLeft + 1;
|
|
||||||
|
|
||||||
indices->push_back(bottomLeft);
|
|
||||||
indices->push_back(bottomRight);
|
|
||||||
indices->push_back(topRight);
|
|
||||||
indices->push_back(topLeft);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
geometry->addPrimitiveSet(indices);
|
}
|
||||||
|
|
||||||
// 创建表面颜色
|
void ConeWave::SetWaveRadius(float radius) {
|
||||||
osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array;
|
waveRadius_ = radius;
|
||||||
colors->push_back(osg::Vec4(0.0f, 0.0f, 1.0f, 1.0f)); // 蓝色
|
radius_ = radius;
|
||||||
|
Rebuild();
|
||||||
|
}
|
||||||
|
|
||||||
geometry->setColorArray(colors);
|
void ConeWave::SetWaveColor(const osg::Vec4& color) {
|
||||||
geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
|
waveColor_ = color;
|
||||||
|
|
||||||
// 添加geometry到geode
|
if (waveColorUniform_.valid()) {
|
||||||
geode->addDrawable(geometry);
|
waveColorUniform_->set(waveColor_);
|
||||||
geode->setUpdateCallback(new WaveSurfaceCallback());
|
}
|
||||||
return;
|
}
|
||||||
|
|
||||||
static const char* vertSource = {
|
void ConeWave::SetRingBrightAlpha(float alpha) {
|
||||||
"#version 330\n"
|
ringBrightAlpha_ = alpha;
|
||||||
|
|
||||||
|
if (ringBrightAlphaUniform_.valid()) {
|
||||||
|
ringBrightAlphaUniform_->set(alpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConeWave::SetRingDarkAlpha(float alpha) {
|
||||||
|
ringDarkAlpha_ = alpha;
|
||||||
|
if (ringDarkAlphaUniform_.valid()) {
|
||||||
|
ringDarkAlphaUniform_->set(alpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConeWave::SetConeAlpha(float alpha) {
|
||||||
|
coneAlpha_ = alpha;
|
||||||
|
if (coneGeometry_.valid()) {
|
||||||
|
osg::StateSet* ss = coneGeometry_->getOrCreateStateSet();
|
||||||
|
osg::ref_ptr<osg::Material> material = new osg::Material();
|
||||||
|
material->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4(0.0f, 0.8f, 1.0f, alpha));
|
||||||
|
material->setTransparency(osg::Material::FRONT_AND_BACK, 1.0f - alpha);
|
||||||
|
ss->setAttributeAndModes(material, osg::StateAttribute::ON);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConeWave::Clear() {
|
||||||
|
if (coneCallback_.valid()) {
|
||||||
|
setUpdateCallback(nullptr);
|
||||||
|
coneCallback_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (coneGeometry_.valid()) {
|
||||||
|
removeDrawable(coneGeometry_);
|
||||||
|
coneGeometry_ = nullptr;
|
||||||
|
coneDrawable_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
waveTimeUniform_ = nullptr;
|
||||||
|
baseColorUniform_ = nullptr;
|
||||||
|
waveColorUniform_ = nullptr;
|
||||||
|
levelHeightUniform_ = nullptr;
|
||||||
|
waveSpeedUniform_ = nullptr;
|
||||||
|
ringBrightAlphaUniform_ = nullptr;
|
||||||
|
ringDarkAlphaUniform_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConeWave::Rebuild() {
|
||||||
|
Clear();
|
||||||
|
|
||||||
|
CreateRadarScanWave();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConeWave::CreateConeGeometry() {
|
||||||
|
osg::ref_ptr<osg::Geometry> coneGeometry = new osg::Geometry();
|
||||||
|
|
||||||
|
const int segments = 64;
|
||||||
|
const float angleStep = 2.0f * osg::PI / segments;
|
||||||
|
|
||||||
|
osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array();
|
||||||
|
osg::ref_ptr<osg::Vec3Array> normals = new osg::Vec3Array();
|
||||||
|
osg::ref_ptr<osg::Vec2Array> texCoords = new osg::Vec2Array();
|
||||||
|
|
||||||
|
vertices->push_back(osg::Vec3(0.0f, 0.0f, 0.0f));
|
||||||
|
normals->push_back(osg::Vec3(0.0f, 0.0f, -1.0f));
|
||||||
|
texCoords->push_back(osg::Vec2(0.5f, 0.5f));
|
||||||
|
|
||||||
|
for (int i = 0; i <= segments; ++i) {
|
||||||
|
float angle = i * angleStep;
|
||||||
|
float x = radius_ * cos(angle);
|
||||||
|
float y = radius_ * sin(angle);
|
||||||
|
float z = height_;
|
||||||
|
|
||||||
|
vertices->push_back(osg::Vec3(x, y, z));
|
||||||
|
|
||||||
|
osg::Vec3 normal(x, y, radius_);
|
||||||
|
normal.normalize();
|
||||||
|
normals->push_back(normal);
|
||||||
|
|
||||||
|
texCoords->push_back(osg::Vec2((x/radius_ + 1.0f) * 0.5f, (y/radius_ + 1.0f) * 0.5f));
|
||||||
|
}
|
||||||
|
|
||||||
|
coneGeometry->setVertexArray(vertices);
|
||||||
|
coneGeometry->setNormalArray(normals);
|
||||||
|
coneGeometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
|
||||||
|
coneGeometry->setTexCoordArray(0, texCoords);
|
||||||
|
|
||||||
|
osg::ref_ptr<osg::DrawElementsUInt> indices = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES);
|
||||||
|
|
||||||
|
for (int i = 0; i < segments; ++i) {
|
||||||
|
indices->push_back(0);
|
||||||
|
indices->push_back(i + 1);
|
||||||
|
indices->push_back(i + 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
coneGeometry->addPrimitiveSet(indices);
|
||||||
|
if (coneGeometry_.valid() && coneGeometry_->getNumParents() > 0) {
|
||||||
|
removeDrawable(coneGeometry_);
|
||||||
|
coneGeometry_ = coneGeometry;
|
||||||
|
coneDrawable_ = coneGeometry_.get();
|
||||||
|
waveTimeUniform_ = nullptr;
|
||||||
|
levelHeightUniform_ = nullptr;
|
||||||
|
addDrawable(coneDrawable_);
|
||||||
|
} else {
|
||||||
|
coneGeometry_ = coneGeometry;
|
||||||
|
coneDrawable_ = coneGeometry_.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConeWave::CreateRadarScanWave() {
|
||||||
|
CreateConeGeometry();
|
||||||
|
|
||||||
|
addDrawable(coneDrawable_);
|
||||||
|
|
||||||
|
osg::StateSet* ss = coneDrawable_->getOrCreateStateSet();
|
||||||
|
ss->setRenderBinDetails(120, "RenderBin");
|
||||||
|
ss->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
|
||||||
|
ss->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
|
||||||
|
|
||||||
|
osg::ref_ptr<osg::BlendFunc> bf = new osg::BlendFunc(osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::ONE_MINUS_SRC_ALPHA);
|
||||||
|
ss->setAttributeAndModes(bf, osg::StateAttribute::ON);
|
||||||
|
ss->setMode(GL_BLEND, osg::StateAttribute::ON);
|
||||||
|
ss->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
|
||||||
|
ss->setAttributeAndModes(new osg::CullFace(osg::CullFace::BACK));
|
||||||
|
|
||||||
|
CreateRadarShader();
|
||||||
|
|
||||||
|
osg::ref_ptr<osg::NodeCallback> waveTimeCallback = new RadarWaveTimeCallback(waveTimeUniform_);
|
||||||
|
coneCallback_ = waveTimeCallback;
|
||||||
|
setUpdateCallback(coneCallback_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConeWave::CreateRadarShader() {
|
||||||
|
if (waveTimeUniform_.valid()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* vertexShaderSource =
|
||||||
"varying vec3 pos;\n"
|
"varying vec3 pos;\n"
|
||||||
"void main()\n"
|
"void main()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
"pos.x=gl_Vertex.x;\n"
|
" pos.x = gl_Vertex.x;\n"
|
||||||
"pos.y=gl_Vertex.y;\n"
|
" pos.y = gl_Vertex.y;\n"
|
||||||
"pos.z=gl_Vertex.z;\n"
|
" pos.z = gl_Vertex.z;\n"
|
||||||
"gl_Position = gl_ModelViewProjectionMatrix*gl_Vertex;\n"
|
" gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
|
||||||
"}\n"
|
"}\n";
|
||||||
};
|
|
||||||
static const char* fragSource = {
|
static const char* fragmentShaderSource =
|
||||||
"#version 330\n"
|
"uniform float height;\n"
|
||||||
"uniform float num; \n"
|
"uniform vec4 baseColor;\n"
|
||||||
"uniform float height; \n"
|
"uniform vec4 waveColor;\n"
|
||||||
"uniform vec4 baseColor;\n"
|
"uniform float waveTime;\n"
|
||||||
"varying vec3 pos;\n"
|
"uniform float ringBrightAlpha;\n"
|
||||||
"float Alpha = 1.0; \n"
|
"uniform float ringDarkAlpha;\n"
|
||||||
"float f = pos.z;\n"
|
"uniform float waveSpeed;\n"
|
||||||
"uniform float osg_FrameTime;\n"
|
"uniform float waveCount;\n"
|
||||||
"void main()\n"
|
"varying vec3 pos;\n"
|
||||||
"{\n"
|
"void main()\n"
|
||||||
"if (sin(f/height*3.14*2*num+ osg_FrameTime*10) > 0)\n"
|
"{\n"
|
||||||
"{\n"
|
" float h = abs(pos.z) / max(height, 1.0);\n"
|
||||||
" Alpha = 0.8;\n"
|
" float radialDist = sqrt(pos.x * pos.x + pos.y * pos.y);\n"
|
||||||
"}\n"
|
" float waveFreq = 0.2 * max(1.0, waveCount * 0.1);\n"
|
||||||
"else\n"
|
" float timeScale = waveTime * waveSpeed * 0.1;\n"
|
||||||
"{\n"
|
" float wavePhase = radialDist * waveFreq - timeScale;\n"
|
||||||
" Alpha = 0.3;\n"
|
" float ripple = sin(wavePhase);\n"
|
||||||
"}\n"
|
" float ripple2 = sin(wavePhase * 1.1 + timeScale * 0.5);\n"
|
||||||
" gl_FragColor = vec4(baseColor.rgb, Alpha);\n"
|
" ripple = (ripple + ripple2 * 0.3) / 1.3;\n"
|
||||||
"}\n "
|
" if (ripple > 0.3)\n"
|
||||||
};
|
" {\n"
|
||||||
|
" gl_FragColor = vec4(waveColor.rgb, ringBrightAlpha);\n"
|
||||||
osg::ref_ptr<osg::Shader> vertexShader = new osg::Shader(osg::Shader::VERTEX);
|
" }\n"
|
||||||
vertexShader->setShaderSource(vertSource);
|
" else\n"
|
||||||
osg::ref_ptr<osg::Shader> fragmentShader = new osg::Shader(osg::Shader::FRAGMENT);
|
" {\n"
|
||||||
fragmentShader->setShaderSource(fragSource);
|
" gl_FragColor = vec4(baseColor.rgb, ringDarkAlpha);\n"
|
||||||
|
" }\n"
|
||||||
osg::StateSet* stateset = coneDrawable_->getOrCreateStateSet();
|
"}\n";
|
||||||
// osg::ref_ptr<osg::Material> mat = new osg::Material;
|
|
||||||
// //设置正面散射颜色
|
osg::ref_ptr<osg::Shader> vertexShader = new osg::Shader(osg::Shader::VERTEX, vertexShaderSource);
|
||||||
// mat->setDiffuse(osg::Material::FRONT, osg::Vec4(1.0, 0.0, 0.0, 0.3));//1.0, 0.0, 0.0, 0.3
|
osg::ref_ptr<osg::Shader> fragmentShader = new osg::Shader(osg::Shader::FRAGMENT, fragmentShaderSource);
|
||||||
// //设置正面镜面颜色
|
|
||||||
// mat->setSpecular(osg::Material::FRONT, osg::Vec4(1.0, 0.0, 0.0, 0.3));//1.0, 0.0, 0.0, 0.3
|
osg::ref_ptr<osg::Program> program = new osg::Program;
|
||||||
//
|
program->addShader(vertexShader);
|
||||||
// geode->getOrCreateStateSet()->setAttribute(mat);
|
program->addShader(fragmentShader);
|
||||||
stateset->setMode(GL_BLEND, osg::StateAttribute::ON);
|
|
||||||
stateset->setMode(GL_RESCALE_NORMAL, osg::StateAttribute::ON);
|
osg::StateSet* stateSet = coneDrawable_->getOrCreateStateSet();
|
||||||
// stateset->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON);
|
stateSet->setAttributeAndModes(program, osg::StateAttribute::ON);
|
||||||
stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
|
|
||||||
|
waveTimeUniform_ = new osg::Uniform("waveTime", 0.0f);
|
||||||
//设置渲染顺序 仿真模型被波束遮盖 ,1000000-指的是若有1000000个Node 则此节点最后一个被渲染
|
baseColorUniform_ = new osg::Uniform("baseColor", baseColor_);
|
||||||
// //stateset->setRenderBinDetails(120, "OSGEARTH_SCREEN_SPACE_LAYOUT_BIN");
|
waveColorUniform_ = new osg::Uniform("waveColor", waveColor_);
|
||||||
stateset->setRenderBinDetails(10, "RenderBin");
|
levelHeightUniform_ = new osg::Uniform("height", height_ > 0 ? height_ : 100.0f);
|
||||||
// osg::ref_ptr<osg::BlendFunc> blendFunc = new osg::BlendFunc();
|
waveSpeedUniform_ = new osg::Uniform("waveSpeed", waveSpeed_ > 0 ? waveSpeed_ : 1.0f);
|
||||||
// stateset->setAttributeAndModes(blendFunc, osg::StateAttribute::ON);
|
waveCountUniform_ = new osg::Uniform("waveCount", waveCount_ > 0 ? waveCount_ : 1);
|
||||||
// osg::ref_ptr<osg::Program> program = new osg::Program();
|
|
||||||
// program->addShader(vertexShader);
|
ringBrightAlphaUniform_ = new osg::Uniform("ringBrightAlpha", ringBrightAlpha_);
|
||||||
// program->addShader(fragmentShader);
|
ringDarkAlphaUniform_ = new osg::Uniform("ringDarkAlpha", ringDarkAlpha_);
|
||||||
//
|
|
||||||
// baseColorUniform_ = new osg::Uniform("baseColor", baseColor_);
|
stateSet->addUniform(waveTimeUniform_);
|
||||||
// stateset->setMode(GL_CULL_FACE, osg::StateAttribute::ON);
|
stateSet->addUniform(baseColorUniform_);
|
||||||
// stateset->addUniform(baseColorUniform_);
|
stateSet->addUniform(waveColorUniform_);
|
||||||
// // stateset->setAttributeAndModes(program, osg::StateAttribute::ON);
|
stateSet->addUniform(levelHeightUniform_);
|
||||||
// // stateset->setAttributeAndModes(new osg::Depth(osg::Depth::LESS, 0.0, 1.0, false));
|
stateSet->addUniform(waveSpeedUniform_);
|
||||||
//
|
stateSet->addUniform(waveCountUniform_);
|
||||||
// levelCountUniform_ = new osg::Uniform("num", float(levelCount_));
|
stateSet->addUniform(ringBrightAlphaUniform_);
|
||||||
// levelHeightUniform_ = new osg::Uniform("height", levelHeight_);
|
stateSet->addUniform(ringDarkAlphaUniform_);
|
||||||
|
|
||||||
// stateset->addUniform(levelCountUniform_);
|
|
||||||
// stateset->addUniform(levelHeightUniform_.get());
|
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
#include <osg/Geode>
|
|
||||||
#include <osg/Geometry>
|
|
||||||
#include <osg/Material>
|
|
||||||
#include <osgFX/Outline>
|
|
||||||
#include <osgFX/Scribe>
|
|
||||||
#include <osg/MatrixTransform>
|
|
||||||
#include <osgEarth/Ellipsoid>
|
|
||||||
|
|
||||||
#include "scene/SceneContent.h"
|
|
||||||
|
|
||||||
class WaveBeamConeCallBack : public osg::NodeCallback {
|
|
||||||
public:
|
|
||||||
WaveBeamConeCallBack();
|
|
||||||
~WaveBeamConeCallBack();
|
|
||||||
|
|
||||||
virtual void operator() (osg::Node *node, osg::NodeVisitor *nv);
|
|
||||||
public:
|
|
||||||
double m_latitude;
|
|
||||||
double m_longitude;
|
|
||||||
double m_height;
|
|
||||||
bool m_ifDynamic;
|
|
||||||
|
|
||||||
double m_angle;
|
|
||||||
double m_length;
|
|
||||||
osg::Vec4 m_color;
|
|
||||||
osg::Vec4 m_lineColor;
|
|
||||||
double m_lineWidth;
|
|
||||||
|
|
||||||
osg::ref_ptr<osg::Geode> m_geode;
|
|
||||||
osg::ref_ptr<osg::Geometry> m_geom;
|
|
||||||
osg::ref_ptr<osg::Vec4Array> m_colorArray;
|
|
||||||
osg::ref_ptr<osg::Vec3Array> m_pointVector;
|
|
||||||
osg::ref_ptr<osgFX::Scribe> m_nodeFX;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
WaveBeamConeCallBack::WaveBeamConeCallBack() {
|
|
||||||
m_latitude = 0.0;
|
|
||||||
m_longitude = 0.0;
|
|
||||||
m_height = -6371000;
|
|
||||||
m_ifDynamic = false;
|
|
||||||
|
|
||||||
m_angle = 20.0;
|
|
||||||
m_length = 100000;
|
|
||||||
m_color = osg::Vec4(1, 0, 0, 0.5);
|
|
||||||
m_lineColor = osg::Vec4(1.0, 0.0, 0.0, 1.0);
|
|
||||||
m_lineWidth = 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
WaveBeamConeCallBack::~WaveBeamConeCallBack() {
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void WaveBeamConeCallBack::operator()(osg::Node *node, osg::NodeVisitor *nv) {
|
|
||||||
if (m_ifDynamic == false)
|
|
||||||
return;
|
|
||||||
//std::cout << "WaveBeamConeCallBack info=" << m_latitude << "," << m_longitude << "," << m_height << std::endl;
|
|
||||||
osg::MatrixTransform* mtCone = dynamic_cast<osg::MatrixTransform*>(node);
|
|
||||||
if (mtCone != NULL) {
|
|
||||||
osg::MatrixTransform* mtR = dynamic_cast<osg::MatrixTransform*>(mtCone->getParent(0));
|
|
||||||
osg::MatrixTransform* mt = dynamic_cast<osg::MatrixTransform*>(mtR->getParent(0));
|
|
||||||
|
|
||||||
//osg::Matrix m = osg::computeWorldToLocal(mtCone->getParentalNodePaths().at(0));
|
|
||||||
osg::Matrix m = osg::Matrix::inverse(mt->getMatrix()*mtR->getMatrix());
|
|
||||||
osg::Matrix mTarget;
|
|
||||||
double x, y, z;
|
|
||||||
osg::EllipsoidModel em;
|
|
||||||
em.convertLatLongHeightToXYZ(osg::DegreesToRadians(m_latitude),
|
|
||||||
osg::DegreesToRadians(m_longitude),
|
|
||||||
m_height, x, y, z);
|
|
||||||
|
|
||||||
mTarget.setTrans(x, y, z);
|
|
||||||
osg::Matrix mConeRate = osg::Matrix::rotate(osg::Vec3d(0, 1, 0), (mTarget*m).getTrans());
|
|
||||||
mtCone->setMatrix(mConeRate);//mTarget*m
|
|
||||||
|
|
||||||
//更改cone的形状----------------------------------------
|
|
||||||
double length = (mTarget*m).getTrans().length();
|
|
||||||
|
|
||||||
double angle = osg::DegreesToRadians(m_angle);
|
|
||||||
double radius = std::tan(angle*0.5) * length;
|
|
||||||
int splitCount = 20;
|
|
||||||
double angleStep = osg::PI * 2.0 / splitCount;
|
|
||||||
|
|
||||||
//侧面
|
|
||||||
for (int i = 1; i <= splitCount + 1; i++) {
|
|
||||||
double tempAngle = (i - 1)*angleStep;
|
|
||||||
osg::Vec3 pos(radius * cos(tempAngle), length, radius * sin(tempAngle) + 3);
|
|
||||||
m_pointVector->at(i) = pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_pointVector->at(splitCount + 2) = osg::Vec3(0, length, 0);
|
|
||||||
|
|
||||||
//底面
|
|
||||||
for (int i = splitCount + 3; i <= splitCount + 3 + splitCount; i++) {
|
|
||||||
double tempAngle = (i - splitCount - 3) *angleStep;
|
|
||||||
osg::Vec3 pos(radius * cos(tempAngle), length, radius * sin(tempAngle) + 3);
|
|
||||||
m_pointVector->at(i) = pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_geom->dirtyBound();
|
|
||||||
m_geom->dirtyDisplayList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ConeWave::ConeWave() {
|
|
||||||
}
|
|
||||||
|
|
||||||
ConeWave::~ConeWave() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConeWave::clearSelf() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConeWave::Render(double dt)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConeWave::createWaveBeamCone(osg::MatrixTransform* node, double angle, double length,
|
|
||||||
osg::Vec4 color, osg::Vec4 lineColor, double lineWidth) {
|
|
||||||
double angleD = osg::DegreesToRadians(angle);
|
|
||||||
double radius = std::tan(angleD*0.5) * length;
|
|
||||||
int splitCount = 20;
|
|
||||||
double angleStep = osg::PI * 2.0 / splitCount;
|
|
||||||
|
|
||||||
|
|
||||||
osg::ref_ptr<osg::Geode> geode = new osg::Geode();
|
|
||||||
osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;
|
|
||||||
osg::ref_ptr<osg::Vec3Array> vertex = new osg::Vec3Array;
|
|
||||||
osg::ref_ptr<osg::Vec3Array> normal = new osg::Vec3Array;
|
|
||||||
osg::ref_ptr<osg::DrawElementsUInt> drawElemUInt = new osg::DrawElementsUInt(GL_TRIANGLE_FAN);
|
|
||||||
osg::ref_ptr<osg::DrawElementsUInt> drawElemUInt2 = new osg::DrawElementsUInt(GL_TRIANGLE_FAN);
|
|
||||||
geom->setVertexArray(vertex);
|
|
||||||
geom->setNormalArray(normal);
|
|
||||||
geode->addDrawable(geom);
|
|
||||||
|
|
||||||
vertex->push_back(osg::Vec3(0, 0, 0));
|
|
||||||
drawElemUInt->push_back(0);
|
|
||||||
normal->push_back(osg::Vec3(0, -1, 0));
|
|
||||||
|
|
||||||
//侧面
|
|
||||||
for (int i = 0; i <= splitCount; i++) {
|
|
||||||
double tempAngle = i*angleStep;
|
|
||||||
osg::Vec3 pos(radius * cos(tempAngle), length, radius * sin(tempAngle) + 3);
|
|
||||||
vertex->push_back(osg::Vec3(pos));
|
|
||||||
|
|
||||||
pos.normalize();
|
|
||||||
normal->push_back(pos);
|
|
||||||
drawElemUInt->push_back(i + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
//底面
|
|
||||||
int indexBegin = vertex->size();
|
|
||||||
vertex->push_back(osg::Vec3(0, length, 0));
|
|
||||||
drawElemUInt2->push_back(indexBegin);
|
|
||||||
normal->push_back(osg::Vec3(0, 1, 0));
|
|
||||||
for (int i = 0; i <= splitCount; i++) {
|
|
||||||
double tempAngle = i*angleStep;
|
|
||||||
osg::Vec3 pos(radius * cos(tempAngle), length, radius * sin(tempAngle) + 3);
|
|
||||||
vertex->push_back(osg::Vec3(pos));
|
|
||||||
|
|
||||||
normal->push_back(osg::Vec3(0, 1, 0));
|
|
||||||
drawElemUInt2->push_back(indexBegin + i + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
geom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
|
|
||||||
geom->addPrimitiveSet(drawElemUInt);
|
|
||||||
geom->addPrimitiveSet(drawElemUInt2);
|
|
||||||
|
|
||||||
//创建材质对象
|
|
||||||
osg::ref_ptr<osg::Material> mat = new osg::Material;
|
|
||||||
//设置正面散射颜色
|
|
||||||
mat->setDiffuse(osg::Material::FRONT, osg::Vec4(1.0, 1.0, 0.0, 0.3));//1.0, 0.0, 0.0, 0.3
|
|
||||||
//设置正面镜面颜色
|
|
||||||
mat->setSpecular(osg::Material::FRONT, osg::Vec4(1.0, 0.0, 0.0, 0.3));//1.0, 0.0, 0.0, 0.3
|
|
||||||
|
|
||||||
geode->getOrCreateStateSet()->setAttribute(mat.get());
|
|
||||||
geode->getOrCreateStateSet()->setMode(GL_RESCALE_NORMAL, osg::StateAttribute::ON);
|
|
||||||
//设置透明效果
|
|
||||||
geode->getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON);
|
|
||||||
geode->getOrCreateStateSet()->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON);
|
|
||||||
geode->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
|
|
||||||
|
|
||||||
//设置渲染顺序 仿真模型被波束遮盖 ,1000000-指的是若有1000000个Node 则此节点最后一个被渲染
|
|
||||||
geode->getOrCreateStateSet()->setRenderBinDetails(12, "RenderBin");
|
|
||||||
|
|
||||||
osg::ref_ptr<osg::MatrixTransform> mtCone = new osg::MatrixTransform;
|
|
||||||
// mtCone->addChild(nodeFX);
|
|
||||||
|
|
||||||
//给callback中赋值
|
|
||||||
WaveBeamConeCallBack* coneCallBack = new WaveBeamConeCallBack;
|
|
||||||
coneCallBack->m_angle = angle;
|
|
||||||
coneCallBack->m_length = length;
|
|
||||||
coneCallBack->m_color = color;
|
|
||||||
coneCallBack->m_lineColor = lineColor;
|
|
||||||
coneCallBack->m_lineWidth = lineWidth;
|
|
||||||
|
|
||||||
coneCallBack->m_geode = geode;
|
|
||||||
coneCallBack->m_geom = geom;
|
|
||||||
coneCallBack->m_pointVector = vertex;
|
|
||||||
|
|
||||||
//添加到模型中
|
|
||||||
// osg::MatrixTransform* mtR = dynamic_cast<osg::MatrixTransform*>(node->getChild(0));
|
|
||||||
// osg::MatrixTransform* mtS = dynamic_cast<osg::MatrixTransform*>(mtR->getChild(0));
|
|
||||||
// mtR->addChild(mtCone);
|
|
||||||
_waveBeamCone = mtCone;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConeWave::changeWaveBeamConeTarget(double latitude, double longitude, double height, bool ifDynamic) {
|
|
||||||
WaveBeamConeCallBack* coneCallBack = dynamic_cast<WaveBeamConeCallBack*>(_waveBeamCone->getUpdateCallback());
|
|
||||||
if (coneCallBack != NULL) {
|
|
||||||
coneCallBack->m_ifDynamic = ifDynamic;
|
|
||||||
coneCallBack->m_latitude = latitude;
|
|
||||||
coneCallBack->m_longitude = longitude;
|
|
||||||
coneCallBack->m_height = height;
|
|
||||||
|
|
||||||
if (ifDynamic == false) {
|
|
||||||
osg::MatrixTransform* mtCone = _waveBeamCone;
|
|
||||||
|
|
||||||
osg::MatrixTransform* mtR = dynamic_cast<osg::MatrixTransform*>(mtCone->getParent(0));
|
|
||||||
osg::MatrixTransform* mt = dynamic_cast<osg::MatrixTransform*>(mtR->getParent(0));
|
|
||||||
|
|
||||||
//osg::Matrix m = osg::computeWorldToLocal(mtCone->getParentalNodePaths().at(0));
|
|
||||||
osg::Matrix m = osg::Matrix::inverse(mt->getMatrix()*mtR->getMatrix());
|
|
||||||
osg::Matrix mTarget;
|
|
||||||
double x, y, z;
|
|
||||||
osg::EllipsoidModel em;
|
|
||||||
em.convertLatLongHeightToXYZ(osg::DegreesToRadians(latitude),
|
|
||||||
osg::DegreesToRadians(longitude),
|
|
||||||
height, x, y, z);
|
|
||||||
|
|
||||||
mTarget.setTrans(x, y, z);
|
|
||||||
osg::Matrix mConeRate = osg::Matrix::rotate(osg::Vec3d(0, 1, 0), (mTarget*m).getTrans());
|
|
||||||
|
|
||||||
mtCone->setMatrix(mConeRate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConeWave::changeWaveBeamConeAppearance( osg::Vec4 color, osg::Vec4 lineColor, double lineWidth) {
|
|
||||||
WaveBeamConeCallBack* coneCallBack = dynamic_cast<WaveBeamConeCallBack*>(_waveBeamCone->getUpdateCallback());
|
|
||||||
if (coneCallBack != NULL) {
|
|
||||||
coneCallBack->m_color = color;
|
|
||||||
coneCallBack->m_lineColor = lineColor;
|
|
||||||
coneCallBack->m_lineWidth = lineWidth;
|
|
||||||
|
|
||||||
//创建材质对象
|
|
||||||
osg::ref_ptr<osg::Material> mat = new osg::Material;
|
|
||||||
//设置正面散射颜色
|
|
||||||
mat->setDiffuse(osg::Material::FRONT, color);//1.0, 0.0, 0.0, 0.3
|
|
||||||
//设置正面镜面颜色
|
|
||||||
mat->setSpecular(osg::Material::FRONT, color);//1.0, 0.0, 0.0, 0.3
|
|
||||||
coneCallBack->m_geode->getOrCreateStateSet()->setAttribute(mat.get());
|
|
||||||
|
|
||||||
if (lineWidth < 0.1) {
|
|
||||||
_waveBeamCone->addChild(coneCallBack->m_geode);
|
|
||||||
_waveBeamCone->removeChild(coneCallBack->m_nodeFX);
|
|
||||||
} else {
|
|
||||||
_waveBeamCone->removeChild(coneCallBack->m_geode);
|
|
||||||
_waveBeamCone->addChild(coneCallBack->m_nodeFX);
|
|
||||||
|
|
||||||
coneCallBack->m_nodeFX->setWireframeColor(lineColor);
|
|
||||||
coneCallBack->m_nodeFX->setWireframeLineWidth(lineWidth);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
/*
|
|
||||||
#include <osg/Matrix>
|
#include <osg/Matrix>
|
||||||
#include <osg/Array>
|
#include <osg/Array>
|
||||||
#include <osg/Geometry>
|
#include <osg/Geometry>
|
||||||
@ -20,78 +20,73 @@ public:
|
|||||||
void InitGeode();
|
void InitGeode();
|
||||||
void Destory();
|
void Destory();
|
||||||
|
|
||||||
|
void CreateRadarScanWave();
|
||||||
|
void CreateConeGeometry();
|
||||||
|
void CreateRadarShader();
|
||||||
|
void SetWaveRadius(float radius);
|
||||||
|
float GetWaveRadius() const { return waveRadius_; }
|
||||||
|
|
||||||
|
void SetWaveSpeed(float speed);
|
||||||
|
float GetWaveSpeed() const { return waveSpeed_; }
|
||||||
|
|
||||||
|
void SetWaveCount(int count);
|
||||||
|
int GetWaveCount() const { return waveCount_; }
|
||||||
|
|
||||||
|
void SetWaveColor(const osg::Vec4& color);
|
||||||
|
const osg::Vec4& GetWaveColor() const { return waveColor_; }
|
||||||
|
|
||||||
void SetHeight(float height);
|
void SetHeight(float height);
|
||||||
float GetHeght() const {
|
float GetHeght() const {
|
||||||
return height_;
|
return height_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetRadius(float radius);
|
|
||||||
float GetRadius() const {
|
|
||||||
return radius_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetBaseColor(const osg::Vec4& color);
|
void SetBaseColor(const osg::Vec4& color);
|
||||||
const osg::Vec4 GetBaseColor() const {
|
const osg::Vec4 GetBaseColor() const {
|
||||||
return baseColor_;
|
return baseColor_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetLevelCount(int count);
|
void SetRingBrightAlpha(float alpha);
|
||||||
int GetLevelCount() const {
|
float GetRingBrightAlpha() const { return ringBrightAlpha_; }
|
||||||
return levelCount_;
|
|
||||||
}
|
void SetRingDarkAlpha(float alpha);
|
||||||
|
float GetRingDarkAlpha() const { return ringDarkAlpha_; }
|
||||||
void SetLevelHeight(float height);
|
|
||||||
float GetLevelHeihgt() const {
|
void SetConeAlpha(float alpha);
|
||||||
return levelHeight_;
|
float GetConeAlpha() const { return coneAlpha_; }
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void CreateTexturedCone(osg::Geode* geode);
|
void Clear();
|
||||||
|
void Rebuild();
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
osg::ref_ptr<osg::Cone> cone_;
|
osg::ref_ptr<osg::Geometry> coneGeometry_;
|
||||||
osg::ref_ptr<osg::ShapeDrawable> coneDrawable_;
|
osg::ref_ptr<osg::Drawable> coneDrawable_;
|
||||||
osg::ref_ptr<osg::Uniform> baseColorUniform_;
|
osg::ref_ptr<osg::NodeCallback> coneCallback_;
|
||||||
osg::Vec4 baseColor_{ 0.0f, 0.2f, 0.5f, 0.2f };
|
|
||||||
osg::ref_ptr<osg::Uniform> levelCountUniform_;
|
|
||||||
int levelCount_{ 4 };
|
|
||||||
osg::ref_ptr<osg::Uniform> levelHeightUniform_;
|
|
||||||
float levelHeight_{ 500.0f };
|
|
||||||
|
|
||||||
float height_{ 60.0f };
|
float height_{ 6.0f };
|
||||||
float radius_{ 10.0f };
|
float radius_{ 10.0f };
|
||||||
|
|
||||||
|
osg::ref_ptr<osg::Uniform> waveTimeUniform_;
|
||||||
|
osg::ref_ptr<osg::Uniform> waveRadiusUniform_;
|
||||||
|
osg::ref_ptr<osg::Uniform> waveSpeedUniform_;
|
||||||
|
osg::ref_ptr<osg::Uniform> waveCountUniform_;
|
||||||
|
osg::ref_ptr<osg::Uniform> baseColorUniform_;
|
||||||
|
osg::ref_ptr<osg::Uniform> waveColorUniform_;
|
||||||
|
osg::ref_ptr<osg::Uniform> levelHeightUniform_;
|
||||||
|
|
||||||
|
osg::ref_ptr<osg::Uniform> ringBrightAlphaUniform_;
|
||||||
|
osg::ref_ptr<osg::Uniform> ringDarkAlphaUniform_;
|
||||||
|
osg::ref_ptr<osg::Uniform> coneAlphaUniform_;
|
||||||
|
|
||||||
|
float waveRadius_{ 100.0f };
|
||||||
|
float waveSpeed_{ 20.0f };
|
||||||
|
int waveCount_{ 30 };
|
||||||
|
osg::Vec4 baseColor_{ 1.0f, 0.2f, 0.5f, 1.f };
|
||||||
|
osg::Vec4 waveColor_{ 0.0f, 0.5f, 1.0f, 0.8f };
|
||||||
|
double currentTime_{ 0.0 };
|
||||||
|
|
||||||
|
float ringBrightAlpha_{ 0.8f };
|
||||||
|
float ringDarkAlpha_{ 0.3f };
|
||||||
|
float coneAlpha_{ 0.7f };
|
||||||
};
|
};
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include <osg/Node>
|
|
||||||
#include <osg/Geode>
|
|
||||||
#include <osg/MatrixTransform>
|
|
||||||
#include "viewer/UpdateRenderStd.h"
|
|
||||||
|
|
||||||
//三维实体的圆锥波束
|
|
||||||
|
|
||||||
class ConeWave : public osg::Geode
|
|
||||||
, public UpdateRenderStd {
|
|
||||||
public:
|
|
||||||
ConeWave();
|
|
||||||
~ConeWave();
|
|
||||||
|
|
||||||
void clearSelf() ;
|
|
||||||
void Render(double dt) override;
|
|
||||||
|
|
||||||
void createWaveBeamCone(osg::MatrixTransform* node,double angle, double length, osg::Vec4 color, osg::Vec4 lineColor, double lineWidth);
|
|
||||||
|
|
||||||
void changeWaveBeamConeTarget(/*osg::MatrixTransform* mt,*/ double latitude, double longitude, double height, bool ifDynamic);
|
|
||||||
|
|
||||||
void changeWaveBeamConeAppearance(osg::Vec4 color, osg::Vec4 lineColor, double lineWidth);
|
|
||||||
|
|
||||||
osg::ref_ptr<osg::MatrixTransform> getWaveBeamCone() {
|
|
||||||
return _waveBeamCone;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
osg::ref_ptr<osg::MatrixTransform> _waveBeamCone;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -102,7 +102,7 @@ void DashedLine::CreateTexturedCone(osg::Geode* geode) {
|
|||||||
"#version 330\n"
|
"#version 330\n"
|
||||||
"in vec4 osg_Vertex;\n"
|
"in vec4 osg_Vertex;\n"
|
||||||
"in vec2 osg_MultiTexCoord0;\n"
|
"in vec2 osg_MultiTexCoord0;\n"
|
||||||
"uniform mat4 osg_ModelViewProjectionMatrix;\n"//当前OSG摄像机的观察矩阵;
|
"uniform mat4 osg_ModelViewProjectionMatrix;\n"//<EFBFBD><EFBFBD>ǰOSG<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĺ۲<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
"uniform float time;\n"
|
"uniform float time;\n"
|
||||||
"out vec2 texCoord;\n"
|
"out vec2 texCoord;\n"
|
||||||
"void main()\n"
|
"void main()\n"
|
||||||
@ -151,7 +151,8 @@ void DashedLine::UpdateRotaion() {
|
|||||||
float height = direction.length();
|
float height = direction.length();
|
||||||
|
|
||||||
cylinder_->setHeight(height);
|
cylinder_->setHeight(height);
|
||||||
cylinderDrawable_->build();
|
// cylinderDrawable_->b();
|
||||||
|
// cylinderDrawable_-
|
||||||
|
|
||||||
osg::Vec3 center = (start_ + end_) * 0.5f;
|
osg::Vec3 center = (start_ + end_) * 0.5f;
|
||||||
direction.normalize();
|
direction.normalize();
|
||||||
|
|||||||
@ -13,7 +13,7 @@ public:
|
|||||||
~AngleReflexComponent();
|
~AngleReflexComponent();
|
||||||
|
|
||||||
static std::string GetTypeName();
|
static std::string GetTypeName();
|
||||||
std::string GetSelfTypeName() override {
|
std::string GetSelfTypeName() const override {
|
||||||
return AngleReflexComponent::GetTypeName();
|
return AngleReflexComponent::GetTypeName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -13,7 +13,7 @@ public:
|
|||||||
~ChaffBombsComponent();
|
~ChaffBombsComponent();
|
||||||
|
|
||||||
static std::string GetTypeName();
|
static std::string GetTypeName();
|
||||||
std::string GetSelfTypeName() override {
|
std::string GetSelfTypeName() const override {
|
||||||
return ChaffBombsComponent::GetTypeName();
|
return ChaffBombsComponent::GetTypeName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -86,6 +86,10 @@ std::vector<SceneComponent*> Component::GetChildren() const {
|
|||||||
return std::vector<SceneComponent*>();
|
return std::vector<SceneComponent*>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Component::HasComponent(const std::string& name) const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool Component::OnDestroy() {
|
bool Component::OnDestroy() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -94,7 +98,7 @@ std::string Component::GetTypeName() {
|
|||||||
return "Component";
|
return "Component";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Component::GetSelfTypeName() {
|
std::string Component::GetSelfTypeName() const {
|
||||||
return Component::GetTypeName();
|
return Component::GetTypeName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -26,15 +26,17 @@ public:
|
|||||||
virtual bool OnDestroy();
|
virtual bool OnDestroy();
|
||||||
|
|
||||||
static std::string GetTypeName();
|
static std::string GetTypeName();
|
||||||
virtual std::string GetSelfTypeName();
|
virtual std::string GetSelfTypeName() const;
|
||||||
virtual void AttachEntity(class Entity* owner);
|
virtual void AttachEntity(class Entity* owner);
|
||||||
virtual bool AttachTo(class SceneComponent* parent);
|
virtual bool AttachTo(class SceneComponent* parent);
|
||||||
|
virtual bool HasComponent(const std::string& name) const;
|
||||||
class Entity* GetEntity() const {
|
class Entity* GetEntity() const {
|
||||||
return owner_;
|
return owner_;
|
||||||
}
|
}
|
||||||
const QString& GetUUID() const {
|
const QString& GetUUID() const {
|
||||||
return uuid_;
|
return uuid_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void SetUUId(const QString& uuid) {
|
void SetUUId(const QString& uuid) {
|
||||||
|
|||||||
@ -9,6 +9,7 @@
|
|||||||
#include "entities/ChaffBombsComponent.h"
|
#include "entities/ChaffBombsComponent.h"
|
||||||
#include "entities/ConeWaveComponent.h"
|
#include "entities/ConeWaveComponent.h"
|
||||||
#include "entities/DashedLineComponent.h"
|
#include "entities/DashedLineComponent.h"
|
||||||
|
#include "entities/LabelComponent.h"
|
||||||
|
|
||||||
//Component::Component(QObject* parent)
|
//Component::Component(QObject* parent)
|
||||||
// : QObject(parent) {
|
// : QObject(parent) {
|
||||||
@ -36,6 +37,8 @@ SceneComponent* ComponentFactory::Create(const QString& name, SceneComponent* pa
|
|||||||
return new ConeWaveComponent(parenet);
|
return new ConeWaveComponent(parenet);
|
||||||
} else if ("DashedLineComponent" == name) {
|
} else if ("DashedLineComponent" == name) {
|
||||||
return new DashedLineComponent(parenet);
|
return new DashedLineComponent(parenet);
|
||||||
|
} else if ("LabelComponent" == name) {
|
||||||
|
return new LabelComponent(parenet);
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,16 +13,12 @@
|
|||||||
|
|
||||||
ConeWaveComponent::ConeWaveComponent(SceneComponent* parent)
|
ConeWaveComponent::ConeWaveComponent(SceneComponent* parent)
|
||||||
: SceneComponent(parent) {
|
: SceneComponent(parent) {
|
||||||
// coneWave_ = new ConeWave();
|
coneWave_ = new ConeWave();
|
||||||
// coneWave_->InitGeode();
|
coneWave_->InitGeode();
|
||||||
|
|
||||||
colorMap_[1] = osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
|
|
||||||
colorMap_[2] = osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
|
|
||||||
colorMap_[3] = osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ConeWaveComponent::~ConeWaveComponent() {
|
ConeWaveComponent::~ConeWaveComponent() {
|
||||||
// coneWave_->Destory();
|
coneWave_->Destory();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ConeWaveComponent::GetTypeName() {
|
std::string ConeWaveComponent::GetTypeName() {
|
||||||
@ -30,47 +26,32 @@ std::string ConeWaveComponent::GetTypeName() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool ConeWaveComponent::SetAttribute(const char* name, const char* value) {
|
bool ConeWaveComponent::SetAttribute(const char* name, const char* value) {
|
||||||
if (0 == strcmp("color1" ,name)) {
|
if (0 == strcmp("radius", name)) {
|
||||||
AddColor(1, StringUtils::StringToVec4(value));
|
|
||||||
} else if (0 == strcmp("color2" ,name)) {
|
|
||||||
AddColor(2, StringUtils::StringToVec4(value));
|
|
||||||
}else if (0 == strcmp("color3" ,name)) {
|
|
||||||
AddColor(3, StringUtils::StringToVec4(value));
|
|
||||||
} else if (0 == strcmp("radius", name)) {
|
|
||||||
SetRadius(atof(value));
|
SetRadius(atof(value));
|
||||||
} else if (0 == strcmp("height", name)) {
|
} else if (0 == strcmp("height", name)) {
|
||||||
SetHeight(atof(value));
|
SetHeight(atof(value));
|
||||||
} else if (0 == strcmp("event", name)) {
|
} else if (0 == strcmp("event", name)) {
|
||||||
SetTimeAction(value);
|
SetTimeAction(value);
|
||||||
} else if (0 == strcmp("levelCount", name)) {
|
} else if (0 == strcmp("waveRadius", name)) {
|
||||||
SetLevelCount(atof(value));
|
SetWaveRadius(atof(value));
|
||||||
} else if (0 == strcmp("levelHeihgt", name)) {
|
} else if (0 == strcmp("waveSpeed", name)) {
|
||||||
SetLevelHeight(atof(value));
|
SetWaveSpeed(atof(value));
|
||||||
|
} else if (0 == strcmp("waveCount", name)) {
|
||||||
|
SetWaveCount(atoi(value));
|
||||||
|
} else if (0 == strcmp("waveColor", name)) {
|
||||||
|
SetWaveColor(StringUtils::StringToVec4(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
return SceneComponent::SetAttribute(name, value);
|
return SceneComponent::SetAttribute(name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ConeWaveComponent::SaveAttribute(tinyxml2::XMLElement* element) {
|
bool ConeWaveComponent::SaveAttribute(tinyxml2::XMLElement* element) {
|
||||||
if (colorMap_.find(1) != colorMap_.end()) {
|
|
||||||
element->SetAttribute("color1", StringUtils::Vec4ToString(colorMap_[1]).c_str());
|
|
||||||
} else {
|
|
||||||
element->SetAttribute("color1", StringUtils::Vec4ToString(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f)).c_str());
|
|
||||||
}
|
|
||||||
if (colorMap_.find(2) != colorMap_.end()) {
|
|
||||||
element->SetAttribute("color2", StringUtils::Vec4ToString(colorMap_[2]).c_str());
|
|
||||||
} else {
|
|
||||||
element->SetAttribute("color2", StringUtils::Vec4ToString(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f)).c_str());
|
|
||||||
}
|
|
||||||
if (colorMap_.find(3) != colorMap_.end()) {
|
|
||||||
element->SetAttribute("color3", StringUtils::Vec4ToString(colorMap_[3]).c_str());
|
|
||||||
} else {
|
|
||||||
element->SetAttribute("color3", StringUtils::Vec4ToString(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f)).c_str());
|
|
||||||
}
|
|
||||||
element->SetAttribute("radius", std::to_string(GetRadius()).c_str());
|
element->SetAttribute("radius", std::to_string(GetRadius()).c_str());
|
||||||
element->SetAttribute("height", std::to_string(GetHeight()).c_str());
|
element->SetAttribute("height", std::to_string(GetHeight()).c_str());
|
||||||
element->SetAttribute("levelCount", std::to_string(GetLevelCount()).c_str());
|
element->SetAttribute("waveRadius", std::to_string(GetWaveRadius()).c_str());
|
||||||
element->SetAttribute("levelHeihgt", std::to_string(GetLevelHeight()).c_str());
|
element->SetAttribute("waveSpeed", std::to_string(GetWaveSpeed()).c_str());
|
||||||
|
element->SetAttribute("waveCount", std::to_string(GetWaveCount()).c_str());
|
||||||
|
element->SetAttribute("waveColor", StringUtils::Vec4ToString(GetWaveColor()).c_str());
|
||||||
element->SetAttribute("event", timeAction_ == nullptr ? "" : timeAction_->GetPath().toStdString().c_str());
|
element->SetAttribute("event", timeAction_ == nullptr ? "" : timeAction_->GetPath().toStdString().c_str());
|
||||||
return SceneComponent::SaveAttribute(element);
|
return SceneComponent::SaveAttribute(element);
|
||||||
}
|
}
|
||||||
@ -81,78 +62,36 @@ void ConeWaveComponent::Begin() {
|
|||||||
|
|
||||||
void ConeWaveComponent::Update(double dt) {
|
void ConeWaveComponent::Update(double dt) {
|
||||||
UpdateEvent();
|
UpdateEvent();
|
||||||
|
if (coneWave_.valid()) {
|
||||||
|
coneWave_->Render(dt);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConeWaveComponent::SetHeight(float height) {
|
void ConeWaveComponent::SetHeight(float height) {
|
||||||
// coneWave_->SetHeight(height);
|
coneWave_->SetHeight(height);
|
||||||
// if (nullptr != mt_) {
|
// if (nullptr != mt_) {
|
||||||
// mt_->setMatrix(osg::Matrix::translate(osg::Vec3(0.0f, 0.0f, -coneWave_->GetHeght() * 0.75f)));
|
// mt_->setMatrix(osg::Matrix::translate(osg::Vec3(0.0f, 0.0f, -coneWave_->GetHeght() * 0.75f)));
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
float ConeWaveComponent::GetHeight() const {
|
float ConeWaveComponent::GetHeight() const {
|
||||||
return 0;// coneWave_->GetHeght();
|
return coneWave_->GetHeght();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConeWaveComponent::SetRadius(float radius) {
|
void ConeWaveComponent::SetRadius(float radius) {
|
||||||
// coneWave_->SetRadius(radius);
|
coneWave_->SetWaveRadius(radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
float ConeWaveComponent::GetRadius() const {
|
float ConeWaveComponent::GetRadius() const {
|
||||||
return 0;// return coneWave_->GetRadius();
|
return coneWave_->GetWaveRadius();
|
||||||
}
|
|
||||||
|
|
||||||
void ConeWaveComponent::SetLevelCount(int count) {
|
|
||||||
// coneWave_->SetLevelCount(count);
|
|
||||||
}
|
|
||||||
|
|
||||||
float ConeWaveComponent::GetLevelCount() const {
|
|
||||||
return 0; // return coneWave_->GetLevelCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConeWaveComponent::SetLevelHeight(float height) {
|
|
||||||
// coneWave_->SetLevelHeight(height);
|
|
||||||
}
|
|
||||||
|
|
||||||
float ConeWaveComponent::GetLevelHeight() const {
|
|
||||||
// return coneWave_->GetLevelHeihgt();
|
|
||||||
return 0.0f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConeWaveComponent::SetBaseColor(const osg::Vec4& color) {
|
void ConeWaveComponent::SetBaseColor(const osg::Vec4& color) {
|
||||||
// coneWave_->SetBaseColor(color);
|
coneWave_->SetBaseColor(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
const osg::Vec4 ConeWaveComponent::GetBaseColor() const {
|
const osg::Vec4 ConeWaveComponent::GetBaseColor() const {
|
||||||
// return coneWave_->GetBaseColor();
|
return coneWave_->GetBaseColor();
|
||||||
return osg::Vec4();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConeWaveComponent::SetColor1(const osg::Vec4& color) {
|
|
||||||
colorMap_[1] = color;
|
|
||||||
}
|
|
||||||
|
|
||||||
const osg::Vec4 ConeWaveComponent::GetColor1() const {
|
|
||||||
const auto color = colorMap_.find(1);
|
|
||||||
return color->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConeWaveComponent::SetColor2(const osg::Vec4& color) {
|
|
||||||
colorMap_[2] = color;
|
|
||||||
}
|
|
||||||
|
|
||||||
const osg::Vec4 ConeWaveComponent::GetColor2() const {
|
|
||||||
const auto color = colorMap_.find(2);
|
|
||||||
return color->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConeWaveComponent::SetColor3(const osg::Vec4& color) {
|
|
||||||
colorMap_[3] = color;
|
|
||||||
}
|
|
||||||
|
|
||||||
const osg::Vec4 ConeWaveComponent::GetColor3() const {
|
|
||||||
const auto color = colorMap_.find(3);
|
|
||||||
return color->second;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConeWaveComponent::SetTimeAction(const QString& path) {
|
void ConeWaveComponent::SetTimeAction(const QString& path) {
|
||||||
@ -171,8 +110,8 @@ void ConeWaveComponent::AddToRender() {
|
|||||||
|
|
||||||
void ConeWaveComponent::Initialize() {
|
void ConeWaveComponent::Initialize() {
|
||||||
mt_ = new osg::MatrixTransform;
|
mt_ = new osg::MatrixTransform;
|
||||||
|
|
||||||
mt_->addChild(coneWave_);
|
mt_->addChild(coneWave_);
|
||||||
// mt_->setMatrix(osg::Matrix::translate(osg::Vec3(0.0f, 0.0f, -coneWave_->GetHeght() * 0.75f)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConeWaveComponent::UpdateEvent() {
|
void ConeWaveComponent::UpdateEvent() {
|
||||||
@ -194,34 +133,98 @@ void ConeWaveComponent::UpdateEvent() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
currentStatus_ = lampStatus->GetCurrent();
|
currentStatus_ = lampStatus->GetCurrent();
|
||||||
if (colorMap_.find(currentStatus_) == colorMap_.end()) {
|
|
||||||
coneWave_->setNodeMask(0x0);
|
Timestep* timeStep = workspace->GetTimestep();
|
||||||
|
if (nullptr == timeStep) {
|
||||||
|
LOG_WARN("timeStep is nullptr");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::Vec4& color = colorMap_[currentStatus_];
|
double dt = timeStep->GetCurrent();
|
||||||
// coneWave_->SetBaseColor(color);
|
int value = timeAction_->GetValue(dt);
|
||||||
coneWave_->setNodeMask(0xff);
|
if (-1 == value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
//Timestep* timeStep = workspace->GetTimestep();
|
|
||||||
//if (nullptr == timeStep) {
|
|
||||||
// LOG_WARN("timeStep is nullptr");
|
|
||||||
// return;
|
|
||||||
//}
|
|
||||||
|
|
||||||
//double dt = timeStep->GetCurrent();
|
|
||||||
//int value = timeAction_->GetValue(dt);
|
|
||||||
//if (-1 == value) {
|
|
||||||
// return;
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
|
|
||||||
//coneWave_->setNodeMask(value == 0 ? 0x0 : 0xff);
|
|
||||||
|
|
||||||
|
coneWave_->setNodeMask(value == 0 ? 0x0 : 0xff);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConeWaveComponent::AddColor(int32_t status, const osg::Vec4& color) {
|
void ConeWaveComponent::SetWaveRadius(float radius) {
|
||||||
colorMap_[status] = color;
|
if (coneWave_.valid()) {
|
||||||
|
coneWave_->SetWaveRadius(radius);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float ConeWaveComponent::GetWaveRadius() const {
|
||||||
|
if (coneWave_.valid()) {
|
||||||
|
return coneWave_->GetWaveRadius();
|
||||||
|
}
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConeWaveComponent::SetWaveSpeed(float speed) {
|
||||||
|
if (coneWave_.valid()) {
|
||||||
|
coneWave_->SetWaveSpeed(speed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float ConeWaveComponent::GetWaveSpeed() const {
|
||||||
|
if (coneWave_.valid()) {
|
||||||
|
return coneWave_->GetWaveSpeed();
|
||||||
|
}
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConeWaveComponent::SetWaveCount(int count) {
|
||||||
|
if (coneWave_.valid()) {
|
||||||
|
coneWave_->SetWaveCount(count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int ConeWaveComponent::GetWaveCount() const {
|
||||||
|
if (coneWave_.valid()) {
|
||||||
|
return coneWave_->GetWaveCount();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConeWaveComponent::SetWaveColor(const osg::Vec4& color) {
|
||||||
|
if (coneWave_.valid()) {
|
||||||
|
coneWave_->SetWaveColor(color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const osg::Vec4& ConeWaveComponent::GetWaveColor() const {
|
||||||
|
static osg::Vec4 defaultColor(0.0f, 0.5f, 1.0f, 0.8f);
|
||||||
|
if (coneWave_.valid()) {
|
||||||
|
return coneWave_->GetWaveColor();
|
||||||
|
}
|
||||||
|
return defaultColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConeWaveComponent::SetRingBrightAlpha(float alpha) {
|
||||||
|
if (coneWave_.valid()) {
|
||||||
|
coneWave_->SetRingBrightAlpha(alpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float ConeWaveComponent::GetRingBrightAlpha() const {
|
||||||
|
if (coneWave_.valid()) {
|
||||||
|
return coneWave_->GetRingBrightAlpha();
|
||||||
|
}
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConeWaveComponent::SetRingDarkAlpha(float alpha) {
|
||||||
|
if (coneWave_.valid()) {
|
||||||
|
coneWave_->SetRingDarkAlpha(alpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float ConeWaveComponent::GetRingDarkAlpha() const {
|
||||||
|
if (coneWave_.valid()) {
|
||||||
|
return coneWave_->GetRingDarkAlpha();
|
||||||
|
}
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|||||||
@ -15,7 +15,7 @@ public:
|
|||||||
~ConeWaveComponent();
|
~ConeWaveComponent();
|
||||||
|
|
||||||
static std::string GetTypeName();
|
static std::string GetTypeName();
|
||||||
std::string GetSelfTypeName() override {
|
std::string GetSelfTypeName() const override {
|
||||||
return ConeWaveComponent::GetTypeName();
|
return ConeWaveComponent::GetTypeName();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,23 +31,24 @@ public:
|
|||||||
void SetRadius(float radius);
|
void SetRadius(float radius);
|
||||||
float GetRadius() const;
|
float GetRadius() const;
|
||||||
|
|
||||||
void SetLevelCount(int count);
|
|
||||||
float GetLevelCount() const;
|
|
||||||
|
|
||||||
void SetLevelHeight(float height);
|
|
||||||
float GetLevelHeight() const;
|
|
||||||
|
|
||||||
void SetBaseColor(const osg::Vec4& color);
|
void SetBaseColor(const osg::Vec4& color);
|
||||||
const osg::Vec4 GetBaseColor() const;
|
const osg::Vec4 GetBaseColor() const;
|
||||||
|
void SetWaveColor(const osg::Vec4& color);
|
||||||
|
const osg::Vec4& GetWaveColor() const;
|
||||||
|
|
||||||
void SetColor1(const osg::Vec4& color);
|
void SetWaveRadius(float radius);
|
||||||
const osg::Vec4 GetColor1() const;
|
float GetWaveRadius() const;
|
||||||
|
|
||||||
|
void SetWaveSpeed(float speed);
|
||||||
|
float GetWaveSpeed() const;
|
||||||
|
|
||||||
|
void SetWaveCount(int count);
|
||||||
|
int GetWaveCount() const;
|
||||||
|
|
||||||
void SetColor2(const osg::Vec4& color);
|
void SetRingBrightAlpha(float alpha);
|
||||||
const osg::Vec4 GetColor2() const;
|
float GetRingBrightAlpha() const;
|
||||||
|
void SetRingDarkAlpha(float alpha);
|
||||||
void SetColor3(const osg::Vec4& color);
|
float GetRingDarkAlpha() const;
|
||||||
const osg::Vec4 GetColor3() const;
|
|
||||||
|
|
||||||
void SetTimeAction(const QString& path);
|
void SetTimeAction(const QString& path);
|
||||||
|
|
||||||
@ -55,11 +56,9 @@ protected:
|
|||||||
void AddToRender() override;
|
void AddToRender() override;
|
||||||
void Initialize();
|
void Initialize();
|
||||||
void UpdateEvent();
|
void UpdateEvent();
|
||||||
void AddColor(int32_t status, const osg::Vec4& color);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
osg::ref_ptr<class ConeWave> coneWave_;
|
osg::ref_ptr<class ConeWave> coneWave_;
|
||||||
std::unordered_map<int32_t, osg::Vec4> colorMap_;
|
|
||||||
class TimeAction* timeAction_{ nullptr };
|
class TimeAction* timeAction_{ nullptr };
|
||||||
int currentStatus_{ 0 };
|
int currentStatus_{ 0 };
|
||||||
};
|
};
|
||||||
|
|||||||
@ -13,7 +13,7 @@ public:
|
|||||||
~DashedLineComponent();
|
~DashedLineComponent();
|
||||||
|
|
||||||
static std::string GetTypeName();
|
static std::string GetTypeName();
|
||||||
std::string GetSelfTypeName() override {
|
std::string GetSelfTypeName() const override {
|
||||||
return DashedLineComponent::GetTypeName();
|
return DashedLineComponent::GetTypeName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -7,6 +7,8 @@
|
|||||||
#include "common/SpdLogger.h"
|
#include "common/SpdLogger.h"
|
||||||
#include "entities/Entity.h"
|
#include "entities/Entity.h"
|
||||||
#include "entities/ComponentFactory.h"
|
#include "entities/ComponentFactory.h"
|
||||||
|
#include "entities/EntityFactory.h"
|
||||||
|
#include "entities/EntityRegistration.h"
|
||||||
|
|
||||||
#include "xml/tinyxml2.h"
|
#include "xml/tinyxml2.h"
|
||||||
|
|
||||||
@ -14,6 +16,7 @@ template<> EntitiesManager* Singleton<EntitiesManager>::instance_ = nullptr;
|
|||||||
|
|
||||||
EntitiesManager::EntitiesManager(QObject* parent)
|
EntitiesManager::EntitiesManager(QObject* parent)
|
||||||
: QObject(parent) {
|
: QObject(parent) {
|
||||||
|
Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
EntitiesManager::~EntitiesManager() {
|
EntitiesManager::~EntitiesManager() {
|
||||||
@ -106,9 +109,6 @@ Entity* EntitiesManager::CreateMesh(const QString& mesh) {
|
|||||||
SceneComponent* conponent = ComponentFactory::Create("MeshComponent", nullptr);
|
SceneComponent* conponent = ComponentFactory::Create("MeshComponent", nullptr);
|
||||||
conponent->SetAttribute("mesh", mesh.toStdString().c_str());
|
conponent->SetAttribute("mesh", mesh.toStdString().c_str());
|
||||||
conponent->AttachEntity(entity);
|
conponent->AttachEntity(entity);
|
||||||
|
|
||||||
//conponent = ComponentFactory::Create("PathComponent", conponent);
|
|
||||||
//conponent->AttachEntity(entity);
|
|
||||||
|
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
@ -148,3 +148,78 @@ void EntitiesManager::RemoveEntity(Entity* entity) {
|
|||||||
|
|
||||||
entities_.erase(entity->GetUUid());
|
entities_.erase(entity->GetUUid());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EntitiesManager::Initialize() {
|
||||||
|
if (!initialized_) {
|
||||||
|
EntityRegistration::RegisterAllEntities();
|
||||||
|
initialized_ = true;
|
||||||
|
LOG_INFO("EntitiesManager::Initialize - Entity factory initialized");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity* EntitiesManager::CreateEntity(const QString& type, WorkSpace* workspace) {
|
||||||
|
if (!initialized_) {
|
||||||
|
Initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!workspace) {
|
||||||
|
workspace = WorkSpaceManager::Get().GetCurrent();
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity* entity = EntityFactory::Get().CreateEntity(type, workspace);
|
||||||
|
if (entity) {
|
||||||
|
AddEntity(entity);
|
||||||
|
if (workspace) {
|
||||||
|
workspace->AddEntity(entity);
|
||||||
|
}
|
||||||
|
LOG_INFO("EntitiesManager::CreateEntity - Created entity of type: {}", type.toStdString());
|
||||||
|
} else {
|
||||||
|
LOG_ERROR("EntitiesManager::CreateEntity - Failed to create entity of type: {}", type.toStdString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity* EntitiesManager::CreateEntityWithComponents(const QString& type, const QString& mesh, bool useLabel, WorkSpace* workspace) {
|
||||||
|
if (!initialized_) {
|
||||||
|
Initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!workspace) {
|
||||||
|
workspace = WorkSpaceManager::Get().GetCurrent();
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity* entity = EntityFactory::Get().CreateEntityWithComponents(type, mesh, useLabel, workspace);
|
||||||
|
if (entity) {
|
||||||
|
AddEntity(entity);
|
||||||
|
if (workspace) {
|
||||||
|
workspace->AddEntity(entity);
|
||||||
|
}
|
||||||
|
LOG_INFO("EntitiesManager::CreateEntityWithComponents - Created entity with components of type: {}", type.toStdString());
|
||||||
|
} else {
|
||||||
|
LOG_ERROR("EntitiesManager::CreateEntityWithComponents - Failed to create entity of type: {}", type.toStdString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList EntitiesManager::GetSupportedEntityTypes() const {
|
||||||
|
if (!initialized_) {
|
||||||
|
return QStringList();
|
||||||
|
}
|
||||||
|
return EntityFactory::Get().GetRegisteredTypes();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString EntitiesManager::GetEntityDisplayName(const QString& type) const {
|
||||||
|
if (!initialized_) {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
return EntityFactory::Get().GetDisplayName(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString EntitiesManager::GetEntityDescription(const QString& type) const {
|
||||||
|
if (!initialized_) {
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
return EntityFactory::Get().GetDescription(type);
|
||||||
|
}
|
||||||
|
|||||||
@ -9,6 +9,7 @@
|
|||||||
#include "xml/tinyxml2.h"
|
#include "xml/tinyxml2.h"
|
||||||
|
|
||||||
class Entity;
|
class Entity;
|
||||||
|
class WorkSpace;
|
||||||
|
|
||||||
class EntitiesManager : public QObject, public Singleton<EntitiesManager> {
|
class EntitiesManager : public QObject, public Singleton<EntitiesManager> {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -18,12 +19,26 @@ public:
|
|||||||
~EntitiesManager();
|
~EntitiesManager();
|
||||||
void OnDestory();
|
void OnDestory();
|
||||||
|
|
||||||
|
// Initialize entity factory
|
||||||
|
void Initialize();
|
||||||
|
|
||||||
bool Contains(const QString& name) const;
|
bool Contains(const QString& name) const;
|
||||||
|
|
||||||
bool Parse(const tinyxml2::XMLElement* element, class WorkSpace* workspce);
|
bool Parse(const tinyxml2::XMLElement* element, class WorkSpace* workspce);
|
||||||
|
|
||||||
|
// Legacy methods (for backward compatibility)
|
||||||
Entity* Create(const QString& name);
|
Entity* Create(const QString& name);
|
||||||
Entity* CreateMesh(const QString& mesh);
|
Entity* CreateMesh(const QString& mesh);
|
||||||
|
|
||||||
|
// New factory methods
|
||||||
|
Entity* CreateEntity(const QString& type, WorkSpace* workspace = nullptr);
|
||||||
|
Entity* CreateEntityWithComponents(const QString& type, const QString& mesh, bool useLabel, WorkSpace* workspace = nullptr);
|
||||||
|
|
||||||
|
// Get supported entity types
|
||||||
|
QStringList GetSupportedEntityTypes() const;
|
||||||
|
QString GetEntityDisplayName(const QString& type) const;
|
||||||
|
QString GetEntityDescription(const QString& type) const;
|
||||||
|
|
||||||
bool DeleteEntity(Entity* entity);
|
bool DeleteEntity(Entity* entity);
|
||||||
|
|
||||||
Entity* GetEntity(const QString& uuid);
|
Entity* GetEntity(const QString& uuid);
|
||||||
@ -36,5 +51,5 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_map<QString, Entity*> entities_;
|
std::unordered_map<QString, Entity*> entities_;
|
||||||
|
bool initialized_{false};
|
||||||
};
|
};
|
||||||
@ -1,6 +1,8 @@
|
|||||||
#include "entities/Entity.h"
|
#include "entities/Entity.h"
|
||||||
|
|
||||||
#include <QUuid>
|
#include <QUuid>
|
||||||
|
// Ensure QVariant can hold and convert Entity* in signals/slots
|
||||||
|
Q_DECLARE_METATYPE(Entity*)
|
||||||
|
|
||||||
#include "common/SpdLogger.h"
|
#include "common/SpdLogger.h"
|
||||||
#include "entities/SceneComponent.h"
|
#include "entities/SceneComponent.h"
|
||||||
@ -182,3 +184,32 @@ void Entity::SetParent(Entity* parent) {
|
|||||||
SetWorkspace(workSpace);
|
SetWorkspace(workSpace);
|
||||||
parent_->childer_.push_back(this);
|
parent_->childer_.push_back(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Entity::HasComponent(const std::string& name) const {
|
||||||
|
if (nullptr == rootComponet_) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return rootComponet_->HasComponent(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Entity::SetVisible(bool v) {
|
||||||
|
LOG_INFO("set visible: {}", v);
|
||||||
|
if (nullptr == rootComponet_) {
|
||||||
|
LOG_WARN("rootComponet_ is nullptr");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rootComponet_->SetVisible(v);
|
||||||
|
for (auto item : childer_) {
|
||||||
|
item->SetVisible(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Entity::IsVisible() const {
|
||||||
|
if (nullptr == rootComponet_) {
|
||||||
|
LOG_WARN("rootComponet_ is nullptr");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rootComponet_->IsVisible();
|
||||||
|
}
|
||||||
|
|||||||
@ -56,6 +56,8 @@ public:
|
|||||||
return rootComponet_->GetComponent();
|
return rootComponet_->GetComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool HasComponent(const std::string& name) const;
|
||||||
|
|
||||||
void SetRootComponent(SceneComponent* root) {
|
void SetRootComponent(SceneComponent* root) {
|
||||||
rootComponet_ = root;
|
rootComponet_ = root;
|
||||||
}
|
}
|
||||||
@ -68,6 +70,9 @@ public:
|
|||||||
return childer_;
|
return childer_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetVisible(bool v);
|
||||||
|
bool IsVisible() const;
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void NameChanged(const QString& name);
|
void NameChanged(const QString& name);
|
||||||
|
|
||||||
|
|||||||
129
src/entities/EntityFactory.cpp
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
#include "entities/EntityFactory.h"
|
||||||
|
#include "entities/ComponentFactory.h"
|
||||||
|
#include "common/SpdLogger.h"
|
||||||
|
#include "workspace/WorkSpace.h"
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
|
template<> EntityFactory* Singleton<EntityFactory>::instance_ = nullptr;
|
||||||
|
|
||||||
|
Entity* EntityFactory::CreateEntity(const QString& type, WorkSpace* workspace) {
|
||||||
|
auto it = creators_.find(type);
|
||||||
|
if (it == creators_.end()) {
|
||||||
|
LOG_WARN("EntityFactory::CreateEntity - Unknown entity type: {}", type.toStdString());
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity* entity = it->second->CreateEntity(workspace);
|
||||||
|
if (!entity) {
|
||||||
|
LOG_ERROR("EntityFactory::CreateEntity - Failed to create entity of type: {}", type.toStdString());
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_INFO("EntityFactory::CreateEntity - Successfully created entity of type: {}", type.toStdString());
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity* EntityFactory::CreateEntityWithComponents(const QString& type, const QString& mesh, bool useLabel, WorkSpace* workspace) {
|
||||||
|
Entity* entity = CreateEntity(type, workspace);
|
||||||
|
if (!entity) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto it = creators_.find(type);
|
||||||
|
if (it == creators_.end()) {
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get default mesh
|
||||||
|
QString defaultMesh = it->second->GetDefaultMesh();
|
||||||
|
if (!mesh.isEmpty()) {
|
||||||
|
defaultMesh = mesh;
|
||||||
|
}
|
||||||
|
if (!defaultMesh.isEmpty()) {
|
||||||
|
SceneComponent* meshComponent = ComponentFactory::Create("MeshComponent", nullptr);
|
||||||
|
if (meshComponent) {
|
||||||
|
meshComponent->SetAttribute("mesh", defaultMesh.toLocal8Bit());
|
||||||
|
meshComponent->AttachEntity(entity);
|
||||||
|
LOG_INFO("EntityFactory::CreateEntityWithComponents - Added MeshComponent with mesh: {}", defaultMesh.toStdString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (useLabel) {
|
||||||
|
SceneComponent* rootComponent = entity->GetRootComponent();
|
||||||
|
if (nullptr == rootComponent) {
|
||||||
|
SceneComponent* meshComponent = ComponentFactory::Create("LabelComponent", nullptr);
|
||||||
|
if (meshComponent) {
|
||||||
|
meshComponent->AttachEntity(entity);
|
||||||
|
LOG_INFO("EntityFactory::CreateEntityWithComponents - Added LabelComponent with mesh: {}", defaultMesh.toStdString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SceneComponent* LabelComponent = ComponentFactory::Create("LabelComponent", rootComponent);
|
||||||
|
if (LabelComponent) {
|
||||||
|
LabelComponent->AttachTo(rootComponent);
|
||||||
|
LOG_INFO("EntityFactory::CreateEntityWithComponents - Added LabelComponent with mesh: {}", defaultMesh.toStdString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add required components
|
||||||
|
QStringList requiredComponents = it->second->GetRequiredComponents();
|
||||||
|
SceneComponent* rootComponent = entity->GetRootComponent();
|
||||||
|
|
||||||
|
for (int i = 0; i < requiredComponents.size(); ++i) {
|
||||||
|
QString componentType = requiredComponents.at(i);
|
||||||
|
SceneComponent* component = ComponentFactory::Create(componentType, rootComponent);
|
||||||
|
if (component && rootComponent) {
|
||||||
|
component->AttachTo(rootComponent);
|
||||||
|
LOG_INFO("EntityFactory::CreateEntityWithComponents - Added component: {}", componentType.toStdString());
|
||||||
|
} else {
|
||||||
|
LOG_WARN("EntityFactory::CreateEntityWithComponents - Failed to create component: {}", componentType.toStdString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList EntityFactory::GetRegisteredTypes() const {
|
||||||
|
QStringList types;
|
||||||
|
for (auto it = creators_.begin(); it != creators_.end(); ++it) {
|
||||||
|
types.append(it->first);
|
||||||
|
}
|
||||||
|
return types;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString EntityFactory::GetDisplayName(const QString& type) const {
|
||||||
|
auto it = creators_.find(type);
|
||||||
|
if (it != creators_.end()) {
|
||||||
|
return it->second->GetDisplayName();
|
||||||
|
}
|
||||||
|
return type; // 返回类型名作为默认显示名
|
||||||
|
}
|
||||||
|
|
||||||
|
QString EntityFactory::GetDescription(const QString& type) const {
|
||||||
|
auto it = creators_.find(type);
|
||||||
|
if (it != creators_.end()) {
|
||||||
|
return it->second->GetDescription();
|
||||||
|
}
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString EntityFactory::GetDefaultMesh(const QString& type) const {
|
||||||
|
auto it = creators_.find(type);
|
||||||
|
if (it != creators_.end()) {
|
||||||
|
return it->second->GetDefaultMesh();
|
||||||
|
}
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList EntityFactory::GetRequiredComponents(const QString& type) const {
|
||||||
|
auto it = creators_.find(type);
|
||||||
|
if (it != creators_.end()) {
|
||||||
|
return it->second->GetRequiredComponents();
|
||||||
|
}
|
||||||
|
return QStringList();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EntityFactory::IsTypeSupported(const QString& type) const {
|
||||||
|
return creators_.find(type) != creators_.end();
|
||||||
|
}
|
||||||
86
src/entities/EntityFactory.h
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <memory>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
#include "app/Singleton.h"
|
||||||
|
#include "entities/Entity.h"
|
||||||
|
|
||||||
|
class WorkSpace;
|
||||||
|
|
||||||
|
class IEntityCreator {
|
||||||
|
public:
|
||||||
|
virtual ~IEntityCreator() = default;
|
||||||
|
virtual Entity* CreateEntity(WorkSpace* workspace) = 0;
|
||||||
|
virtual QString GetEntityType() const = 0;
|
||||||
|
virtual QString GetDisplayName() const = 0;
|
||||||
|
virtual QString GetDescription() const = 0;
|
||||||
|
virtual QString GetDefaultMesh() const = 0;
|
||||||
|
virtual QStringList GetRequiredComponents() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class EntityCreator : public IEntityCreator {
|
||||||
|
public:
|
||||||
|
EntityCreator(const QString& type, const QString& displayName,
|
||||||
|
const QString& description, const QString& defaultMesh,
|
||||||
|
const QStringList& requiredComponents = QStringList())
|
||||||
|
: entityType_(type), displayName_(displayName), description_(description),
|
||||||
|
defaultMesh_(defaultMesh), requiredComponents_(requiredComponents) {}
|
||||||
|
|
||||||
|
Entity* CreateEntity(WorkSpace* workspace) override {
|
||||||
|
return new T(workspace);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString GetEntityType() const override { return entityType_; }
|
||||||
|
QString GetDisplayName() const override { return displayName_; }
|
||||||
|
QString GetDescription() const override { return description_; }
|
||||||
|
QString GetDefaultMesh() const override { return defaultMesh_; }
|
||||||
|
QStringList GetRequiredComponents() const override { return requiredComponents_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString entityType_;
|
||||||
|
QString displayName_;
|
||||||
|
QString description_;
|
||||||
|
QString defaultMesh_;
|
||||||
|
QStringList requiredComponents_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class EntityFactory : public Singleton<EntityFactory> {
|
||||||
|
public:
|
||||||
|
EntityFactory() = default;
|
||||||
|
explicit EntityFactory(class Application* app) : app_(app) {}
|
||||||
|
~EntityFactory() = default;
|
||||||
|
|
||||||
|
void OnDestory() { }
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void RegisterEntity(const QString& type, const QString& displayName,
|
||||||
|
const QString& description, const QString& defaultMesh,
|
||||||
|
const QStringList& requiredComponents = QStringList()) {
|
||||||
|
auto creator = std::make_unique<EntityCreator<T>>(type, displayName, description, defaultMesh, requiredComponents);
|
||||||
|
creators_[type] = std::move(creator);
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity* CreateEntity(const QString& type, WorkSpace* workspace);
|
||||||
|
|
||||||
|
Entity* CreateEntityWithComponents(const QString& type, const QString& mesh, bool useLabel, WorkSpace* workspace);
|
||||||
|
|
||||||
|
QStringList GetRegisteredTypes() const;
|
||||||
|
|
||||||
|
QString GetDisplayName(const QString& type) const;
|
||||||
|
QString GetDescription(const QString& type) const;
|
||||||
|
QString GetDefaultMesh(const QString& type) const;
|
||||||
|
QStringList GetRequiredComponents(const QString& type) const;
|
||||||
|
|
||||||
|
bool IsTypeSupported(const QString& type) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unordered_map<QString, std::unique_ptr<IEntityCreator>> creators_;
|
||||||
|
class Application* app_ = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define REGISTER_ENTITY(EntityClass, Type, DisplayName, Description, DefaultMesh, ...) \
|
||||||
|
EntityFactory::Get().RegisterEntity<EntityClass>(Type, DisplayName, Description, DefaultMesh, QStringList{__VA_ARGS__})
|
||||||
88
src/entities/EntityRegistration.cpp
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
#include "entities/EntityRegistration.h"
|
||||||
|
#include "common/SpdLogger.h"
|
||||||
|
|
||||||
|
void EntityRegistration::RegisterAllEntities() {
|
||||||
|
EntityFactory& factory = EntityFactory::Get();
|
||||||
|
|
||||||
|
// Register missile entity
|
||||||
|
factory.RegisterEntity<MissileEntity>("Missile",
|
||||||
|
"Missile",
|
||||||
|
"Military missile entity with target tracking and flight capabilities",
|
||||||
|
"models/missile.osg",
|
||||||
|
QStringList() << "LabelComponent" << "TrajectoryComponent"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Register satellite entity
|
||||||
|
factory.RegisterEntity<SatelliteEntity>("Satellite",
|
||||||
|
"Satellite",
|
||||||
|
"Artificial satellite entity with orbital motion and communication capabilities",
|
||||||
|
"models/satellite.osg",
|
||||||
|
QStringList() << "LabelComponent" << "ConeWaveComponent" << "OrbitComponent"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Register ship entity
|
||||||
|
factory.RegisterEntity<ShipEntity>("Ship",
|
||||||
|
"Ship",
|
||||||
|
"Naval vessel entity with maritime navigation and combat capabilities",
|
||||||
|
"models/ship.osg",
|
||||||
|
QStringList() << "LabelComponent" << "NavigationComponent"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Register radar entity
|
||||||
|
factory.RegisterEntity<RadarEntity>("Radar",
|
||||||
|
"Radar",
|
||||||
|
"Radar system entity with target detection and tracking capabilities",
|
||||||
|
"models/radar.osg",
|
||||||
|
QStringList() << "LabelComponent" << "RadarComponent" << "ScanComponent"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Register vehicle entity
|
||||||
|
factory.RegisterEntity<VehicleEntity>("Vehicle",
|
||||||
|
"Vehicle",
|
||||||
|
"Generic vehicle entity configurable for different types of transportation",
|
||||||
|
"models/vehicle.osg",
|
||||||
|
QStringList() << "LabelComponent" << "MovementComponent"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Register aircraft entity
|
||||||
|
factory.RegisterEntity<VehicleEntity>("Aircraft",
|
||||||
|
"Aircraft",
|
||||||
|
"Aviation entity with flight and aerial combat capabilities",
|
||||||
|
"models/aircraft.osg",
|
||||||
|
QStringList() << "LabelComponent" << "FlightComponent" << "NavigationComponent"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Register tank entity
|
||||||
|
factory.RegisterEntity<VehicleEntity>("Tank",
|
||||||
|
"Tank",
|
||||||
|
"Armored vehicle entity with ground combat capabilities",
|
||||||
|
"models/tank.osg",
|
||||||
|
QStringList() << "LabelComponent" << "ArmorComponent" << "WeaponComponent"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Register submarine entity
|
||||||
|
factory.RegisterEntity<ShipEntity>("Submarine",
|
||||||
|
"Submarine",
|
||||||
|
"Submarine entity with underwater combat capabilities",
|
||||||
|
"models/submarine.osg",
|
||||||
|
QStringList() << "LabelComponent" << "SonarComponent" << "TorpedoComponent"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Register base entity
|
||||||
|
factory.RegisterEntity<Entity>("Base",
|
||||||
|
"Base",
|
||||||
|
"Military base entity serving as command and logistics center",
|
||||||
|
"models/base.osg",
|
||||||
|
QStringList() << "LabelComponent" << "CommandComponent" << "DefenseComponent"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Register generic entity (for backward compatibility)
|
||||||
|
factory.RegisterEntity<Entity>("Entity",
|
||||||
|
"Entity",
|
||||||
|
"Basic entity type extensible through component system",
|
||||||
|
"models/default.osg",
|
||||||
|
QStringList() << "LabelComponent"
|
||||||
|
);
|
||||||
|
|
||||||
|
LOG_INFO("EntityRegistration::RegisterAllEntities - All entity types registered successfully");
|
||||||
|
}
|
||||||
11
src/entities/EntityRegistration.h
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "entities/EntityFactory.h"
|
||||||
|
#include "entities/SpecializedEntities.h"
|
||||||
|
|
||||||
|
// Entity registration class
|
||||||
|
class EntityRegistration {
|
||||||
|
public:
|
||||||
|
// Register all entity types
|
||||||
|
static void RegisterAllEntities();
|
||||||
|
};
|
||||||
193
src/entities/LabelComponent.cpp
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
#include "entities/LabelComponent.h"
|
||||||
|
|
||||||
|
#include <osg/Billboard>
|
||||||
|
#include <osg/StateSet>
|
||||||
|
#include <osg/BlendFunc>
|
||||||
|
#include <osg/Depth>
|
||||||
|
#include <osgText/Font>
|
||||||
|
|
||||||
|
#include "entities/Entity.h"
|
||||||
|
#include "common/SpdLogger.h"
|
||||||
|
|
||||||
|
#include "scutcheon/osgScutcheon.h"
|
||||||
|
|
||||||
|
LabelComponent::LabelComponent(SceneComponent* parent)
|
||||||
|
: SceneComponent(parent)
|
||||||
|
, text_("Label")
|
||||||
|
, fontSize_(26.0f)
|
||||||
|
, color_(1.0f, 0.0f, 0.0f, 1.0f)
|
||||||
|
, visible_(true)
|
||||||
|
, needUpdate_(true) {
|
||||||
|
}
|
||||||
|
|
||||||
|
LabelComponent::~LabelComponent() {
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string LabelComponent::GetTypeName() {
|
||||||
|
return "LabelComponent";
|
||||||
|
}
|
||||||
|
|
||||||
|
void LabelComponent::AttachEntity(Entity* entity) {
|
||||||
|
SceneComponent::AttachEntity(entity);
|
||||||
|
|
||||||
|
if (entity && !entity->GetName().isEmpty()) {
|
||||||
|
LOG_INFO("LabelComponent: Attaching to entity '{}'", entity->GetName().toUtf8().data());
|
||||||
|
SetText(entity->GetName().toLocal8Bit().data());
|
||||||
|
|
||||||
|
Entity* entity = GetEntity();
|
||||||
|
if (nullptr != entity) {
|
||||||
|
connect(entity, &Entity::NameChanged, this, &LabelComponent::UpdateText);
|
||||||
|
}
|
||||||
|
|
||||||
|
CreateTextNode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LabelComponent::SetAttribute(const char* name, const char* value) {
|
||||||
|
if (0 == strcmp(name, "text")) {
|
||||||
|
SetText(value);
|
||||||
|
return true;
|
||||||
|
} else if (0 == strcmp(name, "fontSize")) {
|
||||||
|
SetFontSize(static_cast<float>(atof(value)));
|
||||||
|
return true;
|
||||||
|
} else if (0 == strcmp(name, "visible")) {
|
||||||
|
SetVisible(0 == strcmp(value, "true"));
|
||||||
|
return true;
|
||||||
|
} else if (0 == strcmp(name, "color")) {
|
||||||
|
float r, g, b, a = 1.0f;
|
||||||
|
int parsed = sscanf(value, "%f,%f,%f,%f", &r, &g, &b, &a);
|
||||||
|
if (parsed >= 3) {
|
||||||
|
SetColor(osg::Vec4(r, g, b, a));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return SceneComponent::SetAttribute(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LabelComponent::SaveAttribute(tinyxml2::XMLElement* element) {
|
||||||
|
element->SetAttribute("text", text_.c_str());
|
||||||
|
element->SetAttribute("fontSize", fontSize_);
|
||||||
|
element->SetAttribute("visible", visible_ ? "true" : "false");
|
||||||
|
|
||||||
|
char colorStr[64];
|
||||||
|
sprintf(colorStr, "%.2f,%.2f,%.2f,%.2f", color_.r(), color_.g(), color_.b(), color_.a());
|
||||||
|
element->SetAttribute("color", colorStr);
|
||||||
|
|
||||||
|
return SceneComponent::SaveAttribute(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string LabelComponent::GetSelfTypeName() const {
|
||||||
|
return LabelComponent::GetTypeName();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LabelComponent::Begin() {
|
||||||
|
SceneComponent::Begin();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void LabelComponent::Update(double dt) {
|
||||||
|
SceneComponent::Update(dt);
|
||||||
|
|
||||||
|
if (needUpdate_) {
|
||||||
|
UpdateTextNode();
|
||||||
|
needUpdate_ = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LabelComponent::End() {
|
||||||
|
SceneComponent::End();
|
||||||
|
|
||||||
|
Entity* entity = GetEntity();
|
||||||
|
if (nullptr != entity) {
|
||||||
|
disconnect(entity, &Entity::NameChanged, this, &LabelComponent::UpdateText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LabelComponent::AddToRender() {
|
||||||
|
SceneComponent::AddToRender();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LabelComponent::SetText(const std::string& text) {
|
||||||
|
if (text_ != text) {
|
||||||
|
text_ = text;
|
||||||
|
needUpdate_ = true;
|
||||||
|
if (textNode_.valid()) {
|
||||||
|
textNode_->setText(text_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LabelComponent::SetFontSize(float size) {
|
||||||
|
if (fontSize_ != size) {
|
||||||
|
fontSize_ = size;
|
||||||
|
needUpdate_ = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LabelComponent::SetColor(const osg::Vec4& color) {
|
||||||
|
if (color_ != color) {
|
||||||
|
color_ = color;
|
||||||
|
needUpdate_ = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LabelComponent::SetVisible(bool visible) {
|
||||||
|
if (visible_ != visible) {
|
||||||
|
visible_ = visible;
|
||||||
|
if (billboard_.valid()) {
|
||||||
|
billboard_->setNodeMask(visible_ ? 0xffffffff : 0x0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LabelComponent::CreateTextNode() {
|
||||||
|
if (mt_.valid()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!billboard_.valid()) {
|
||||||
|
billboard_ = new osg::Billboard();
|
||||||
|
billboard_->setMode(osg::Billboard::POINT_ROT_EYE);
|
||||||
|
|
||||||
|
textNode_ = new osgText::Text();
|
||||||
|
|
||||||
|
textNode_->setAlignment(osgText::Text::CENTER_BOTTOM);
|
||||||
|
textNode_->setAxisAlignment(osgText::Text::SCREEN);
|
||||||
|
textNode_->setCharacterSizeMode(osgText::Text::SCREEN_COORDS);
|
||||||
|
textNode_->setText(text_);
|
||||||
|
textNode_->setPosition(osg::Vec3(0.0f, 0.0f, 0.0f));
|
||||||
|
|
||||||
|
billboard_->addDrawable(textNode_.get(), osg::Vec3(0.0f, 0.0f, 5.0f));
|
||||||
|
|
||||||
|
osg::StateSet* stateSet = billboard_->getOrCreateStateSet();
|
||||||
|
stateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
|
||||||
|
stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON);
|
||||||
|
stateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
|
||||||
|
stateSet->setAttributeAndModes(new osg::BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
|
||||||
|
|
||||||
|
osg::ref_ptr<osg::MatrixTransform> mt = new osg::MatrixTransform();
|
||||||
|
mt->addChild(billboard_);
|
||||||
|
if (!mt_.valid()) {
|
||||||
|
mt_ = mt;
|
||||||
|
}
|
||||||
|
|
||||||
|
needUpdate_ = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LabelComponent::UpdateTextNode() {
|
||||||
|
if (textNode_.valid()) {
|
||||||
|
textNode_->setText(text_);
|
||||||
|
textNode_->setCharacterSize(fontSize_);
|
||||||
|
textNode_->setColor(color_);
|
||||||
|
|
||||||
|
SPDLOG_INFO("LabelComponent: Updated billboard text '{}' with size {}", text_, fontSize_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LabelComponent::UpdateText(const QString& text) {
|
||||||
|
SetText(text.toLocal8Bit().data());
|
||||||
|
needUpdate_ = true;
|
||||||
|
}
|
||||||
57
src/entities/LabelComponent.h
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "entities/SceneComponent.h"
|
||||||
|
|
||||||
|
#include <qstring.h>
|
||||||
|
|
||||||
|
#include <osg/Billboard>
|
||||||
|
#include <osgText/Text>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class LabelComponent : public SceneComponent {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit LabelComponent(SceneComponent* parent = nullptr);
|
||||||
|
~LabelComponent();
|
||||||
|
|
||||||
|
static std::string GetTypeName();
|
||||||
|
|
||||||
|
void AttachEntity(class Entity* owner) override;
|
||||||
|
bool SetAttribute(const char* name, const char* value) override;
|
||||||
|
bool SaveAttribute(tinyxml2::XMLElement* element) override;
|
||||||
|
std::string GetSelfTypeName() const override;
|
||||||
|
|
||||||
|
void Begin() override;
|
||||||
|
void Update(double dt) override;
|
||||||
|
void End() override;
|
||||||
|
void AddToRender() override;
|
||||||
|
|
||||||
|
void SetText(const std::string& text);
|
||||||
|
const std::string& GetText() const { return text_; }
|
||||||
|
|
||||||
|
void SetFontSize(float size);
|
||||||
|
float GetFontSize() const { return fontSize_; }
|
||||||
|
|
||||||
|
void SetColor(const osg::Vec4& color);
|
||||||
|
const osg::Vec4& GetColor() const { return color_; }
|
||||||
|
|
||||||
|
void SetVisible(bool visible);
|
||||||
|
bool IsVisible() const { return visible_; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void CreateTextNode();
|
||||||
|
void UpdateTextNode();
|
||||||
|
void UpdateText(const QString& text);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::string text_;
|
||||||
|
float fontSize_;
|
||||||
|
osg::Vec4 color_;
|
||||||
|
bool visible_;
|
||||||
|
bool needUpdate_;
|
||||||
|
|
||||||
|
//osg::ref_ptr<class osgScutcheon> scutcheon_;
|
||||||
|
osg::ref_ptr<osg::Billboard> billboard_;
|
||||||
|
osg::ref_ptr<osgText::Text> textNode_;
|
||||||
|
};
|
||||||
@ -29,7 +29,7 @@ bool MeshComponent::SaveAttribute(tinyxml2::XMLElement* element) {
|
|||||||
return SceneComponent::SaveAttribute(element);
|
return SceneComponent::SaveAttribute(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string MeshComponent::GetSelfTypeName() {
|
std::string MeshComponent::GetSelfTypeName() const {
|
||||||
return MeshComponent::GetTypeName();
|
return MeshComponent::GetTypeName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -16,7 +16,7 @@ public:
|
|||||||
|
|
||||||
bool SetAttribute(const char* name, const char* value) override;
|
bool SetAttribute(const char* name, const char* value) override;
|
||||||
bool SaveAttribute(tinyxml2::XMLElement* element) override;
|
bool SaveAttribute(tinyxml2::XMLElement* element) override;
|
||||||
std::string GetSelfTypeName() override;
|
std::string GetSelfTypeName() const override;
|
||||||
|
|
||||||
bool LoadNode(const char* mesh);
|
bool LoadNode(const char* mesh);
|
||||||
const std::string& GetMesh() const {
|
const std::string& GetMesh() const {
|
||||||
|
|||||||
@ -68,7 +68,7 @@ void PathComponent::Begin() {
|
|||||||
for (int index = 0; index < num; ++index) {
|
for (int index = 0; index < num; ++index) {
|
||||||
const Transform& transform = transforms[index];
|
const Transform& transform = transforms[index];
|
||||||
osg::AnimationPath::ControlPoint controlPoint(transform.GetLocation() /*+ osg::Vec3(index * 10, 0, 0)*/,
|
osg::AnimationPath::ControlPoint controlPoint(transform.GetLocation() /*+ osg::Vec3(index * 10, 0, 0)*/,
|
||||||
OsgUtils::HPRToQuat(transform.GetRotation() + osg::Vec3(0, 0, -90.0)), transform.GetScale());
|
OsgUtils::HPRToQuat(transform.GetRotation()), transform.GetScale());
|
||||||
animationPath_->insert(steps[index], controlPoint);
|
animationPath_->insert(steps[index], controlPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +104,7 @@ void PathComponent::Update(double dt) {
|
|||||||
osg::Vec3 angle;
|
osg::Vec3 angle;
|
||||||
OsgUtils::QuatToHPR(cp.getRotation(), &angle);
|
OsgUtils::QuatToHPR(cp.getRotation(), &angle);
|
||||||
transform->SetRotation(angle);
|
transform->SetRotation(angle);
|
||||||
transform->SetScale(cp.getScale());
|
// transform->SetScale(cp.getScale());
|
||||||
}
|
}
|
||||||
|
|
||||||
void PathComponent::SetPath(const QString& path) {
|
void PathComponent::SetPath(const QString& path) {
|
||||||
|
|||||||
@ -12,7 +12,7 @@ public:
|
|||||||
~PathComponent();
|
~PathComponent();
|
||||||
|
|
||||||
static std::string GetTypeName();
|
static std::string GetTypeName();
|
||||||
std::string GetSelfTypeName() override {
|
std::string GetSelfTypeName() const override {
|
||||||
return PathComponent::GetTypeName();
|
return PathComponent::GetTypeName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -261,3 +261,32 @@ void SceneComponent::AddToRender() {
|
|||||||
AttachParent(parent);
|
AttachParent(parent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SceneComponent::HasComponent(const std::string& name) const {
|
||||||
|
if (GetSelfTypeName() == name) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& componet : children_) {
|
||||||
|
if (componet->GetSelfTypeName() == name) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneComponent::SetVisible(bool v) {
|
||||||
|
visible_ = v;
|
||||||
|
if (nullptr == mt_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mt_->setNodeMask(v ? ~0 : 0);
|
||||||
|
|
||||||
|
// for (auto child : children_) {
|
||||||
|
// child->SetVisible(v);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SceneComponent::IsVisible() const {
|
||||||
|
return visible_;
|
||||||
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
#include "entities/Component.h"
|
#include "entities/Component.h"
|
||||||
//#include "entities/Entity.h"
|
//#include "entities/Entity.h"
|
||||||
#include "utils/Transform.h"
|
#include "utils/Transform.h"
|
||||||
@ -9,6 +10,7 @@
|
|||||||
|
|
||||||
#include "osg/Vec3"
|
#include "osg/Vec3"
|
||||||
#include "osg/MatrixTransform"
|
#include "osg/MatrixTransform"
|
||||||
|
#include "Entity.h"
|
||||||
|
|
||||||
class SceneComponent : public Component {
|
class SceneComponent : public Component {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -29,6 +31,7 @@ public:
|
|||||||
bool AttachTo(SceneComponent* parent) override;
|
bool AttachTo(SceneComponent* parent) override;
|
||||||
|
|
||||||
virtual void AddToRender();
|
virtual void AddToRender();
|
||||||
|
virtual bool HasComponent(const std::string& name) const override;
|
||||||
|
|
||||||
SceneComponent* GetRootComponent() const;
|
SceneComponent* GetRootComponent() const;
|
||||||
|
|
||||||
@ -59,6 +62,9 @@ public:
|
|||||||
void AttachParent(SceneComponent* parent);
|
void AttachParent(SceneComponent* parent);
|
||||||
void UpdateLocationAndRotation();
|
void UpdateLocationAndRotation();
|
||||||
|
|
||||||
|
void SetVisible(bool v);
|
||||||
|
bool IsVisible() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void RemoveRender();
|
void RemoveRender();
|
||||||
void RemoveParent();
|
void RemoveParent();
|
||||||
@ -74,4 +80,5 @@ protected:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
Transform transform_;
|
Transform transform_;
|
||||||
|
bool visible_{ true };
|
||||||
};
|
};
|
||||||
@ -1,513 +0,0 @@
|
|||||||
#include "entities/ScutcheonComponent.h"
|
|
||||||
|
|
||||||
#include <osgViewer/Renderer>
|
|
||||||
|
|
||||||
|
|
||||||
Scutcheon::Scutcheon() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Scutcheon::Scutcheon(const QString& titleText, osg::ref_ptr<osg::MatrixTransform> targetObj) :
|
|
||||||
osgWidget::Box("Scutcheon", osgWidget::Box::VERTICAL),
|
|
||||||
mTargetObj(targetObj),
|
|
||||||
mIndex(0),
|
|
||||||
mIsVisible(true),
|
|
||||||
mIsItemVisible(true),
|
|
||||||
mIsMouseDrag(false),
|
|
||||||
mIsMousePush(false) {
|
|
||||||
|
|
||||||
getBackground()->setColor(1.0, 1.0, 1.0, 0.5);
|
|
||||||
setEventMask(osgWidget::EVENT_ALL);
|
|
||||||
attachMoveCallback();
|
|
||||||
|
|
||||||
mTitleText = titleText;
|
|
||||||
addLabelTitle(titleText);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Scutcheon::~Scutcheon() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scutcheon::addLabelTitle(const QString& titleText) {
|
|
||||||
|
|
||||||
osg::ref_ptr<osgWidget::Label> labelTitle = new osgWidget::Label("labelTitle");
|
|
||||||
labelTitle->setFont(FONT_TEXT);
|
|
||||||
labelTitle->setFontSize(14);
|
|
||||||
labelTitle->setFontColor(1.0f, 1.0f, 0.0f, 1.0f);
|
|
||||||
labelTitle->setColor(1.0f, 1.0f, 1.0f, 0.3f);
|
|
||||||
labelTitle->addSize(128.0f, 32.0f);
|
|
||||||
//labelTitle->setEventMask(osgWidget::EVENT_MOUSE_DRAG);
|
|
||||||
//labelTitle->addCallback(new osgWidget::Callback(&osgScutcheon::callbackMousePush, this, osgWidget::EVENT_MOUSE_DRAG));
|
|
||||||
|
|
||||||
//labelTitle->setShadow(0.08f);
|
|
||||||
labelTitle->setCanFill(true);
|
|
||||||
labelTitle->setImage(TITLE_IMAGE);
|
|
||||||
labelTitle->setTexCoord(0.0f, 0.0f, osgWidget::Widget::LOWER_LEFT);
|
|
||||||
labelTitle->setTexCoord(1.0f, 0.0f, osgWidget::Widget::LOWER_RIGHT);
|
|
||||||
labelTitle->setTexCoord(1.0f, 1.0f, osgWidget::Widget::UPPER_RIGHT);
|
|
||||||
labelTitle->setTexCoord(0.0f, 1.0f, osgWidget::Widget::UPPER_LEFT);
|
|
||||||
osgText::String labelString = TextCodecUtils::QStringToOsgTextString(titleText);
|
|
||||||
labelTitle->setLabel(labelString);
|
|
||||||
addWidget(labelTitle);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Scutcheon::addLabelItem(const QString& labelText) {
|
|
||||||
++mIndex;
|
|
||||||
ScutcheonMenu* labelItem = new ScutcheonMenu(labelText, this);
|
|
||||||
labelItem->setIndex(mIndex);
|
|
||||||
mLabelItemManager.push_back(labelItem);
|
|
||||||
addWidget(labelItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scutcheon::addLabelItem(ScutcheonMenu& labelItem) {
|
|
||||||
++mIndex;
|
|
||||||
labelItem.setIndex(mIndex);
|
|
||||||
mLabelItemManager.push_back(&labelItem);
|
|
||||||
if (mIsItemVisible) {
|
|
||||||
addWidget(&labelItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scutcheon::moveLabelItem() {
|
|
||||||
int x = this->getX();
|
|
||||||
int y = this->getY();
|
|
||||||
|
|
||||||
for (int i = 0; i < mLabelItemManager.size(); ++i) {
|
|
||||||
ScutcheonMenu* labelItem = mLabelItemManager.at(i);
|
|
||||||
labelItem->moveTo(x, y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Scutcheon::callbackMouseDrag(osgWidget::Event& ev) {
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Scutcheon::mouseDrag(double, double, const osgWidget::WindowManager*) {
|
|
||||||
qDebug() << "osgScutcheon mouseDrag called";
|
|
||||||
mIsMouseDrag = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Scutcheon::mousePush(double, double, const osgWidget::WindowManager*) {
|
|
||||||
mIsMousePush = true;
|
|
||||||
qDebug() << "osgScutcheon mousePush called" << mIsMousePush << ":" << mTitleText;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Scutcheon::mouseRelease(double, double, const osgWidget::WindowManager*) {
|
|
||||||
qDebug() << "osgScutcheon mouseRelease called" << mIsMouseDrag << ":" << mTitleText;
|
|
||||||
|
|
||||||
if (!mIsMouseDrag) {
|
|
||||||
if (mIsMousePush && mIsItemVisible) {
|
|
||||||
std::vector<osg::ref_ptr<ScutcheonMenu> >::const_iterator it;
|
|
||||||
for (it = mLabelItemManager.begin(); it != mLabelItemManager.end(); ++it) {
|
|
||||||
(*it)->getChildMenu()->hide();
|
|
||||||
this->removeWidget((*it));
|
|
||||||
qDebug() << "item removed!" << (*it)->getIndex();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (this->getNumChildren() <= mLabelItemManager.size()) {
|
|
||||||
std::vector<osg::ref_ptr<ScutcheonMenu> >::const_iterator it;
|
|
||||||
for (it = mLabelItemManager.begin(); it != mLabelItemManager.end(); ++it) {
|
|
||||||
this->addWidget((*it));
|
|
||||||
qDebug() << "item added!" << (*it)->getIndex();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mIsItemVisible = !mIsItemVisible;
|
|
||||||
}
|
|
||||||
mIsMousePush = false;
|
|
||||||
mIsMouseDrag = false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<osg::ref_ptr<ScutcheonMenu> > Scutcheon::getLabelItemManager() const {
|
|
||||||
return mLabelItemManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Scutcheon::onMouseEvent(const osgGA::GUIEventAdapter& ea, osgViewer::Viewer* viewer) {
|
|
||||||
int etype = ea.getEventType();
|
|
||||||
if (etype == ea.FRAME) {
|
|
||||||
if (mTargetObj) {
|
|
||||||
osg::Vec3 position = mTargetObj->getMatrix().getTrans() + osg::Vec3d(0, 0, 0);
|
|
||||||
osgViewer::Renderer* renderer = dynamic_cast<osgViewer::Renderer*>(viewer->getCamera()->getRenderer());
|
|
||||||
osg::Vec3 renderPos;
|
|
||||||
renderer->getSceneView(0)->projectObjectIntoWindow(position, renderPos);
|
|
||||||
|
|
||||||
float x = this->getX();
|
|
||||||
float y = this->getY();
|
|
||||||
float w = this->getWidth();
|
|
||||||
float h = this->getHeight();
|
|
||||||
|
|
||||||
float offset = 0.0;
|
|
||||||
osg::Vec3 stPt(x + 0.5 * w, y + 0.5 * h, 0);
|
|
||||||
if (stPt.y()- renderPos.y()>0.5*h)
|
|
||||||
{
|
|
||||||
stPt[1] = stPt.y()-0.5*h+offset;
|
|
||||||
}
|
|
||||||
else if (stPt.y()- renderPos.y()<-0.5*h)
|
|
||||||
{
|
|
||||||
stPt[1] = stPt.y()+0.5*h+offset;
|
|
||||||
}
|
|
||||||
if (stPt.x()- renderPos.x()>0.5*w)
|
|
||||||
{
|
|
||||||
stPt[0] = stPt.x()-0.5*w-offset;
|
|
||||||
}
|
|
||||||
else if (stPt.x()- renderPos.x()<-0.5*w)
|
|
||||||
{
|
|
||||||
stPt[0] = stPt.x()+0.5*w-offset;
|
|
||||||
}
|
|
||||||
setPos(renderPos + osg::Vec3d(50, 50, 50));
|
|
||||||
createLine(stPt, renderPos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((etype == ea.PUSH) && ea.getButtonMask() == ea.LEFT_MOUSE_BUTTON) {
|
|
||||||
if (mIsMousePush) {
|
|
||||||
//qDebug() << "mousePush called" ;
|
|
||||||
m_LBDownPt.set(ea.getX(), ea.getY(), 0);
|
|
||||||
m_LastPt = m_LBDownPt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((etype == ea.DRAG)) {
|
|
||||||
//qDebug() << "mouseDrag called" ;
|
|
||||||
if (mIsMouseDrag) {
|
|
||||||
osg::Vec3 pt(ea.getX() - m_LastPt[0], ea.getY() - m_LastPt[1], 0);
|
|
||||||
setOffset(m_offset + pt);
|
|
||||||
m_LastPt.set(ea.getX(), ea.getY(), 0);
|
|
||||||
ea.setHandled(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((etype == ea.RELEASE)) {
|
|
||||||
//qDebug() << "mouseDrag release" ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scutcheon::setPos(osg::Vec3 pos) {
|
|
||||||
m_pos = pos;
|
|
||||||
pos = m_pos + m_offset;
|
|
||||||
this->setOrigin(pos.x(), pos.y());
|
|
||||||
this->update();
|
|
||||||
moveLabelItem();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scutcheon::setOffset(osg::Vec3 offset) {
|
|
||||||
m_offset = offset;
|
|
||||||
offset = m_pos + m_offset;
|
|
||||||
this->setOrigin(offset.x(), offset.y());
|
|
||||||
this->update();
|
|
||||||
moveLabelItem();
|
|
||||||
}
|
|
||||||
|
|
||||||
osg::ref_ptr<osg::MatrixTransform> Scutcheon::getTargetObject() {
|
|
||||||
return mTargetObj;
|
|
||||||
}
|
|
||||||
int Scutcheon::getItemCount() {
|
|
||||||
return mLabelItemManager.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scutcheon::setVisibility(bool b) {
|
|
||||||
mIsVisible = b;
|
|
||||||
if (mIsVisible) {
|
|
||||||
this->show();
|
|
||||||
m_line->setNodeMask(1);
|
|
||||||
} else {
|
|
||||||
this->hide();
|
|
||||||
m_line->setNodeMask(0);
|
|
||||||
for (int i = 0; i < mLabelItemManager.size(); i++) {
|
|
||||||
mLabelItemManager.at(i)->getChildMenu()->hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scutcheon::createLine(const osg::Vec3& startPt, const osg::Vec3& endPt) {
|
|
||||||
if (NULL == m_line) {
|
|
||||||
m_line = new osg::Geometry;
|
|
||||||
osg::Vec3Array* vertices = new osg::Vec3Array;
|
|
||||||
vertices->push_back(startPt);
|
|
||||||
vertices->push_back(endPt);
|
|
||||||
m_line->setVertexArray(vertices);
|
|
||||||
|
|
||||||
osg::Vec3Array* normals = new osg::Vec3Array;
|
|
||||||
normals->push_back(osg::Vec3(0.0f, 0.0f, 1.0f));
|
|
||||||
m_line->setNormalArray(normals);
|
|
||||||
m_line->setNormalBinding(osg::Geometry::BIND_OVERALL);
|
|
||||||
|
|
||||||
osg::Vec4Array* colors = new osg::Vec4Array;
|
|
||||||
|
|
||||||
colors->push_back(osg::Vec4(1.0, 1.0, 0.0, 1.0));
|
|
||||||
m_line->setColorArray(colors);
|
|
||||||
m_line->setColorBinding(osg::Geometry::BIND_OVERALL);
|
|
||||||
|
|
||||||
m_line->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_STRIP, 0, 2));
|
|
||||||
m_line->getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON);
|
|
||||||
//m_line->getOrCreateStateSet()->setAttributeAndModes(new osg::LineWidth(1.0f),osg::StateAttribute::ON);
|
|
||||||
m_line->getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
|
|
||||||
osg::Geode* geode = new osg::Geode();
|
|
||||||
geode->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
|
|
||||||
geode->addDrawable(m_line);
|
|
||||||
//this->addChild(geode);
|
|
||||||
this->getWindowManager()->addChild(geode);
|
|
||||||
} else {
|
|
||||||
osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(m_line->getVertexArray());
|
|
||||||
(*vertices)[0].set(startPt.x(), startPt.y(), 0.0);
|
|
||||||
(*vertices)[1].set(endPt.x(), endPt.y(), 0.0);
|
|
||||||
vertices->dirty();
|
|
||||||
m_line->setVertexArray(vertices);
|
|
||||||
m_line->dirtyDisplayList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////
|
|
||||||
/// \brief osgScutcheonManager::osgScutcheonManager
|
|
||||||
/// 标牌管理器
|
|
||||||
/// ///////////////////////////////////////////////////////////
|
|
||||||
ScutcheonManager* ScutcheonManager::m_pInstance = NULL;
|
|
||||||
ScutcheonManager::ScutcheonManager(osgViewer::Viewer* pViewer, osg::Group* pScreneRoot) {
|
|
||||||
m_bVisible = true;
|
|
||||||
|
|
||||||
|
|
||||||
mWindowManager = new osgWidget::WindowManager(pViewer, 50.0f, 50.0f, 1, /*0xF0000000*/
|
|
||||||
osgWidget::WindowManager::WM_PICK_DEBUG);
|
|
||||||
osg::Camera* camera = mWindowManager->createParentOrthoCamera();
|
|
||||||
pScreneRoot->addChild(camera);
|
|
||||||
|
|
||||||
/*pViewer->addEventHandler(new osgWidget::MouseHandler(mWindowManager));
|
|
||||||
pViewer->addEventHandler(new osgWidget::KeyboardHandler(mWindowManager));
|
|
||||||
pViewer->addEventHandler(new osgWidget::ResizeHandler(mWindowManager, camera));
|
|
||||||
pViewer->addEventHandler(new osgWidget::CameraSwitchHandler(mWindowManager, camera));*/
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
ScutcheonManager::~ScutcheonManager() {
|
|
||||||
m_bGUIStoped = true;
|
|
||||||
clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
ScutcheonManager* ScutcheonManager::instance() {
|
|
||||||
if (NULL == m_pInstance) {
|
|
||||||
//osgViewer::Viewer* getOSGViewer(){ return m_pViewer; }
|
|
||||||
//osg::Group* getRoot(){ return m_pRoot.get(); }
|
|
||||||
/* m_pInstance = new osgScutcheonManager(GraphicsView::instance()->getOSGViewer(),
|
|
||||||
GraphicsView::instance()->getRoot());
|
|
||||||
GraphicsView::instance()->getOSGViewer()->addEventHandler(m_pInstance);*/
|
|
||||||
}
|
|
||||||
return m_pInstance;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScutcheonManager::destroy() {
|
|
||||||
if (NULL != m_pInstance) {
|
|
||||||
delete m_pInstance;
|
|
||||||
m_pInstance = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ScutcheonManager::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) {
|
|
||||||
if (m_bStopGUI) {
|
|
||||||
m_bGUIStoped = true;
|
|
||||||
} else {
|
|
||||||
osgViewer::Viewer* viewer = dynamic_cast<osgViewer::Viewer*>(&aa);
|
|
||||||
int nCount = m_LabelList.size();
|
|
||||||
for (int i = 0; i < nCount; i++) {
|
|
||||||
m_LabelList[i]->onMouseEvent(ea, viewer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ScutcheonManager::addLabel(Scutcheon* label) {
|
|
||||||
m_bVisible = true;
|
|
||||||
if (label == NULL) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
lock(true);
|
|
||||||
// while (!m_bStopGUI) QThread::sleep(100);
|
|
||||||
int nCount = m_LabelList.size();
|
|
||||||
for (int i = 0; i < nCount; i++) {
|
|
||||||
if (m_LabelList[i] == label) {
|
|
||||||
lock(false);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mWindowManager->addChild(label);
|
|
||||||
mWindowManager->resizeAllWindows();
|
|
||||||
m_LabelList.push_back(label);
|
|
||||||
|
|
||||||
lock(false);
|
|
||||||
return m_LabelList.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
int ScutcheonManager::delLabel(Scutcheon*& label) {
|
|
||||||
lock(true);
|
|
||||||
while (!m_bStopGUI) QThread::sleep(100);
|
|
||||||
for (std::vector<Scutcheon*>::iterator vit = m_LabelList.begin(); vit != m_LabelList.end(); vit++) {
|
|
||||||
if ((*vit) == label) {
|
|
||||||
m_LabelList.erase(vit);
|
|
||||||
//label->setVisibility(false);
|
|
||||||
delete label;
|
|
||||||
label = NULL;
|
|
||||||
lock(false);
|
|
||||||
return m_LabelList.size();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lock(false);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ScutcheonManager::delLabel(osg::MatrixTransform* tethernode) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScutcheonManager::clear() {
|
|
||||||
lock(true);
|
|
||||||
//while (!m_bGUIStoped) Sleep(200);
|
|
||||||
while (m_LabelList.size() > 0) {
|
|
||||||
Scutcheon* back = m_LabelList.back();
|
|
||||||
delLabel(back);
|
|
||||||
}
|
|
||||||
lock(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScutcheonManager::lock(bool b) {
|
|
||||||
if (b) {
|
|
||||||
m_bStopGUI = true;
|
|
||||||
m_bGUIStoped = false;
|
|
||||||
} else {
|
|
||||||
m_bStopGUI = false;
|
|
||||||
m_bGUIStoped = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
osg::ref_ptr<osgWidget::WindowManager> ScutcheonManager::getWindowManager() const {
|
|
||||||
return mWindowManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
ScutcheonMenu::ScutcheonMenu(const QString& label, osg::ref_ptr<Scutcheon> parentMenu) :
|
|
||||||
osgWidget::Label("menu1"),
|
|
||||||
mChildMenu(NULL),
|
|
||||||
mParentMenu(parentMenu),
|
|
||||||
mHasChildMenu(false),
|
|
||||||
mIndex(0),
|
|
||||||
mMenuItemCount(0) {
|
|
||||||
initLabel(label);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScutcheonMenu::addChildMenu(const QString& menuText) {
|
|
||||||
ImageLabel* childMenuContent = new ImageLabel(menuText);
|
|
||||||
if (mChildMenu == NULL) {
|
|
||||||
mChildMenu = new osgWidget::Box("childMenu", osgWidget::Box::VERTICAL, true);
|
|
||||||
mChildMenu->addWidget(childMenuContent);
|
|
||||||
mMenuItemManager.push_back(childMenuContent);
|
|
||||||
mChildMenu->getBackground()->setColor(1.0f, 1.0f, 1.0f, 0.6f);
|
|
||||||
mChildMenu->resize();
|
|
||||||
mChildMenu->hide();
|
|
||||||
mHasChildMenu = true;
|
|
||||||
//mParentMenu->addChild(mChildMenu);
|
|
||||||
mParentMenu->getWindowManager()->addChild(mChildMenu.get());
|
|
||||||
|
|
||||||
} else {
|
|
||||||
mChildMenu->addWidget(childMenuContent);
|
|
||||||
mMenuItemManager.push_back(childMenuContent);
|
|
||||||
}
|
|
||||||
|
|
||||||
++mMenuItemCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScutcheonMenu::updateChildMenuText(int index, QString labelText) {
|
|
||||||
if (index >= 0 && index < getMenuItemCount()) {
|
|
||||||
//mMenuItemManager.at(index)->setLabelText(labelText);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScutcheonMenu::initLabel(const QString& labelText) {
|
|
||||||
setFont(FONT_TEXT);
|
|
||||||
setFontSize(15);
|
|
||||||
setFontColor(0.0f, 0.0f, 1.0f, 1.0f);
|
|
||||||
addSize(128.0f, 32.0f);
|
|
||||||
setColor(1.0f, 1.0f, 0.0f, 0.6f);
|
|
||||||
//setShadow(0.08f);
|
|
||||||
setCanFill(true);
|
|
||||||
setEventMask(osgWidget::EVENT_ALL);
|
|
||||||
setImage(ITEM_IAMGE);
|
|
||||||
setTexCoord(0.0f, 0.0f, osgWidget::Widget::LOWER_LEFT);
|
|
||||||
setTexCoord(1.0f, 0.0f, osgWidget::Widget::LOWER_RIGHT);
|
|
||||||
setTexCoord(1.0f, 1.0f, osgWidget::Widget::UPPER_RIGHT);
|
|
||||||
setTexCoord(0.0f, 1.0f, osgWidget::Widget::UPPER_LEFT);
|
|
||||||
osgText::String labelString = TextCodecUtils::QStringToOsgTextString(labelText);
|
|
||||||
setLabel(labelString);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScutcheonMenu::hideOtherChildMenu() {
|
|
||||||
for (int i = 0; i < mParentMenu->getLabelItemManager().size(); i++) {
|
|
||||||
osg::ref_ptr<ScutcheonMenu> childItem = mParentMenu->getLabelItemManager().at(i);
|
|
||||||
if (childItem->getChildMenu() != mChildMenu) {
|
|
||||||
childItem->getChildMenu()->hide();
|
|
||||||
}
|
|
||||||
qDebug() << "hideOtherChildMenu";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScutcheonMenu::hideAllChildMenu(osgWidget::WindowManager* wm) {
|
|
||||||
osgWidget::Window* tmp = 0;
|
|
||||||
unsigned int count = wm->getNumChildren();
|
|
||||||
for (unsigned int i = 0; i < count; ++i) {
|
|
||||||
tmp = dynamic_cast<osgWidget::Window*>(wm->getChild(i));
|
|
||||||
if (tmp) {
|
|
||||||
QString name = QString::fromStdString(tmp->getName());
|
|
||||||
if (tmp != mChildMenu.get() && name == "childMenu") {
|
|
||||||
if (tmp->isVisible()) {
|
|
||||||
tmp->hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ScutcheonMenu::mousePush(double, double, const osgWidget::WindowManager* wm) {
|
|
||||||
hideOtherChildMenu();
|
|
||||||
//hideAllChildMenu(mParentMenu->getWindowManager());
|
|
||||||
|
|
||||||
if (!mChildMenu->isVisible()) {
|
|
||||||
mChildMenu->show();
|
|
||||||
qDebug() << "hideOtherChildMenu show";
|
|
||||||
} else {
|
|
||||||
mChildMenu->hide();
|
|
||||||
qDebug() << "hideOtherChildMenu hide";
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
ImageLabel::ImageLabel(const QString& labelText) : osgWidget::Label("menu1") {
|
|
||||||
setFont(FONT_TEXT);
|
|
||||||
setFontSize(13);
|
|
||||||
setFontColor(0.0f, 0.2f, 1.0f, 1.0f);
|
|
||||||
addSize(128.0f, 32.0f);
|
|
||||||
setColor(1.0f, 1.0f, 1.0f, 0.6f);
|
|
||||||
//setPadding(1.0f);
|
|
||||||
//setShadow(0.08f);
|
|
||||||
setCanFill(true);
|
|
||||||
setEventMask(osgWidget::EVENT_ALL);
|
|
||||||
setImage(ITEM_IAMGE);
|
|
||||||
|
|
||||||
setLabelText(labelText);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImageLabel::setLabelText(QString labelText) {
|
|
||||||
setAlignHorizontal(osgWidget::Widget::HA_LEFT);
|
|
||||||
setTexCoord(0.0f, 0.0f, osgWidget::Widget::LOWER_LEFT);
|
|
||||||
setTexCoord(1.0f, 0.0f, osgWidget::Widget::LOWER_RIGHT);
|
|
||||||
setTexCoord(1.0f, 1.0f, osgWidget::Widget::UPPER_RIGHT);
|
|
||||||
setTexCoord(0.0f, 1.0f, osgWidget::Widget::UPPER_LEFT);
|
|
||||||
|
|
||||||
osgText::String labelString = TextCodecUtils::QStringToOsgTextString(labelText);
|
|
||||||
setLabel(labelString);
|
|
||||||
}
|
|
||||||
@ -1,255 +0,0 @@
|
|||||||
/**
|
|
||||||
* @brief 标牌
|
|
||||||
* @author hph
|
|
||||||
* @date 2018/07/07
|
|
||||||
*/
|
|
||||||
#ifndef OSGSCUTCHEON_H
|
|
||||||
#define OSGSCUTCHEON_H
|
|
||||||
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include <iostream>
|
|
||||||
#include <sstream>
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QTextCodec>
|
|
||||||
#include <QVector>
|
|
||||||
#include <QThread>
|
|
||||||
|
|
||||||
#include <osgWidget/Box>
|
|
||||||
#include <osgWidget/Label>
|
|
||||||
#include <osgWidget/WindowManager>
|
|
||||||
|
|
||||||
#include "utils/TextCodecUtil.h"
|
|
||||||
|
|
||||||
#define FONT_TEXT "fonts/simhei.ttf"
|
|
||||||
#define TITLE_IMAGE "../publish/data/texture/mark/label_title.png"
|
|
||||||
#define ITEM_IAMGE "../publish/data/texture/mark/label_normal_01.png"
|
|
||||||
|
|
||||||
class ScutcheonMenu;
|
|
||||||
class ImageLabel;
|
|
||||||
|
|
||||||
class Scutcheon : public osgWidget::Box {
|
|
||||||
public:
|
|
||||||
Scutcheon();
|
|
||||||
Scutcheon(const QString& titleText, osg::ref_ptr<osg::MatrixTransform> targetObj);
|
|
||||||
~Scutcheon();
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
void addLabelTitle(const QString& titleText);
|
|
||||||
void addLabelItem(const QString& labelText);
|
|
||||||
void addLabelItem(ScutcheonMenu& labelItem);
|
|
||||||
|
|
||||||
void hideOtherLabelItem();
|
|
||||||
void moveLabelItem();
|
|
||||||
|
|
||||||
void createLine(const osg::Vec3& startPt = osg::Vec3(0, 0, 0), const osg::Vec3& endPt = osg::Vec3(0, 0, 0));
|
|
||||||
|
|
||||||
void onMouseEvent(const osgGA::GUIEventAdapter& ea, osgViewer::Viewer* viewer);
|
|
||||||
|
|
||||||
osg::Geometry* getLine() const {
|
|
||||||
return m_line;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getItemCount();
|
|
||||||
|
|
||||||
void setVisibility(bool b);
|
|
||||||
bool getVisibility() {
|
|
||||||
return mIsVisible;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setPos(osg::Vec3 pos);
|
|
||||||
void setOffset(osg::Vec3 offset);
|
|
||||||
|
|
||||||
osg::ref_ptr<osg::MatrixTransform> getTargetObject();
|
|
||||||
std::vector<osg::ref_ptr<ScutcheonMenu> > getLabelItemManager() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool callbackMouseDrag(osgWidget::Event& ev);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bool mouseDrag(double, double, const osgWidget::WindowManager*);
|
|
||||||
bool mousePush(double, double, const osgWidget::WindowManager*);
|
|
||||||
bool mouseRelease(double, double, const osgWidget::WindowManager*);
|
|
||||||
|
|
||||||
public:
|
|
||||||
QString mTitleText;
|
|
||||||
std::vector<osg::ref_ptr<ScutcheonMenu> > mLabelItemManager;
|
|
||||||
|
|
||||||
int mIndex;
|
|
||||||
|
|
||||||
osg::ref_ptr<osg::MatrixTransform> mTargetObj;
|
|
||||||
osg::ref_ptr<osg::Geometry> m_line;
|
|
||||||
|
|
||||||
bool mIsVisible;
|
|
||||||
bool mIsItemVisible;
|
|
||||||
bool mIsMousePush;
|
|
||||||
bool mIsMouseDrag;
|
|
||||||
|
|
||||||
|
|
||||||
osg::Vec3 m_pos;
|
|
||||||
osg::Vec3 m_offset;
|
|
||||||
|
|
||||||
osg::Vec3 m_LastPt;
|
|
||||||
osg::Vec3 m_LBDownPt;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ScutcheonManager : public osgGA::GUIEventHandler {
|
|
||||||
protected:
|
|
||||||
ScutcheonManager(osgViewer::Viewer* pViewer, osg::Group* pScreneRoot);
|
|
||||||
~ScutcheonManager();
|
|
||||||
|
|
||||||
public:
|
|
||||||
static ScutcheonManager* instance();
|
|
||||||
static void destroy();
|
|
||||||
bool handle(const osgGA::GUIEventAdapter&, osgGA::GUIActionAdapter&);
|
|
||||||
int addLabel(Scutcheon* label);
|
|
||||||
int delLabel(Scutcheon*& label);
|
|
||||||
int delLabel(osg::MatrixTransform* tethernode);
|
|
||||||
void clear();
|
|
||||||
void lock(bool b);
|
|
||||||
|
|
||||||
void setVisibility(bool b);
|
|
||||||
void setVisibilityByID(unsigned int ID, bool b);
|
|
||||||
bool getVisibilityByID(unsigned int ID);
|
|
||||||
bool getVisibility() const {
|
|
||||||
return m_bVisible;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setLabelTxtColor(const osg::Vec4f& color);
|
|
||||||
void setLabelBgColor(const osg::Vec4f& color);
|
|
||||||
const osg::Vec4f& getLabelTxtColor() const {
|
|
||||||
return m_clrTxt;
|
|
||||||
}
|
|
||||||
const osg::Vec4f& getLabelBgColor() const {
|
|
||||||
return m_clrBg;
|
|
||||||
}
|
|
||||||
|
|
||||||
osg::ref_ptr<osgWidget::WindowManager> getWindowManager() const;
|
|
||||||
public:
|
|
||||||
static ScutcheonManager* m_pInstance;
|
|
||||||
osg::ref_ptr<osgWidget::WindowManager> mWindowManager;
|
|
||||||
//osgWidget::WindowManager* mWindowManager;
|
|
||||||
std::vector<Scutcheon*> m_LabelList;
|
|
||||||
bool m_bStopGUI;
|
|
||||||
bool m_bGUIStoped;
|
|
||||||
bool m_bVisible;
|
|
||||||
osg::Vec4f m_clrTxt;
|
|
||||||
osg::Vec4f m_clrBg;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class ScutcheonMenu : public osgWidget::Label {
|
|
||||||
public:
|
|
||||||
ScutcheonMenu(const QString& label, osg::ref_ptr<Scutcheon> parentMenu);
|
|
||||||
|
|
||||||
void addChildMenu(const QString& menuText);
|
|
||||||
|
|
||||||
void updateChildMenuText(int index, QString labelText);
|
|
||||||
|
|
||||||
void initLabel(const QString& labelText);
|
|
||||||
|
|
||||||
void setIndex(int index) {
|
|
||||||
mIndex = index;
|
|
||||||
}
|
|
||||||
|
|
||||||
void moveTo(int parentX, int parentY) {
|
|
||||||
if (mChildMenu) {
|
|
||||||
mChildMenu->setOrigin(parentX + 128.0, parentY + 32.0 * mIndex);
|
|
||||||
mChildMenu->update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isHasChildMenu() {
|
|
||||||
return mHasChildMenu;
|
|
||||||
}
|
|
||||||
|
|
||||||
osg::ref_ptr<osgWidget::Window> getChildMenu() {
|
|
||||||
return mChildMenu;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getIndex() {
|
|
||||||
return mIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getMenuItemCount() {
|
|
||||||
return mMenuItemManager.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
void hideOtherChildMenu();
|
|
||||||
|
|
||||||
void hideAllChildMenu(osgWidget::WindowManager* wm);
|
|
||||||
|
|
||||||
void managed(osgWidget::WindowManager* wm) {
|
|
||||||
osgWidget::Label::managed(wm);
|
|
||||||
if (mChildMenu) {
|
|
||||||
mChildMenu->hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void positioned() {
|
|
||||||
osgWidget::Label::positioned();
|
|
||||||
if (mChildMenu) {
|
|
||||||
//qDebug() << "mChildMenu not NULL!!" << mIndex;
|
|
||||||
mChildMenu->setOrigin(mParentMenu->getX() + 128.0, mParentMenu->getY() + 32.0 * mIndex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool mousePush(double, double, const osgWidget::WindowManager* wm);
|
|
||||||
|
|
||||||
bool mouseEnter(double, double, const osgWidget::WindowManager*) {
|
|
||||||
setColor(1.0f, 1.0f, 1.0f, 0.3f);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool mouseLeave(double, double, const osgWidget::WindowManager*) {
|
|
||||||
setColor(1.0f, 1.0f, 1.0f, 0.6f);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
QVector<osg::ref_ptr<ImageLabel> > mMenuItemManager;
|
|
||||||
|
|
||||||
private:
|
|
||||||
osg::ref_ptr<osgWidget::Box> mChildMenu;
|
|
||||||
osg::ref_ptr<Scutcheon> mParentMenu;
|
|
||||||
|
|
||||||
int mIndex;
|
|
||||||
int mMenuItemCount;
|
|
||||||
bool mHasChildMenu;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
class ImageLabel : public osgWidget::Label {
|
|
||||||
public:
|
|
||||||
ImageLabel(const QString& labelText);
|
|
||||||
|
|
||||||
void setLabelText(QString labelText);
|
|
||||||
|
|
||||||
bool mousePush(double, double, const osgWidget::WindowManager*) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool mouseDrag(double, double, const osgWidget::WindowManager*) {
|
|
||||||
//osg::notify(osg::NOTICE) << _name << " > mouseDrag called" << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool mouseEnter(double, double, const osgWidget::WindowManager*) {
|
|
||||||
//setColor(1.0f, 1.0f, 1.0f, 1.0f);
|
|
||||||
setFontColor(0.0f, 0.0f, 1.0f, 1.0f);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool mouseLeave(double, double, const osgWidget::WindowManager*) {
|
|
||||||
//setColor(1.0f, 1.0f, 1.0f, 0.8f);
|
|
||||||
setFontColor(0.0f, 0.2f, 1.0f, 1.0f);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool mouseOver(double, double, const osgWidget::WindowManager*) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // OSGSCUTCHEON_H
|
|
||||||
60
src/entities/SpecializedEntities.cpp
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
#include "entities/SpecializedEntities.h"
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
#include "common/SpdLogger.h"
|
||||||
|
|
||||||
|
MissileEntity::MissileEntity(WorkSpace* workspace)
|
||||||
|
: Entity(workspace) {
|
||||||
|
SetName("Missile");
|
||||||
|
LOG_INFO("MissileEntity created");
|
||||||
|
}
|
||||||
|
|
||||||
|
MissileEntity::MissileEntity(const QString& name, QObject* parent)
|
||||||
|
: Entity(name, parent) {
|
||||||
|
LOG_INFO("MissileEntity created with name: {}", name.toStdString());
|
||||||
|
}
|
||||||
|
|
||||||
|
SatelliteEntity::SatelliteEntity(WorkSpace* workspace)
|
||||||
|
: Entity(workspace) {
|
||||||
|
SetName("Satellite");
|
||||||
|
LOG_INFO("SatelliteEntity created");
|
||||||
|
}
|
||||||
|
|
||||||
|
SatelliteEntity::SatelliteEntity(const QString& name, QObject* parent)
|
||||||
|
: Entity(name, parent) {
|
||||||
|
LOG_INFO("SatelliteEntity created with name: {}", name.toStdString());
|
||||||
|
}
|
||||||
|
|
||||||
|
ShipEntity::ShipEntity(WorkSpace* workspace)
|
||||||
|
: Entity(workspace) {
|
||||||
|
SetName("Ship");
|
||||||
|
LOG_INFO("ShipEntity created");
|
||||||
|
}
|
||||||
|
|
||||||
|
ShipEntity::ShipEntity(const QString& name, QObject* parent)
|
||||||
|
: Entity(name, parent) {
|
||||||
|
LOG_INFO("ShipEntity created with name: {}", name.toStdString());
|
||||||
|
}
|
||||||
|
|
||||||
|
RadarEntity::RadarEntity(WorkSpace* workspace)
|
||||||
|
: Entity(workspace) {
|
||||||
|
SetName("Radar");
|
||||||
|
LOG_INFO("RadarEntity created");
|
||||||
|
}
|
||||||
|
|
||||||
|
RadarEntity::RadarEntity(const QString& name, QObject* parent)
|
||||||
|
: Entity(name, parent) {
|
||||||
|
LOG_INFO("RadarEntity created with name: {}", name.toStdString());
|
||||||
|
}
|
||||||
|
|
||||||
|
VehicleEntity::VehicleEntity(WorkSpace* workspace)
|
||||||
|
: Entity(workspace) {
|
||||||
|
SetName("Vehicle");
|
||||||
|
LOG_INFO("VehicleEntity created");
|
||||||
|
}
|
||||||
|
|
||||||
|
VehicleEntity::VehicleEntity(const QString& name, QObject* parent)
|
||||||
|
: Entity(name, parent) {
|
||||||
|
LOG_INFO("VehicleEntity created with name: {}", name.toStdString());
|
||||||
|
}
|
||||||
58
src/entities/SpecializedEntities.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "entities/Entity.h"
|
||||||
|
|
||||||
|
// 导弹实体
|
||||||
|
class MissileEntity : public Entity {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit MissileEntity(WorkSpace* workspace);
|
||||||
|
explicit MissileEntity(const QString& name, QObject* parent = nullptr);
|
||||||
|
~MissileEntity() override = default;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// 卫星实体
|
||||||
|
class SatelliteEntity : public Entity {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit SatelliteEntity(WorkSpace* workspace);
|
||||||
|
explicit SatelliteEntity(const QString& name, QObject* parent = nullptr);
|
||||||
|
~SatelliteEntity() override = default;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// 舰船实体
|
||||||
|
class ShipEntity : public Entity {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ShipEntity(WorkSpace* workspace);
|
||||||
|
explicit ShipEntity(const QString& name, QObject* parent = nullptr);
|
||||||
|
~ShipEntity() override = default;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// 雷达实体
|
||||||
|
class RadarEntity : public Entity {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit RadarEntity(WorkSpace* workspace);
|
||||||
|
explicit RadarEntity(const QString& name, QObject* parent = nullptr);
|
||||||
|
~RadarEntity() override = default;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// 通用载具实体
|
||||||
|
class VehicleEntity : public Entity {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit VehicleEntity(WorkSpace* workspace);
|
||||||
|
explicit VehicleEntity(const QString& name, QObject* parent = nullptr);
|
||||||
|
~VehicleEntity() override = default;
|
||||||
|
|
||||||
|
};
|
||||||
390
src/main.cpp
@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
#include "app/Application.h"
|
#include "app/Application.h"
|
||||||
|
|
||||||
#include "common/SpdLogger.h"
|
#include "common/SpdLogger.h"
|
||||||
@ -5,23 +6,396 @@
|
|||||||
#include "common/CrashHandler.h"
|
#include "common/CrashHandler.h"
|
||||||
|
|
||||||
#include "ui/MainFrame.h"
|
#include "ui/MainFrame.h"
|
||||||
|
#include "ui/MainWindow.h"
|
||||||
|
#include "viewer/OsgWidget.h"
|
||||||
|
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QGridLayout>
|
||||||
|
|
||||||
|
#include <osgViewer/CompositeViewer>
|
||||||
|
#include <osgViewer/ViewerEventHandlers>
|
||||||
|
|
||||||
|
#include <osgGA/MultiTouchTrackballManipulator>
|
||||||
|
|
||||||
|
#include <osgDB/ReadFile>
|
||||||
|
#include <osgEarth/MapNode>
|
||||||
|
#include <osgEarthUtil/ExampleResources>
|
||||||
|
#include <osgGA/StateSetManipulator>
|
||||||
|
// #include <osgEarth/GLUtils>
|
||||||
|
|
||||||
|
#include "osgqt/GraphicsWindowQt.h"
|
||||||
|
#include "scene/ui/CompositeWidgetManager.h"
|
||||||
|
#include "scene/ui/QueryElevationWidget.h"
|
||||||
|
|
||||||
|
#ifndef LC
|
||||||
|
#define LC "DYT"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const unsigned int MASK_2D = 0xF0000000;
|
||||||
|
std::string path = "D:\\Project\\DYT\\Source\\bin\\Release\\data\\";
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
osg::Node* createUiExample(osgViewer::View* viewer, osgWidget::WindowManager* wm) {
|
||||||
|
if(!wm) return nullptr;
|
||||||
|
|
||||||
|
// viewer.setUpViewInWindow(
|
||||||
|
// 50,
|
||||||
|
// 50,
|
||||||
|
// static_cast<int>(wm->getWidth()),
|
||||||
|
// static_cast<int>(wm->getHeight())
|
||||||
|
// );
|
||||||
|
|
||||||
|
osg::Group* group = new osg::Group();
|
||||||
|
osg::Camera* camera = wm->createParentOrthoCamera();
|
||||||
|
|
||||||
|
group->addChild(camera);
|
||||||
|
|
||||||
|
viewer->addEventHandler(new osgWidget::MouseHandler(wm));
|
||||||
|
viewer->addEventHandler(new osgWidget::KeyboardHandler(wm));
|
||||||
|
viewer->addEventHandler(new osgWidget::ResizeHandler(wm, camera));
|
||||||
|
viewer->addEventHandler(new osgWidget::CameraSwitchHandler(wm, camera));
|
||||||
|
viewer->addEventHandler(new osgViewer::StatsHandler());
|
||||||
|
viewer->addEventHandler(new osgViewer::WindowSizeHandler());
|
||||||
|
viewer->addEventHandler(new osgGA::StateSetManipulator(
|
||||||
|
viewer->getCamera()->getOrCreateStateSet()
|
||||||
|
));
|
||||||
|
|
||||||
|
wm->resizeAllWindows();
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
void creatWidget(osgViewer::View* viewer, osg::Group* root) {
|
||||||
|
osgWidget::WindowManager* wm = new osgWidget::WindowManager(
|
||||||
|
viewer,
|
||||||
|
1280.0f,
|
||||||
|
1024.0f,
|
||||||
|
MASK_2D,
|
||||||
|
osgWidget::WindowManager::WM_PICK_DEBUG
|
||||||
|
//osgWidget::WindowManager::WM_NO_INVERT_Y
|
||||||
|
);
|
||||||
|
|
||||||
|
osgWidget::Frame* frame = osgWidget::Frame::createSimpleFrameFromTheme(
|
||||||
|
"frame",
|
||||||
|
osgDB::readRefImageFile("osgWidget/theme.png"),
|
||||||
|
40.0f,
|
||||||
|
40.0f,
|
||||||
|
osgWidget::Frame::FRAME_ALL
|
||||||
|
);
|
||||||
|
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);
|
||||||
|
|
||||||
|
img1->setImage(path + "osgWidget/scrolled1.jpg", true);
|
||||||
|
img2->setImage(path + "osgWidget/scrolled2.jpg", true);
|
||||||
|
img3->setImage(path + "osgWidget/scrolled3.jpg", true);
|
||||||
|
img4->setImage(path + "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);
|
||||||
|
|
||||||
|
osg::Node* ui = createUiExample(viewer, wm);
|
||||||
|
root->addChild(ui);
|
||||||
|
}
|
||||||
|
|
||||||
|
void configureView( osgViewer::View* view )
|
||||||
|
{
|
||||||
|
// default uniform values:
|
||||||
|
// GLUtils::setGlobalDefaults(view->getCamera()->getOrCreateStateSet());
|
||||||
|
|
||||||
|
// add some stock OSG handlers:
|
||||||
|
view->addEventHandler(new osgViewer::StatsHandler());
|
||||||
|
view->addEventHandler(new osgViewer::WindowSizeHandler());
|
||||||
|
view->addEventHandler(new osgViewer::ThreadingHandler());
|
||||||
|
view->addEventHandler(new osgViewer::LODScaleHandler());
|
||||||
|
view->addEventHandler(new osgGA::StateSetManipulator(view->getCamera()->getOrCreateStateSet()));
|
||||||
|
view->addEventHandler(new osgViewer::RecordCameraPathHandler());
|
||||||
|
view->addEventHandler(new osgViewer::ScreenCaptureHandler());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
osg::Node* LoadEarth(const std::string& earth, osgViewer::CompositeViewer* viewer) {
|
||||||
|
osg::ref_ptr<osg::Node> node = osgDB::readNodeFile(earth);
|
||||||
|
|
||||||
|
osg::ref_ptr<osgEarth::MapNode> mapNode = osgEarth::MapNode::get(node.get());
|
||||||
|
if ( !mapNode.valid() )
|
||||||
|
{
|
||||||
|
OE_WARN << LC << "Loaded scene graph does not contain a MapNode - aborting" << std::endl;
|
||||||
|
return 0L;
|
||||||
|
}
|
||||||
|
|
||||||
|
// collect the views
|
||||||
|
osgViewer::Viewer::Views views;
|
||||||
|
if (viewer)
|
||||||
|
{
|
||||||
|
viewer->getViews(views);
|
||||||
|
}
|
||||||
|
|
||||||
|
// warn about not having an earth manip
|
||||||
|
for (osgViewer::Viewer::Views::iterator view = views.begin(); view != views.end(); ++view)
|
||||||
|
{
|
||||||
|
osgEarth::Util::EarthManipulator* manip = dynamic_cast<osgEarth::Util::EarthManipulator*>((*view)->getCameraManipulator());
|
||||||
|
if ( manip == 0L )
|
||||||
|
{
|
||||||
|
OE_WARN << LC << "Helper used before installing an EarthManipulator" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// a root node to hold everything:
|
||||||
|
osg::Group* root = new osg::Group();
|
||||||
|
|
||||||
|
root->addChild( node );
|
||||||
|
|
||||||
|
// parses common cmdline arguments and apply to the first view:
|
||||||
|
// if ( !views.empty() )
|
||||||
|
// {
|
||||||
|
// parse( mapNode.get(), args, views.front(), root, userContainer );
|
||||||
|
//
|
||||||
|
// float lodscale;
|
||||||
|
// if (args.read("--lodscale", lodscale))
|
||||||
|
// {
|
||||||
|
// LODScaleGroup* g = new LODScaleGroup();
|
||||||
|
// g->setLODScaleFactor(osg::maximum(lodscale, 0.0001f));
|
||||||
|
// osgEarth::insertGroup(g, mapNode->getParent(0));
|
||||||
|
// OE_NOTICE << "LOD Scale set to: " << lodscale << std::endl;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// configures each view with some stock goodies
|
||||||
|
for (osgViewer::Viewer::Views::iterator view = views.begin(); view != views.end(); ++view)
|
||||||
|
{
|
||||||
|
configureView( *view );
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef OSG_GL3_AVAILABLE
|
||||||
|
if (viewer)
|
||||||
|
{
|
||||||
|
viewer->setRealizeOperation(new GL3RealizeOperation());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ViewerWidget : public QWidget, public osgViewer::CompositeViewer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ViewerWidget(QWidget* parent = 0, Qt::WindowFlags f = 0, osgViewer::ViewerBase::ThreadingModel threadingModel=osgViewer::CompositeViewer::SingleThreaded) : QWidget(parent, f)
|
||||||
|
{
|
||||||
|
setThreadingModel(threadingModel);
|
||||||
|
|
||||||
|
// disable the default setting of viewer.done() by pressing Escape.
|
||||||
|
setKeyEventSetsDone(0);
|
||||||
|
|
||||||
|
std::string earthPath = "D:/Project/DYT/Tool/TritonSample/TritonSample/triton.earth";
|
||||||
|
// osg::Node* node = osgDB::readNodeFile();
|
||||||
|
osg::Node* node =LoadEarth(earthPath, this);
|
||||||
|
if ( !node ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Group to hold all our annotation elements.
|
||||||
|
// osg::Group* annoGroup = new osg::Group();
|
||||||
|
// osgEarth::MapNode::get(node)->addChild( annoGroup );
|
||||||
|
|
||||||
|
QWidget* widget1 = addViewWidget( createGraphicsWindow(0,0,100,100), node);
|
||||||
|
// QWidget* widget2 = addViewWidget( createGraphicsWindow(0,0,100,100), osgDB::readRefNodeFile("glider.osgt") );
|
||||||
|
// QWidget* widget3 = addViewWidget( createGraphicsWindow(0,0,100,100), osgDB::readRefNodeFile("axes.osgt") );
|
||||||
|
// QWidget* widget4 = addViewWidget( createGraphicsWindow(0,0,100,100), osgDB::readRefNodeFile("fountain.osgt") );
|
||||||
|
// QWidget* popupWidget = addViewWidget( createGraphicsWindow(900,100,320,240,"Popup window",true), osgDB::readRefNodeFile("dumptruck.osgt") );
|
||||||
|
// popupWidget->show();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
QGridLayout* grid = new QGridLayout;
|
||||||
|
grid->addWidget( widget1, 0, 0 );
|
||||||
|
// grid->addWidget( widget2, 0, 1 );
|
||||||
|
// grid->addWidget( widget3, 1, 0 );
|
||||||
|
// grid->addWidget( widget4, 1, 1 );
|
||||||
|
setLayout( grid );
|
||||||
|
|
||||||
|
connect( &_timer, SIGNAL(timeout()), this, SLOT(update()) );
|
||||||
|
_timer.start( 10 );
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget* addViewWidget( osgQt::GraphicsWindowQt* gw, osg::ref_ptr<osg::Node> scene )
|
||||||
|
{
|
||||||
|
osgViewer::View* view = new osgViewer::View;
|
||||||
|
addView( view );
|
||||||
|
view->setCameraManipulator( new osgEarth::Util::EarthManipulator() );
|
||||||
|
configureView(view);
|
||||||
|
|
||||||
|
osg::Camera* camera = view->getCamera();
|
||||||
|
camera->setGraphicsContext( gw );
|
||||||
|
|
||||||
|
const osg::GraphicsContext::Traits* traits = gw->getTraits();
|
||||||
|
|
||||||
|
camera->setClearColor( osg::Vec4(0.2, 0.2, 0.6, 1.0) );
|
||||||
|
camera->setViewport( new osg::Viewport(0, 0, traits->width, traits->height) );
|
||||||
|
camera->setProjectionMatrixAsPerspective(30.0f, static_cast<double>(traits->width)/static_cast<double>(traits->height), 1.0f, 10000.0f );
|
||||||
|
|
||||||
|
creatWidget(view, scene->asGroup());
|
||||||
|
|
||||||
|
osgEarth::MapNode* mapNode = osgEarth::MapNode::findMapNode(scene);
|
||||||
|
if ( !mapNode )
|
||||||
|
return gw->getGLWidget();
|
||||||
|
|
||||||
|
auto skyDome_ = osgEarth::Util::SkyNode::create(mapNode);
|
||||||
|
if (!mapNode) {
|
||||||
|
LOG_WARN("eart map node is nullptr");
|
||||||
|
return gw->getGLWidget();
|
||||||
|
}
|
||||||
|
skyDome_->attach(view);
|
||||||
|
skyDome_->getSunLight()->setAmbient(osg::Vec4(0.5,0.5,0.5,1.0));
|
||||||
|
scene->asGroup()->addChild(skyDome_);
|
||||||
|
|
||||||
|
skyDome_->setDateTime(osgEarth::DateTime(2024, 12, 24, 3));
|
||||||
|
|
||||||
|
view->setSceneData( scene );
|
||||||
|
view->addEventHandler( new osgViewer::StatsHandler );
|
||||||
|
// view->setCameraManipulator( new osgGA::MultiTouchTrackballManipulator );
|
||||||
|
gw->setTouchEventsEnabled( true );
|
||||||
|
return gw->getGLWidget();
|
||||||
|
}
|
||||||
|
|
||||||
|
osgQt::GraphicsWindowQt* createGraphicsWindow( int x, int y, int w, int h, const std::string& name="", bool windowDecoration=false )
|
||||||
|
{
|
||||||
|
osg::DisplaySettings* ds = osg::DisplaySettings::instance().get();
|
||||||
|
osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
|
||||||
|
traits->windowName = name;
|
||||||
|
traits->windowDecoration = windowDecoration;
|
||||||
|
traits->x = x;
|
||||||
|
traits->y = y;
|
||||||
|
traits->width = w;
|
||||||
|
traits->height = h;
|
||||||
|
traits->doubleBuffer = true;
|
||||||
|
traits->alpha = ds->getMinimumNumAlphaBits();
|
||||||
|
traits->stencil = ds->getMinimumNumStencilBits();
|
||||||
|
traits->sampleBuffers = ds->getMultiSamples();
|
||||||
|
traits->samples = ds->getNumMultiSamples();
|
||||||
|
|
||||||
|
return new osgQt::GraphicsWindowQt(traits.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void paintEvent( QPaintEvent* /*event*/ )
|
||||||
|
{ frame(); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
QTimer _timer;
|
||||||
|
};
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
SpdLogger logger("logs/log.txt", 5);
|
SpdLogger logger("logs/log.txt", 5);
|
||||||
|
//
|
||||||
Application::setAttribute(Qt::AA_EnableHighDpiScaling);
|
Application::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||||
|
////
|
||||||
Application app(argc, argv);
|
Application app(argc, argv);
|
||||||
app.setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
|
app.setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
|
||||||
//InstallCrashHandler();
|
// InstallCrashHandler();
|
||||||
|
//
|
||||||
RecourceHelper::ChangeSkin("default");
|
RecourceHelper::ChangeSkin("default");
|
||||||
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
MainFrame mainWindow;
|
MainFrame mainWindow;
|
||||||
mainWindow.showMaximized();
|
mainWindow.showMaximized();
|
||||||
|
//
|
||||||
|
int ret = app.exec();
|
||||||
|
app.Uninit();
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
//osg::ArgumentParser arguments(&argc, argv);
|
||||||
|
|
||||||
ret = app.exec();
|
//QMainWindow* mainWindow = new QMainWindow;
|
||||||
return ret;
|
//OsgWidget* viewWidget = new OsgWidget(nullptr, Qt::Widget);
|
||||||
|
//mainWindow->setCentralWidget(viewWidget);
|
||||||
|
//// ViewerWidget* viewWidget = new ViewerWidget(nullptr, Qt::Widget, threadingModel);
|
||||||
|
////viewWidget->setGeometry( 100, 100, 800, 600 );
|
||||||
|
//viewWidget->Initialize();
|
||||||
|
//mainWindow->show();
|
||||||
|
//return app.exec();
|
||||||
}
|
}
|
||||||
|
|||||||
1066
src/osgqt/GraphicsWindowQt.cpp
Normal file
195
src/osgqt/GraphicsWindowQt.h
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
/* -*-c++-*- OpenSceneGraph - Copyright (C) 2009 Wang Rui
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef OSGVIEWER_GRAPHICSWINDOWQT
|
||||||
|
#define OSGVIEWER_GRAPHICSWINDOWQT
|
||||||
|
|
||||||
|
#define USE_NO_STATIC_REGISTRATION 1
|
||||||
|
|
||||||
|
#include <osgViewer/GraphicsWindow>
|
||||||
|
|
||||||
|
#include <QMutex>
|
||||||
|
#include <QEvent>
|
||||||
|
#include <QQueue>
|
||||||
|
#include <QSet>
|
||||||
|
#include <QGLWidget>
|
||||||
|
|
||||||
|
class QInputEvent;
|
||||||
|
class QGestureEvent;
|
||||||
|
|
||||||
|
namespace osgViewer {
|
||||||
|
class ViewerBase;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace osgQt
|
||||||
|
{
|
||||||
|
|
||||||
|
// forward declarations
|
||||||
|
class GraphicsWindowQt;
|
||||||
|
|
||||||
|
#if USE_NO_STATIC_REGISTRATION
|
||||||
|
/// The function sets the WindowingSystem to Qt.
|
||||||
|
void initQtWindowingSystem();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** The function sets the viewer that will be used after entering
|
||||||
|
* the Qt main loop (QCoreApplication::exec()).
|
||||||
|
*
|
||||||
|
* The function also initializes internal structures required for proper
|
||||||
|
* scene rendering.
|
||||||
|
*
|
||||||
|
* The method must be called from main thread. */
|
||||||
|
void setViewer( osgViewer::ViewerBase *viewer );
|
||||||
|
|
||||||
|
|
||||||
|
class GLWidget : public QGLWidget
|
||||||
|
{
|
||||||
|
typedef QGLWidget inherited;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
GLWidget( QWidget* parent = NULL, const QGLWidget* shareWidget = NULL, Qt::WindowFlags f = 0, bool forwardKeyEvents = false );
|
||||||
|
GLWidget( QGLContext* context, QWidget* parent = NULL, const QGLWidget* shareWidget = NULL, Qt::WindowFlags f = 0, bool forwardKeyEvents = false );
|
||||||
|
GLWidget( const QGLFormat& format, QWidget* parent = NULL, const QGLWidget* shareWidget = NULL, Qt::WindowFlags f = 0, bool forwardKeyEvents = false );
|
||||||
|
virtual ~GLWidget();
|
||||||
|
|
||||||
|
inline void setGraphicsWindow( GraphicsWindowQt* gw ) { _gw = gw; }
|
||||||
|
inline GraphicsWindowQt* getGraphicsWindow() { return _gw; }
|
||||||
|
inline const GraphicsWindowQt* getGraphicsWindow() const { return _gw; }
|
||||||
|
|
||||||
|
inline bool getForwardKeyEvents() const { return _forwardKeyEvents; }
|
||||||
|
virtual void setForwardKeyEvents( bool f ) { _forwardKeyEvents = f; }
|
||||||
|
|
||||||
|
inline bool getTouchEventsEnabled() const { return _touchEventsEnabled; }
|
||||||
|
void setTouchEventsEnabled( bool e );
|
||||||
|
|
||||||
|
void setKeyboardModifiers( QInputEvent* event );
|
||||||
|
|
||||||
|
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 );
|
||||||
|
virtual bool gestureEvent( QGestureEvent* event );
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
int getNumDeferredEvents()
|
||||||
|
{
|
||||||
|
QMutexLocker lock(&_deferredEventQueueMutex);
|
||||||
|
return _deferredEventQueue.count();
|
||||||
|
}
|
||||||
|
void enqueueDeferredEvent(QEvent::Type eventType, QEvent::Type removeEventType = QEvent::None)
|
||||||
|
{
|
||||||
|
QMutexLocker lock(&_deferredEventQueueMutex);
|
||||||
|
|
||||||
|
if (removeEventType != QEvent::None)
|
||||||
|
{
|
||||||
|
if (_deferredEventQueue.removeOne(removeEventType))
|
||||||
|
_eventCompressor.remove(eventType);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_eventCompressor.find(eventType) == _eventCompressor.end())
|
||||||
|
{
|
||||||
|
_deferredEventQueue.enqueue(eventType);
|
||||||
|
_eventCompressor.insert(eventType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processDeferredEvents();
|
||||||
|
|
||||||
|
friend class GraphicsWindowQt;
|
||||||
|
GraphicsWindowQt* _gw;
|
||||||
|
|
||||||
|
QMutex _deferredEventQueueMutex;
|
||||||
|
QQueue<QEvent::Type> _deferredEventQueue;
|
||||||
|
QSet<QEvent::Type> _eventCompressor;
|
||||||
|
|
||||||
|
bool _touchEventsEnabled;
|
||||||
|
|
||||||
|
bool _forwardKeyEvents;
|
||||||
|
qreal _devicePixelRatio;
|
||||||
|
|
||||||
|
virtual void resizeEvent( QResizeEvent* event );
|
||||||
|
virtual void moveEvent( QMoveEvent* event );
|
||||||
|
virtual void glDraw();
|
||||||
|
virtual bool event( QEvent* event );
|
||||||
|
};
|
||||||
|
|
||||||
|
class GraphicsWindowQt : public osgViewer::GraphicsWindow
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GraphicsWindowQt( osg::GraphicsContext::Traits* traits, QWidget* parent = NULL, const QGLWidget* shareWidget = NULL, Qt::WindowFlags f = 0 );
|
||||||
|
GraphicsWindowQt( GLWidget* widget );
|
||||||
|
virtual ~GraphicsWindowQt();
|
||||||
|
|
||||||
|
inline GLWidget* getGLWidget() { return _widget; }
|
||||||
|
inline const GLWidget* getGLWidget() const { return _widget; }
|
||||||
|
|
||||||
|
/// deprecated
|
||||||
|
inline GLWidget* getGraphWidget() { return _widget; }
|
||||||
|
/// deprecated
|
||||||
|
inline const GLWidget* getGraphWidget() const { return _widget; }
|
||||||
|
|
||||||
|
struct WindowData : public osg::Referenced
|
||||||
|
{
|
||||||
|
WindowData( GLWidget* widget = NULL, QWidget* parent = NULL ): _widget(widget), _parent(parent) {}
|
||||||
|
GLWidget* _widget;
|
||||||
|
QWidget* _parent;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool init( QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f );
|
||||||
|
|
||||||
|
static QGLFormat traits2qglFormat( const osg::GraphicsContext::Traits* traits );
|
||||||
|
static void qglFormat2traits( const QGLFormat& format, osg::GraphicsContext::Traits* traits );
|
||||||
|
static osg::GraphicsContext::Traits* createTraits( const QGLWidget* widget );
|
||||||
|
|
||||||
|
virtual bool setWindowRectangleImplementation( int x, int y, int width, int height );
|
||||||
|
virtual void getWindowRectangle( int& x, int& y, int& width, int& height );
|
||||||
|
virtual bool setWindowDecorationImplementation( bool windowDecoration );
|
||||||
|
virtual bool getWindowDecoration() const;
|
||||||
|
virtual void grabFocus();
|
||||||
|
virtual void grabFocusIfPointerInWindow();
|
||||||
|
virtual void raiseWindow();
|
||||||
|
virtual void setWindowName( const std::string& name );
|
||||||
|
virtual std::string getWindowName();
|
||||||
|
virtual void useCursor( bool cursorOn );
|
||||||
|
virtual void setCursor( MouseCursor cursor );
|
||||||
|
inline bool getTouchEventsEnabled() const { return _widget->getTouchEventsEnabled(); }
|
||||||
|
virtual void setTouchEventsEnabled( bool e ) { _widget->setTouchEventsEnabled(e); }
|
||||||
|
|
||||||
|
|
||||||
|
virtual bool valid() const;
|
||||||
|
virtual bool realizeImplementation();
|
||||||
|
virtual bool isRealizedImplementation() const;
|
||||||
|
virtual void closeImplementation();
|
||||||
|
virtual bool makeCurrentImplementation();
|
||||||
|
virtual bool releaseContextImplementation();
|
||||||
|
virtual void swapBuffersImplementation();
|
||||||
|
virtual void runOperations();
|
||||||
|
|
||||||
|
virtual void requestWarpPointer( float x, float y );
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
friend class GLWidget;
|
||||||
|
GLWidget* _widget;
|
||||||
|
bool _ownsWidget;
|
||||||
|
QCursor _currentCursor;
|
||||||
|
bool _realized;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
149
src/osgqt/QFontImplementation.cpp
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
/* -*-c++-*- OpenSceneGraph - Copyright (C) 2009-2010 Mathias Froehlich
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
#include "osgqt/QFontImplementation.h"
|
||||||
|
|
||||||
|
#include <osgDB/FileNameUtils>
|
||||||
|
#include <osgDB/Registry>
|
||||||
|
#include <osgText/Font>
|
||||||
|
|
||||||
|
#include <QFont>
|
||||||
|
#include <QFontMetrics>
|
||||||
|
#include <QImage>
|
||||||
|
#include <QPainter>
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef OSGTEXT_GLYPH_INTERNALFORMAT
|
||||||
|
#define OSGTEXT_GLYPH_INTERNALFORMAT GL_LUMINANCE_ALPHA
|
||||||
|
#endif
|
||||||
|
#ifndef OSGTEXT_GLYPH_FORMAT
|
||||||
|
#define OSGTEXT_GLYPH_FORMAT GL_LUMINANCE_ALPHA
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
namespace osgQt {
|
||||||
|
|
||||||
|
QFontImplementation::QFontImplementation(const QFont& font) :
|
||||||
|
_filename(font.toString().toStdString() + ".qfont"),
|
||||||
|
_font(font)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QFontImplementation::~QFontImplementation()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
QFontImplementation::getFileName() const
|
||||||
|
{
|
||||||
|
return _filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
osgText::Glyph*
|
||||||
|
QFontImplementation::getGlyph(const osgText::FontResolution& fontRes, unsigned int charcode)
|
||||||
|
{
|
||||||
|
unsigned int fontSize = fontRes.second;
|
||||||
|
_font.setPixelSize(fontSize);
|
||||||
|
|
||||||
|
float coord_scale = 1.0f/float(fontSize);
|
||||||
|
|
||||||
|
QFontMetrics fontMetrics(_font);
|
||||||
|
QFontMetricsF fontMetricsF(_font);
|
||||||
|
|
||||||
|
QRect rect = fontMetrics.boundingRect(QChar(charcode));
|
||||||
|
QRectF rectF = fontMetricsF.boundingRect(QChar(charcode));
|
||||||
|
|
||||||
|
int margin = 1;
|
||||||
|
|
||||||
|
int imageWidth = rect.width() + 2*margin;
|
||||||
|
int imageHeight = rect.height() + 2*margin;
|
||||||
|
|
||||||
|
// Now paint the glyph into the image
|
||||||
|
QImage image(imageWidth, imageHeight, QImage::Format_ARGB32);
|
||||||
|
image.fill(0);
|
||||||
|
QPainter painter(&image);
|
||||||
|
painter.setRenderHint(QPainter::TextAntialiasing);
|
||||||
|
|
||||||
|
painter.setFont(_font);
|
||||||
|
|
||||||
|
painter.setBackgroundMode(Qt::TransparentMode);
|
||||||
|
painter.setBrush(Qt::white);
|
||||||
|
painter.setPen(Qt::white);
|
||||||
|
|
||||||
|
painter.drawText(margin - rect.left(), imageHeight - 1 - (margin + rect.bottom()), QString(QChar(charcode)));
|
||||||
|
painter.end();
|
||||||
|
|
||||||
|
// Transfer the rendered image to osg
|
||||||
|
osg::ref_ptr<osgText::Glyph> glyph = new osgText::Glyph(_facade, charcode);
|
||||||
|
|
||||||
|
unsigned int dataSize = imageWidth*imageHeight;
|
||||||
|
unsigned char* data = new unsigned char[dataSize];
|
||||||
|
|
||||||
|
// copy the qimage into the texture memory
|
||||||
|
for (int x = 0; x < imageWidth; ++x)
|
||||||
|
{
|
||||||
|
for (int y = 0; y < imageHeight; ++y)
|
||||||
|
{
|
||||||
|
data[x + y*imageWidth] = qAlpha(image.pixel(x, imageHeight - 1 - y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// the glyph texture in osg
|
||||||
|
glyph->setImage(imageWidth, imageHeight, 1,
|
||||||
|
OSGTEXT_GLYPH_INTERNALFORMAT,
|
||||||
|
OSGTEXT_GLYPH_FORMAT, GL_UNSIGNED_BYTE,
|
||||||
|
data,
|
||||||
|
osg::Image::USE_NEW_DELETE,
|
||||||
|
1);
|
||||||
|
glyph->setInternalTextureFormat(OSGTEXT_GLYPH_INTERNALFORMAT);
|
||||||
|
|
||||||
|
glyph->setWidth((float)imageWidth * coord_scale);
|
||||||
|
glyph->setHeight((float)imageHeight * coord_scale);
|
||||||
|
|
||||||
|
// Layout parameters
|
||||||
|
float leftBearing = fontMetricsF.leftBearing(QChar(charcode));
|
||||||
|
float rightBearing = fontMetricsF.rightBearing(QChar(charcode));
|
||||||
|
|
||||||
|
// for horizonal layout
|
||||||
|
osg::Vec2 bottomLeft(leftBearing - margin, - rectF.bottom() - margin);
|
||||||
|
glyph->setHorizontalBearing(bottomLeft * coord_scale);
|
||||||
|
glyph->setHorizontalAdvance(fontMetricsF.width(QChar(charcode)) * coord_scale);
|
||||||
|
|
||||||
|
// for vertical layout
|
||||||
|
osg::Vec2 topMiddle(- margin + 0.5*(leftBearing - rect.width() - rightBearing),
|
||||||
|
rectF.top() - margin);
|
||||||
|
glyph->setVerticalBearing(topMiddle * coord_scale);
|
||||||
|
glyph->setVerticalAdvance((rectF.height() + fontMetricsF.overlinePos() - fontMetricsF.xHeight()) * coord_scale);
|
||||||
|
|
||||||
|
// ... ready
|
||||||
|
//addGlyph(fontRes, charcode, glyph.get());
|
||||||
|
|
||||||
|
return glyph.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
//osg::Vec2
|
||||||
|
//QFontImplementation::getKerning(const osgText::FontResolution& /*fontRes*/, unsigned int /*leftcharcode*/, unsigned int /*rightcharcode*/, osgText::KerningType /*kerningType*/)
|
||||||
|
//{
|
||||||
|
// return osg::Vec2(0, 0);
|
||||||
|
//}
|
||||||
|
|
||||||
|
osg::Vec2 QFontImplementation::getKerning(unsigned int leftcharcode, unsigned int rightcharcode, osgText::KerningType kerningType) {
|
||||||
|
return osg::Vec2(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
QFontImplementation::hasVertical() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
52
src/osgqt/QFontImplementation.h
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/* -*-c++-*- OpenSceneGraph - Copyright (C) 2009-2010 Mathias Froehlich
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
#ifndef QFontImplementation_H
|
||||||
|
#define QFontImplementation_H
|
||||||
|
|
||||||
|
#include <osgText/Font>
|
||||||
|
|
||||||
|
#include <QtGui/QFont>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace osgQt {
|
||||||
|
|
||||||
|
class QFontImplementation : public osgText::Font::FontImplementation
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QFontImplementation(const QFont& font);
|
||||||
|
virtual ~QFontImplementation();
|
||||||
|
|
||||||
|
virtual std::string getFileName() const;
|
||||||
|
|
||||||
|
virtual bool supportsMultipleFontResolutions() const { return true; }
|
||||||
|
|
||||||
|
virtual osgText::Glyph* getGlyph(const osgText::FontResolution& fontRes, unsigned int charcode);
|
||||||
|
|
||||||
|
//virtual osgText::Glyph3D* getGlyph3D(const osgText::FontResolution& /*fontRes*/, unsigned int /*charcode*/) { return 0; }
|
||||||
|
virtual osgText::Glyph3D* getGlyph3D(unsigned int charcode) { return 0; }
|
||||||
|
|
||||||
|
//virtual osg::Vec2 getKerning(const osgText::FontResolution& fontRes, unsigned int leftcharcode, unsigned int rightcharcode, osgText::KerningType kerningType);
|
||||||
|
virtual osg::Vec2 getKerning(unsigned int leftcharcode, unsigned int rightcharcode, osgText::KerningType kerningType);
|
||||||
|
|
||||||
|
virtual bool hasVertical() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
std::string _filename;
|
||||||
|
QFont _font;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
613
src/osgqt/QGraphicsViewAdapter.cpp
Normal file
@ -0,0 +1,613 @@
|
|||||||
|
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2009 Robert Osfield
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "osgqt/QGraphicsViewAdapter.h"
|
||||||
|
#include "osgqt/QWidgetImage.h"
|
||||||
|
|
||||||
|
#include <QtOpenGL/QGLWidget>
|
||||||
|
|
||||||
|
#include <osg/Version>
|
||||||
|
#include <osgGA/GUIEventAdapter>
|
||||||
|
|
||||||
|
#include <osg/NodeVisitor>
|
||||||
|
#include <osg/io_utils>
|
||||||
|
#include <QGraphicsItem>
|
||||||
|
#include <QGraphicsProxyWidget>
|
||||||
|
|
||||||
|
#define MYQKEYEVENT 2000
|
||||||
|
#define MYQPOINTEREVENT 2001
|
||||||
|
|
||||||
|
namespace osgQt
|
||||||
|
{
|
||||||
|
|
||||||
|
QCoreApplication* getOrCreateQApplication()
|
||||||
|
{
|
||||||
|
if (QApplication::instance()==0)
|
||||||
|
{
|
||||||
|
static char** argv = 0;
|
||||||
|
static int argc = 0;
|
||||||
|
static QApplication app(argc,argv);
|
||||||
|
}
|
||||||
|
return QApplication::instance();
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyQKeyEvent : public QEvent
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MyQKeyEvent( int key, bool down ):
|
||||||
|
QEvent( QEvent::Type(MYQKEYEVENT) ),
|
||||||
|
_key(key), _down(down) {}
|
||||||
|
|
||||||
|
int _key;
|
||||||
|
bool _down;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MyQPointerEvent : public QEvent
|
||||||
|
{
|
||||||
|
MyQPointerEvent(int x, int y, unsigned int buttonMask):
|
||||||
|
QEvent( QEvent::Type(MYQPOINTEREVENT) ),
|
||||||
|
_x(x), _y(y),_buttonMask(buttonMask) {}
|
||||||
|
|
||||||
|
int _x, _y;
|
||||||
|
unsigned int _buttonMask;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const QImage::Format s_imageFormat = QImage::Format_ARGB32_Premultiplied;
|
||||||
|
|
||||||
|
QGraphicsViewAdapter::QGraphicsViewAdapter(osg::Image* image, QWidget* widget):
|
||||||
|
_image(image),
|
||||||
|
_backgroundWidget(0),
|
||||||
|
_previousButtonMask(0),
|
||||||
|
_previousMouseX(-1),
|
||||||
|
_previousMouseY(-1),
|
||||||
|
_previousQtMouseX(-1),
|
||||||
|
_previousQtMouseY(-1),
|
||||||
|
_previousSentEvent(false),
|
||||||
|
_requiresRendering(false),
|
||||||
|
_qtKeyModifiers(Qt::NoModifier),
|
||||||
|
_backgroundColor(255, 255, 255),
|
||||||
|
_widget(widget)
|
||||||
|
{
|
||||||
|
// make sure we have a valid QApplication before we start creating widgets.
|
||||||
|
getOrCreateQApplication();
|
||||||
|
|
||||||
|
|
||||||
|
setUpKeyMap();
|
||||||
|
|
||||||
|
_graphicsScene = new QGraphicsScene;
|
||||||
|
_graphicsScene->addWidget(widget);
|
||||||
|
|
||||||
|
_graphicsView = new QGraphicsView;
|
||||||
|
_graphicsView->setScene(_graphicsScene);
|
||||||
|
_graphicsView->viewport()->setParent(0);
|
||||||
|
|
||||||
|
#if (QT_VERSION_CHECK(4, 5, 0) <= QT_VERSION)
|
||||||
|
_graphicsScene->setStickyFocus(true);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
_width = static_cast<int>(_graphicsScene->width());
|
||||||
|
_height = static_cast<int>(_graphicsScene->height());
|
||||||
|
|
||||||
|
_qimages[0] = QImage(QSize(_width, _height), s_imageFormat);
|
||||||
|
_qimages[1] = QImage(QSize(_width, _height), s_imageFormat);
|
||||||
|
_qimages[2] = QImage(QSize(_width, _height), s_imageFormat);
|
||||||
|
|
||||||
|
_currentRead = 0;
|
||||||
|
_currentWrite = 1;
|
||||||
|
_previousWrite = 2;
|
||||||
|
_previousFrameNumber = osg::UNINITIALIZED_FRAME_NUMBER;
|
||||||
|
_newImageAvailable = false;
|
||||||
|
|
||||||
|
connect(_graphicsScene, SIGNAL(changed(const QList<QRectF> &)),
|
||||||
|
this, SLOT(repaintRequestedSlot(const QList<QRectF> &)));
|
||||||
|
connect(_graphicsScene, SIGNAL(sceneRectChanged(const QRectF &)),
|
||||||
|
this, SLOT(repaintRequestedSlot(const QRectF &)));
|
||||||
|
|
||||||
|
assignImage(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QGraphicsViewAdapter::repaintRequestedSlot(const QList<QRectF>&)
|
||||||
|
{
|
||||||
|
// OSG_NOTICE<<"QGraphicsViewAdapter::repaintRequestedSlot"<<std::endl;
|
||||||
|
_requiresRendering = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QGraphicsViewAdapter::repaintRequestedSlot(const QRectF&)
|
||||||
|
{
|
||||||
|
// OSG_NOTICE<<"QGraphicsViewAdapter::repaintRequestedSlot"<<std::endl;
|
||||||
|
_requiresRendering = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QGraphicsViewAdapter::customEvent ( QEvent * event )
|
||||||
|
{
|
||||||
|
if (event->type()==MYQKEYEVENT)
|
||||||
|
{
|
||||||
|
MyQKeyEvent* keyEvent = (MyQKeyEvent*)event;
|
||||||
|
handleKeyEvent(keyEvent->_key, keyEvent->_down);
|
||||||
|
}
|
||||||
|
else if (event->type()==MYQPOINTEREVENT)
|
||||||
|
{
|
||||||
|
MyQPointerEvent* pointerEvent = (MyQPointerEvent*)event;
|
||||||
|
handlePointerEvent(pointerEvent->_x, pointerEvent->_y, pointerEvent->_buttonMask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void QGraphicsViewAdapter::setUpKeyMap()
|
||||||
|
{
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_BackSpace] = Qt::Key_Backspace;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_Tab] = Qt::Key_Tab;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_Linefeed] = Qt::Key_Return; // No LineFeed in Qt!
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_Clear] = Qt::Key_Clear;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_Return] = Qt::Key_Return;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_Pause] = Qt::Key_Pause;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_Scroll_Lock] = Qt::Key_ScrollLock;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_Sys_Req] = Qt::Key_SysReq;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_Escape] = Qt::Key_Escape;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_Delete] = Qt::Key_Delete;
|
||||||
|
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_Home] = Qt::Key_Home;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_Left] = Qt::Key_Left;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_Up] = Qt::Key_Up;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_Right] = Qt::Key_Right;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_Down] = Qt::Key_Down;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_Prior] = Qt::Key_Left; // no Prior in Qt
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_Page_Up] = Qt::Key_PageUp;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_Next] = Qt::Key_Right; // No Next in Qt
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_Page_Down] = Qt::Key_PageDown;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_End] = Qt::Key_End;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_Begin] = Qt::Key_Home; // No Begin in Qt
|
||||||
|
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_Select] = Qt::Key_Select;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_Print] = Qt::Key_Print;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_Execute] = Qt::Key_Execute;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_Insert] = Qt::Key_Insert;
|
||||||
|
//_keyMap[osgGA::GUIEventAdapter::KEY_Undo] = Qt::Key_; // no Undo
|
||||||
|
//_keyMap[osgGA::GUIEventAdapter::KEY_Redo] = Qt::Key_; // no Redo
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_Menu] = Qt::Key_Menu;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_Find] = Qt::Key_Search; // no Qt Find
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_Cancel] = Qt::Key_Cancel;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_Help] = Qt::Key_Help;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_Break] = Qt::Key_Escape; // no break
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_Mode_switch] = Qt::Key_Mode_switch;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_Script_switch] = Qt::Key_Mode_switch; // no Script switch
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_Num_Lock] = Qt::Key_NumLock;
|
||||||
|
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_Shift_L] = Qt::Key_Shift;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_Shift_R] = Qt::Key_Shift;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_Control_L] = Qt::Key_Control;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_Control_R] = Qt::Key_Control;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_Caps_Lock] = Qt::Key_CapsLock;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_Shift_Lock] = Qt::Key_CapsLock;
|
||||||
|
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_Meta_L] = Qt::Key_Meta; // Qt doesn't have a Meta L
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_Meta_R] = Qt::Key_Meta; // Qt doesn't have a Meta R
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_Alt_L] = Qt::Key_Alt; // Qt doesn't have a Alt L
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_Alt_R] = Qt::Key_Alt; // Qt doesn't have a Alt R
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_Super_L] = Qt::Key_Super_L;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_Super_R] = Qt::Key_Super_R;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_Hyper_L] = Qt::Key_Hyper_L;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_Hyper_R] = Qt::Key_Hyper_R;
|
||||||
|
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_KP_Space] = Qt::Key_Space;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_KP_Tab] = Qt::Key_Tab;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_KP_Enter] = Qt::Key_Enter;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_KP_F1] = Qt::Key_F1;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_KP_F2] = Qt::Key_F2;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_KP_F3] = Qt::Key_F3;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_KP_F4] = Qt::Key_F4;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_KP_Home] = Qt::Key_Home;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_KP_Left] = Qt::Key_Left;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_KP_Up] = Qt::Key_Up;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_KP_Right] = Qt::Key_Right;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_KP_Down] = Qt::Key_Down;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_KP_Prior] = Qt::Key_Left;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_KP_Page_Up] = Qt::Key_PageUp;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_KP_Next] = Qt::Key_Right;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_KP_Page_Down] = Qt::Key_PageDown;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_KP_End] = Qt::Key_End;
|
||||||
|
|
||||||
|
// _keyMap[osgGA::GUIEventAdapter::KEY_KP_Begin] = Qt::Key_Begin;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_KP_Insert] = Qt::Key_Insert;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_KP_Delete] = Qt::Key_Delete;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_KP_Equal] = Qt::Key_Equal;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_KP_Multiply] = Qt::Key_Asterisk;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_KP_Add] = Qt::Key_Plus;
|
||||||
|
//_keyMap[osgGA::GUIEventAdapter::KEY_KP_Separator] = Qt::Key_;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_KP_Subtract] = Qt::Key_Minus;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_KP_Decimal] = Qt::Key_Period;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_KP_Divide] = Qt::Key_division;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_KP_0] = Qt::Key_0;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_KP_1] = Qt::Key_1;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_KP_2] = Qt::Key_2;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_KP_3] = Qt::Key_3;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_KP_4] = Qt::Key_4;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_KP_5] = Qt::Key_5;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_KP_6] = Qt::Key_6;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_KP_7] = Qt::Key_7;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_KP_8] = Qt::Key_8;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_KP_9] = Qt::Key_9;
|
||||||
|
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_F1] = Qt::Key_F1;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_F2] = Qt::Key_F2;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_F3] = Qt::Key_F3;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_F4] = Qt::Key_F4;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_F5] = Qt::Key_F5;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_F6] = Qt::Key_F6;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_F7] = Qt::Key_F7;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_F8] = Qt::Key_F8;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_F9] = Qt::Key_F9;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_F10] = Qt::Key_F10;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_F11] = Qt::Key_F11;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_F12] = Qt::Key_F12;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_F13] = Qt::Key_F13;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_F14] = Qt::Key_F14;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_F15] = Qt::Key_F15;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_F16] = Qt::Key_F16;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_F17] = Qt::Key_F17;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_F18] = Qt::Key_F18;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_F19] = Qt::Key_F19;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_F20] = Qt::Key_F20;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_F21] = Qt::Key_F21;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_F22] = Qt::Key_F22;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_F23] = Qt::Key_F23;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_F24] = Qt::Key_F24;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_F25] = Qt::Key_F25;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_F26] = Qt::Key_F26;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_F27] = Qt::Key_F27;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_F28] = Qt::Key_F28;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_F29] = Qt::Key_F29;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_F30] = Qt::Key_F30;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_F31] = Qt::Key_F31;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_F32] = Qt::Key_F32;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_F33] = Qt::Key_F33;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_F34] = Qt::Key_F34;
|
||||||
|
_keyMap[osgGA::GUIEventAdapter::KEY_F35] = Qt::Key_F35;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget* QGraphicsViewAdapter::getWidgetAt(const QPoint& pos)
|
||||||
|
{
|
||||||
|
QWidget* childAt = _graphicsView->childAt(pos);
|
||||||
|
if(childAt)
|
||||||
|
{
|
||||||
|
return childAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
QGraphicsItem* item = _graphicsView->itemAt(pos);
|
||||||
|
if(item /*&& item->contains(item->mapFromScene(pos))*/)
|
||||||
|
{
|
||||||
|
QGraphicsProxyWidget* p = qgraphicsitem_cast<QGraphicsProxyWidget*>(item);
|
||||||
|
if(p)
|
||||||
|
{
|
||||||
|
childAt = p->widget();
|
||||||
|
QWidget* c;
|
||||||
|
while( (c = childAt->childAt(childAt->mapFromGlobal(pos)))!=0 )
|
||||||
|
{
|
||||||
|
childAt = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Widgets like QTextEdit will automatically add child scroll area widgets
|
||||||
|
// that will be selected by childAt(), we have to change to parents at that moment
|
||||||
|
// Hardcoded by the internal widget's name 'qt_scrollarea_viewport' at present
|
||||||
|
if (childAt->objectName() == "qt_scrollarea_viewport")
|
||||||
|
{
|
||||||
|
childAt = childAt->parentWidget();
|
||||||
|
}
|
||||||
|
return childAt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QGraphicsViewAdapter::sendPointerEvent(int x, int y, int buttonMask)
|
||||||
|
{
|
||||||
|
_previousQtMouseX = x;
|
||||||
|
_previousQtMouseY = _graphicsView->size().height() - y;
|
||||||
|
|
||||||
|
QPoint pos(_previousQtMouseX, _previousQtMouseY);
|
||||||
|
|
||||||
|
QWidget* targetWidget = getWidgetAt(pos);
|
||||||
|
OSG_INFO << "Get " << (targetWidget ? targetWidget->metaObject()->className() : std::string("NULL"))
|
||||||
|
<< " at global pos " << x << ", " << y << std::endl;
|
||||||
|
|
||||||
|
if (_backgroundWidget && _backgroundWidget == targetWidget)
|
||||||
|
{
|
||||||
|
// Mouse is at background widget, so ignore such events
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targetWidget != NULL || (_previousSentEvent && buttonMask != 0))
|
||||||
|
{
|
||||||
|
QCoreApplication::postEvent(this, new MyQPointerEvent(x,y,buttonMask));
|
||||||
|
OSG_INFO<<"sendPointerEvent("<<x<<", "<<y<<") sent"<<std::endl;
|
||||||
|
_previousSentEvent = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
OSG_INFO<<"sendPointerEvent("<<x<<", "<<y<<") not sent"<<std::endl;
|
||||||
|
_previousSentEvent = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QGraphicsViewAdapter::handlePointerEvent(int x, int y, int buttonMask)
|
||||||
|
{
|
||||||
|
OSG_INFO<<"dispatchPointerEvent("<<x<<", "<<y<<", "<<buttonMask<<")"<<std::endl;
|
||||||
|
|
||||||
|
y = _graphicsView->size().height()-y;
|
||||||
|
|
||||||
|
bool leftButtonPressed = (buttonMask & osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON)!=0;
|
||||||
|
bool middleButtonPressed = (buttonMask & osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON)!=0;
|
||||||
|
bool rightButtonPressed = (buttonMask & osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON)!=0;
|
||||||
|
|
||||||
|
bool prev_leftButtonPressed = (_previousButtonMask & osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON)!=0;
|
||||||
|
bool prev_middleButtonPressed = (_previousButtonMask & osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON)!=0;
|
||||||
|
bool prev_rightButtonPressed = (_previousButtonMask & osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON)!=0;
|
||||||
|
|
||||||
|
OSG_INFO<<"leftButtonPressed "<<leftButtonPressed<<std::endl;
|
||||||
|
OSG_INFO<<"middleButtonPressed "<<middleButtonPressed<<std::endl;
|
||||||
|
OSG_INFO<<"rightButtonPressed "<<rightButtonPressed<<std::endl;
|
||||||
|
|
||||||
|
Qt::MouseButtons qtMouseButtons =
|
||||||
|
(leftButtonPressed ? Qt::LeftButton : Qt::NoButton) |
|
||||||
|
(middleButtonPressed ? Qt::MidButton : Qt::NoButton) |
|
||||||
|
(rightButtonPressed ? Qt::RightButton : Qt::NoButton);
|
||||||
|
|
||||||
|
const QPoint globalPos(x, y);
|
||||||
|
QWidget* targetWidget = getWidgetAt(globalPos);
|
||||||
|
|
||||||
|
if (buttonMask != _previousButtonMask)
|
||||||
|
{
|
||||||
|
Qt::MouseButton qtButton = Qt::NoButton;
|
||||||
|
QEvent::Type eventType = QEvent::None;
|
||||||
|
if (leftButtonPressed != prev_leftButtonPressed)
|
||||||
|
{
|
||||||
|
qtButton = Qt::LeftButton;
|
||||||
|
eventType = leftButtonPressed ? QEvent::MouseButtonPress : QEvent::MouseButtonRelease ;
|
||||||
|
}
|
||||||
|
else if (middleButtonPressed != prev_middleButtonPressed)
|
||||||
|
{
|
||||||
|
qtButton = Qt::MidButton;
|
||||||
|
eventType = middleButtonPressed ? QEvent::MouseButtonPress : QEvent::MouseButtonRelease ;
|
||||||
|
}
|
||||||
|
else if (rightButtonPressed != prev_rightButtonPressed)
|
||||||
|
{
|
||||||
|
qtButton = Qt::RightButton;
|
||||||
|
eventType = rightButtonPressed ? QEvent::MouseButtonPress : QEvent::MouseButtonRelease ;
|
||||||
|
if(!rightButtonPressed)
|
||||||
|
{
|
||||||
|
if(targetWidget)
|
||||||
|
{
|
||||||
|
QPoint localPos = targetWidget->mapFromGlobal(globalPos);
|
||||||
|
QContextMenuEvent* cme = new QContextMenuEvent(QContextMenuEvent::Mouse, localPos, globalPos);
|
||||||
|
QCoreApplication::postEvent(targetWidget, cme);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eventType==QEvent::MouseButtonPress)
|
||||||
|
{
|
||||||
|
_image->sendFocusHint(true);
|
||||||
|
if (targetWidget) targetWidget->setFocus(Qt::MouseFocusReason);
|
||||||
|
}
|
||||||
|
|
||||||
|
QMouseEvent event(eventType, globalPos, qtButton, qtMouseButtons, 0);
|
||||||
|
QCoreApplication::sendEvent(_graphicsView->viewport(), &event);
|
||||||
|
|
||||||
|
_previousButtonMask = buttonMask;
|
||||||
|
}
|
||||||
|
else if (x != _previousMouseX || y != _previousMouseY)
|
||||||
|
{
|
||||||
|
QMouseEvent event(QEvent::MouseMove, globalPos, Qt::NoButton, qtMouseButtons, 0);
|
||||||
|
QCoreApplication::sendEvent(_graphicsView->viewport(), &event);
|
||||||
|
|
||||||
|
_previousMouseX = x;
|
||||||
|
_previousMouseY = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QGraphicsViewAdapter::sendKeyEvent(int key, bool keyDown)
|
||||||
|
{
|
||||||
|
QPoint pos(_previousQtMouseX, _previousQtMouseY);
|
||||||
|
QWidget* targetWidget = getWidgetAt(pos);
|
||||||
|
if (_backgroundWidget && _backgroundWidget == targetWidget)
|
||||||
|
{
|
||||||
|
// Mouse is at background widget, so ignore such events
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targetWidget != NULL)
|
||||||
|
{
|
||||||
|
QCoreApplication::postEvent(this, new MyQKeyEvent(key,keyDown));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QGraphicsViewAdapter::handleKeyEvent(int key, bool keyDown)
|
||||||
|
{
|
||||||
|
QEvent::Type eventType = keyDown ? QEvent::KeyPress : QEvent::KeyRelease;
|
||||||
|
|
||||||
|
OSG_INFO<<"sendKeyEvent("<<key<<", "<<keyDown<<")"<<std::endl;
|
||||||
|
|
||||||
|
if (key==Qt::Key_Shift)
|
||||||
|
{
|
||||||
|
_qtKeyModifiers = (_qtKeyModifiers & ~Qt::ShiftModifier) | (keyDown ? Qt::ShiftModifier : Qt::NoModifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key==Qt::Key_Control)
|
||||||
|
{
|
||||||
|
_qtKeyModifiers = (_qtKeyModifiers & ~Qt::ControlModifier) | (keyDown ? Qt::ControlModifier : Qt::NoModifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key==Qt::Key_Alt || key==Qt::Key_AltGr)
|
||||||
|
{
|
||||||
|
_qtKeyModifiers = (_qtKeyModifiers & ~Qt::ControlModifier) | (keyDown ? Qt::ControlModifier : Qt::NoModifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key==Qt::Key_Meta)
|
||||||
|
{
|
||||||
|
_qtKeyModifiers = (_qtKeyModifiers & ~Qt::MetaModifier) | (keyDown ? Qt::MetaModifier : Qt::NoModifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
Qt::Key qtkey;
|
||||||
|
QChar input;
|
||||||
|
|
||||||
|
KeyMap::iterator itr = _keyMap.find(key);
|
||||||
|
if (itr != _keyMap.end())
|
||||||
|
{
|
||||||
|
qtkey = itr->second;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qtkey = (Qt::Key)key;
|
||||||
|
input = QChar(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
QKeyEvent event(eventType, qtkey, _qtKeyModifiers, input);
|
||||||
|
QCoreApplication::sendEvent(_graphicsScene.data(), &event);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QGraphicsViewAdapter::setFrameLastRendered(const osg::FrameStamp* frameStamp)
|
||||||
|
{
|
||||||
|
OSG_INFO<<"setFrameLastRendered("<<frameStamp->getFrameNumber()<<")"<<std::endl;
|
||||||
|
|
||||||
|
if (_newImageAvailable && _previousFrameNumber!=frameStamp->getFrameNumber())
|
||||||
|
{
|
||||||
|
{
|
||||||
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_qimagesMutex);
|
||||||
|
|
||||||
|
// make sure that _previousFrameNumber hasn't been updated by another thread since we entered this branch.
|
||||||
|
if (_previousFrameNumber==frameStamp->getFrameNumber()) return;
|
||||||
|
_previousFrameNumber = frameStamp->getFrameNumber();
|
||||||
|
|
||||||
|
std::swap(_currentRead, _previousWrite);
|
||||||
|
_newImageAvailable = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
assignImage(_currentRead);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QGraphicsViewAdapter::clearWriteBuffer()
|
||||||
|
{
|
||||||
|
QImage& image = _qimages[_currentWrite];
|
||||||
|
image.fill(_backgroundColor.rgba ());
|
||||||
|
image = QGLWidget::convertToGLFormat(image);
|
||||||
|
|
||||||
|
// swap the write buffers in a thread safe way
|
||||||
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_qimagesMutex);
|
||||||
|
std::swap(_currentWrite, _previousWrite);
|
||||||
|
_newImageAvailable = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QGraphicsViewAdapter::render()
|
||||||
|
{
|
||||||
|
OSG_INFO<<"Current write = "<<_currentWrite<<std::endl;
|
||||||
|
QImage& image = _qimages[_currentWrite];
|
||||||
|
_requiresRendering = false;
|
||||||
|
|
||||||
|
// If we got a resize, act on it, first by resizing the view, then the current image
|
||||||
|
|
||||||
|
{
|
||||||
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_qresizeMutex);
|
||||||
|
if (_graphicsView->size().width() != _width || _graphicsView->size().height() != _height)
|
||||||
|
{
|
||||||
|
_graphicsView->setGeometry(0, 0, _width, _height);
|
||||||
|
_graphicsView->viewport()->setGeometry(0, 0, _width, _height);
|
||||||
|
|
||||||
|
_widget->setGeometry(0, 0, _width, _height);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (image.width() != _width || image.height() != _height)
|
||||||
|
{
|
||||||
|
_qimages[_currentWrite] = QImage(_width, _height, s_imageFormat);
|
||||||
|
image = _qimages[_currentWrite];
|
||||||
|
}
|
||||||
|
OSG_INFO << "render image " << _currentWrite << " with size (" << _width << "," << _height << ")" <<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
// paint the image with the graphics view
|
||||||
|
QPainter painter(&image);
|
||||||
|
|
||||||
|
// Clear the image otherwise there are artifacts for some widgets that overpaint.
|
||||||
|
painter.setCompositionMode(QPainter::CompositionMode_Source);
|
||||||
|
painter.fillRect(0, 0, image.width(), image.height(), _backgroundColor);
|
||||||
|
painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
|
||||||
|
|
||||||
|
QRectF destinationRect(0, 0, image.width(), image.height());
|
||||||
|
QRect sourceRect(0, 0, image.width(), image.height());
|
||||||
|
_graphicsView->render(&painter, destinationRect, sourceRect, Qt::IgnoreAspectRatio);
|
||||||
|
painter.end();
|
||||||
|
#elif 0
|
||||||
|
QPixmap pixmap(QPixmap::grabWidget(_graphicsView.data(), QRect(0, 0, image.width(), image.height())));
|
||||||
|
image = pixmap.toImage();
|
||||||
|
#else
|
||||||
|
// paint the image with the graphics view
|
||||||
|
QPixmap pixmap(image.width(), image.height());
|
||||||
|
// Clear the image otherwise there are artifacts for some widgets that overpaint.
|
||||||
|
pixmap.fill(Qt::transparent);
|
||||||
|
QPainter painter(&pixmap);
|
||||||
|
|
||||||
|
QRectF destinationRect(0, 0, image.width(), image.height());
|
||||||
|
QRect sourceRect(0, 0, image.width(), image.height());
|
||||||
|
_graphicsView->render(&painter, destinationRect, _graphicsView->viewport()->rect());
|
||||||
|
painter.end();
|
||||||
|
|
||||||
|
image = pixmap.toImage();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// convert into OpenGL format - flipping around the Y axis and swizzling the pixels
|
||||||
|
image = QGLWidget::convertToGLFormat(image);
|
||||||
|
|
||||||
|
// swap the write buffers in a thread safe way
|
||||||
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_qimagesMutex);
|
||||||
|
std::swap(_currentWrite, _previousWrite);
|
||||||
|
_newImageAvailable = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QGraphicsViewAdapter::assignImage(unsigned int i)
|
||||||
|
{
|
||||||
|
QImage& image = _qimages[i];
|
||||||
|
unsigned char* data = image.bits();
|
||||||
|
|
||||||
|
OSG_INFO<<"assignImage("<<i<<") image = "<<&image<<" size = ("<<image.width()<<","<<image.height()<<") data = "<<(void*)data<<std::endl;
|
||||||
|
|
||||||
|
_image->setImage(image.width(), image.height(), 1,
|
||||||
|
4, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||||
|
data, osg::Image::NO_DELETE, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QGraphicsViewAdapter::resize(int width, int height)
|
||||||
|
{
|
||||||
|
OSG_INFO << "resize to (" << width << "," << height << ")" <<std::endl;
|
||||||
|
|
||||||
|
// Save the new width and height which will take effect on the next render() (in the Qt thread).
|
||||||
|
|
||||||
|
{
|
||||||
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_qresizeMutex);
|
||||||
|
_width = width;
|
||||||
|
_height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Force an update so render() will be called.
|
||||||
|
_graphicsScene->update(_graphicsScene->sceneRect());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
122
src/osgqt/QGraphicsViewAdapter.h
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2009 Robert Osfield
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef QGRAPHICSVIEWADAPTER
|
||||||
|
#define QGRAPHICSVIEWADAPTER
|
||||||
|
|
||||||
|
#include <QGLWidget>
|
||||||
|
|
||||||
|
#include <osg/Image>
|
||||||
|
#include <osg/observer_ptr>
|
||||||
|
|
||||||
|
#include <QPointer>
|
||||||
|
#include <QGraphicsScene>
|
||||||
|
#include <QGraphicsView>
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QtEvents>
|
||||||
|
|
||||||
|
namespace osgQt
|
||||||
|
{
|
||||||
|
|
||||||
|
extern QCoreApplication* getOrCreateQApplication();
|
||||||
|
|
||||||
|
class QGraphicsViewAdapter : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
QGraphicsViewAdapter(osg::Image* image, QWidget* widget);
|
||||||
|
|
||||||
|
void setUpKeyMap();
|
||||||
|
|
||||||
|
bool sendPointerEvent(int x, int y, int buttonMask);
|
||||||
|
|
||||||
|
|
||||||
|
bool sendKeyEvent(int key, bool keyDown);
|
||||||
|
|
||||||
|
|
||||||
|
void setFrameLastRendered(const osg::FrameStamp* frameStamp);
|
||||||
|
|
||||||
|
void clearWriteBuffer();
|
||||||
|
|
||||||
|
bool requiresRendering() const { return _requiresRendering; }
|
||||||
|
void render();
|
||||||
|
|
||||||
|
void assignImage(unsigned int i);
|
||||||
|
|
||||||
|
void resize(int width, int height);
|
||||||
|
|
||||||
|
void setBackgroundColor(QColor color) { _backgroundColor = color; }
|
||||||
|
QColor getBackgroundColor() const { return _backgroundColor; }
|
||||||
|
|
||||||
|
/** The 'background widget' will ignore mouse/keyboard events and let following handlers handle them
|
||||||
|
It is mainly used for integrating scene graph and full-screen UIs
|
||||||
|
*/
|
||||||
|
void setBackgroundWidget(QWidget* w) { _backgroundWidget = w; }
|
||||||
|
QWidget* getBackgroundWidget() { return _backgroundWidget; }
|
||||||
|
|
||||||
|
QGraphicsView* getQGraphicsView() { return _graphicsView; }
|
||||||
|
QGraphicsScene* getQGraphicsScene() { return _graphicsScene; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
bool handlePointerEvent(int x, int y, int buttonMask);
|
||||||
|
bool handleKeyEvent(int key, bool keyDown);
|
||||||
|
QWidget* getWidgetAt(const QPoint& pos);
|
||||||
|
|
||||||
|
osg::observer_ptr<osg::Image> _image;
|
||||||
|
QWidget* _backgroundWidget;
|
||||||
|
|
||||||
|
int _previousButtonMask;
|
||||||
|
int _previousMouseX;
|
||||||
|
int _previousMouseY;
|
||||||
|
int _previousQtMouseX;
|
||||||
|
int _previousQtMouseY;
|
||||||
|
bool _previousSentEvent;
|
||||||
|
bool _requiresRendering;
|
||||||
|
|
||||||
|
int _width;
|
||||||
|
int _height;
|
||||||
|
|
||||||
|
typedef std::map<int, Qt::Key> KeyMap;
|
||||||
|
KeyMap _keyMap;
|
||||||
|
Qt::KeyboardModifiers _qtKeyModifiers;
|
||||||
|
|
||||||
|
QColor _backgroundColor;
|
||||||
|
QPointer<QGraphicsView> _graphicsView;
|
||||||
|
QPointer<QGraphicsScene> _graphicsScene;
|
||||||
|
QPointer<QWidget> _widget;
|
||||||
|
|
||||||
|
OpenThreads::Mutex _qimagesMutex;
|
||||||
|
OpenThreads::Mutex _qresizeMutex;
|
||||||
|
unsigned int _previousFrameNumber;
|
||||||
|
bool _newImageAvailable;
|
||||||
|
unsigned int _currentRead;
|
||||||
|
unsigned int _currentWrite;
|
||||||
|
unsigned int _previousWrite;
|
||||||
|
QImage _qimages[3];
|
||||||
|
|
||||||
|
virtual void customEvent ( QEvent * event ) ;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
|
||||||
|
void repaintRequestedSlot(const QList<QRectF> ®ions);
|
||||||
|
void repaintRequestedSlot(const QRectF ®ion);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
108
src/osgqt/QWebViewImage.h
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2009 Robert Osfield
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef QWEBVIEWIMAGE
|
||||||
|
#define QWEBVIEWIMAGE
|
||||||
|
|
||||||
|
// make sure this header isn't built as par of osgQt, leaving it to applications to build
|
||||||
|
#if !defined(OSGQT_LIBRARY) && !defined(OSG_LIBRARY_STATIC)
|
||||||
|
|
||||||
|
#if QT_VERSION >= 0x050000
|
||||||
|
# include <QtWebKitWidgets>
|
||||||
|
#else
|
||||||
|
# include <QtWebKit>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#include <osgWidget/Browser>
|
||||||
|
#include "osgqt/QGraphicsViewAdapter.h"
|
||||||
|
|
||||||
|
namespace osgQt
|
||||||
|
{
|
||||||
|
|
||||||
|
class QWebViewImage : public osgWidget::BrowserImage
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
QWebViewImage()
|
||||||
|
{
|
||||||
|
// make sure we have a valid QApplication before we start creating widgets.
|
||||||
|
getOrCreateQApplication();
|
||||||
|
|
||||||
|
_webView = new QWebView;
|
||||||
|
|
||||||
|
_webPage = new QWebPage;
|
||||||
|
_webPage->settings()->setAttribute(QWebSettings::JavascriptEnabled, true);
|
||||||
|
_webPage->settings()->setAttribute(QWebSettings::PluginsEnabled, true);
|
||||||
|
|
||||||
|
_webView->setPage(_webPage);
|
||||||
|
|
||||||
|
_adapter = new QGraphicsViewAdapter(this, _webView.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void navigateTo(const std::string& url)
|
||||||
|
{
|
||||||
|
_webView->load(QUrl(url.c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
|
QWebView* getQWebView() { return _webView; }
|
||||||
|
QWebPage* getQWebPage() { return _webPage; }
|
||||||
|
QGraphicsViewAdapter* getQGraphicsViewAdapter() { return _adapter; }
|
||||||
|
|
||||||
|
void clearWriteBuffer()
|
||||||
|
{
|
||||||
|
_adapter->clearWriteBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
void render()
|
||||||
|
{
|
||||||
|
if (_adapter->requiresRendering()) _adapter->render();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool requiresUpdateCall() const { return true; }
|
||||||
|
virtual void update( osg::NodeVisitor* nv ) { render(); }
|
||||||
|
|
||||||
|
virtual bool sendFocusHint(bool focus)
|
||||||
|
{
|
||||||
|
QFocusEvent event(focus ? QEvent::FocusIn : QEvent::FocusOut, Qt::OtherFocusReason);
|
||||||
|
QCoreApplication::sendEvent(_webPage, &event);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool sendPointerEvent(int x, int y, int buttonMask)
|
||||||
|
{
|
||||||
|
return _adapter->sendPointerEvent(x,y,buttonMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool sendKeyEvent(int key, bool keyDown)
|
||||||
|
{
|
||||||
|
return QWebViewImage::_adapter->sendKeyEvent(key, keyDown);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void setFrameLastRendered(const osg::FrameStamp* frameStamp)
|
||||||
|
{
|
||||||
|
_adapter->setFrameLastRendered(frameStamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
QPointer<QGraphicsViewAdapter> _adapter;
|
||||||
|
QPointer<QWebView> _webView;
|
||||||
|
QPointer<QWebPage> _webPage;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
66
src/osgqt/QWidgetImage.cpp
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2009 Robert Osfield
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "osgqt/QWidgetImage.h"
|
||||||
|
#include <QLayout>
|
||||||
|
|
||||||
|
namespace osgQt
|
||||||
|
{
|
||||||
|
|
||||||
|
QWidgetImage::QWidgetImage( QWidget* widget )
|
||||||
|
{
|
||||||
|
// make sure we have a valid QApplication before we start creating widgets.
|
||||||
|
getOrCreateQApplication();
|
||||||
|
|
||||||
|
_widget = widget;
|
||||||
|
_adapter = new QGraphicsViewAdapter(this, _widget.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QWidgetImage::sendFocusHint(bool focus)
|
||||||
|
{
|
||||||
|
QFocusEvent event(focus ? QEvent::FocusIn : QEvent::FocusOut, Qt::OtherFocusReason);
|
||||||
|
QCoreApplication::sendEvent(_widget, &event);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QWidgetImage::clearWriteBuffer()
|
||||||
|
{
|
||||||
|
_adapter->clearWriteBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QWidgetImage::render()
|
||||||
|
{
|
||||||
|
if (_adapter->requiresRendering()) _adapter->render();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QWidgetImage::scaleImage(int s,int t,int /*r*/, GLenum /*newDataType*/)
|
||||||
|
{
|
||||||
|
_adapter->resize(s, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QWidgetImage::setFrameLastRendered(const osg::FrameStamp* frameStamp)
|
||||||
|
{
|
||||||
|
_adapter->setFrameLastRendered(frameStamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QWidgetImage::sendPointerEvent(int x, int y, int buttonMask)
|
||||||
|
{
|
||||||
|
return _adapter->sendPointerEvent(x,y,buttonMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QWidgetImage::sendKeyEvent(int key, bool keyDown)
|
||||||
|
{
|
||||||
|
return _adapter->sendKeyEvent(key, keyDown);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
60
src/osgqt/QWidgetImage.h
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2009 Robert Osfield
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef QWIDGETIMAGE
|
||||||
|
#define QWIDGETIMAGE
|
||||||
|
|
||||||
|
#include <osg/Image>
|
||||||
|
|
||||||
|
#include "osgQt/QGraphicsViewAdapter.h"
|
||||||
|
|
||||||
|
namespace osgQt
|
||||||
|
{
|
||||||
|
|
||||||
|
class QWidgetImage : public osg::Image
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
QWidgetImage( QWidget* widget=0 );
|
||||||
|
|
||||||
|
QWidget* getQWidget() { return _widget; }
|
||||||
|
QGraphicsViewAdapter* getQGraphicsViewAdapter() { return _adapter; }
|
||||||
|
|
||||||
|
virtual bool requiresUpdateCall() const { return true; }
|
||||||
|
virtual void update( osg::NodeVisitor* /*nv*/ ) { render(); }
|
||||||
|
|
||||||
|
void clearWriteBuffer();
|
||||||
|
|
||||||
|
void render();
|
||||||
|
|
||||||
|
/// Overridden scaleImage used to catch cases where the image is
|
||||||
|
/// fullscreen and the window is resized.
|
||||||
|
virtual void scaleImage(int s,int t,int r, GLenum newDataType);
|
||||||
|
|
||||||
|
virtual bool sendFocusHint(bool focus);
|
||||||
|
|
||||||
|
virtual bool sendPointerEvent(int x, int y, int buttonMask);
|
||||||
|
|
||||||
|
virtual bool sendKeyEvent(int key, bool keyDown);
|
||||||
|
|
||||||
|
virtual void setFrameLastRendered(const osg::FrameStamp* frameStamp);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
QPointer<QGraphicsViewAdapter> _adapter;
|
||||||
|
QPointer<QWidget> _widget;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
66
src/osgqt/ReaderQFont.cpp
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/* -*-c++-*- OpenSceneGraph - Copyright (C) 2009-2010 Mathias Froehlich
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
#include "osgqt/QFontImplementation.h"
|
||||||
|
|
||||||
|
#include <osgDB/FileNameUtils>
|
||||||
|
#include <osgDB/Registry>
|
||||||
|
#include <osgText/Font>
|
||||||
|
|
||||||
|
#include <QtCore/QThread>
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QtGui/QFont>
|
||||||
|
#include <QtGui/QFontDatabase>
|
||||||
|
|
||||||
|
namespace osgQFont {
|
||||||
|
|
||||||
|
class ReaderQFont : public osgDB::ReaderWriter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ReaderQFont()
|
||||||
|
{
|
||||||
|
supportsExtension("qfont", "Qt font meta loader");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const char* className() const { return "QFont Font Reader"; }
|
||||||
|
|
||||||
|
virtual ReadResult readObject(const std::string& file, const osgDB::ReaderWriter::Options* /*options*/) const
|
||||||
|
{
|
||||||
|
if (!acceptsExtension(osgDB::getLowerCaseFileExtension(file)))
|
||||||
|
return ReadResult::FILE_NOT_HANDLED;
|
||||||
|
|
||||||
|
if (!QApplication::instance())
|
||||||
|
{
|
||||||
|
OSG_WARN << "Trying to load qfont \"" << file << "\" from within a non qt application!" << std::endl;
|
||||||
|
return ReadResult::FILE_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!QFontDatabase::supportsThreadedFontRendering() && QApplication::instance()->thread() != QThread::currentThread())
|
||||||
|
{
|
||||||
|
OSG_WARN << "Trying to load qfont \"" << file << "\" from a non gui thread "
|
||||||
|
"within qt application without threaded font rendering!" << std::endl;
|
||||||
|
return ReadResult::FILE_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
QFont font;
|
||||||
|
if (!font.fromString(QString::fromStdString(osgDB::getNameLessExtension(file))))
|
||||||
|
return ReadResult::FILE_NOT_FOUND;
|
||||||
|
|
||||||
|
return new osgText::Font(new osgQt::QFontImplementation(font));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// now register with Registry to instantiate the above
|
||||||
|
// reader/writer.
|
||||||
|
REGISTER_OSGPLUGIN(qfont, ReaderQFont)
|
||||||
|
|
||||||
|
}
|
||||||
BIN
src/res/default/Command.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
src/res/default/menu_image_file.png
Normal file
|
After Width: | Height: | Size: 6.8 KiB |
BIN
src/res/default/menu_light_file.png
Normal file
|
After Width: | Height: | Size: 973 B |
BIN
src/res/default/menu_surface_file.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
src/res/default/menu_table_file.png
Normal file
|
After Width: | Height: | Size: 326 B |
BIN
src/res/default/menu_wave_file.png
Normal file
|
After Width: | Height: | Size: 662 B |
BIN
src/res/default/menu_window_setting.png
Normal file
|
After Width: | Height: | Size: 800 B |
BIN
src/res/default/polar.png
Normal file
|
After Width: | Height: | Size: 64 KiB |
BIN
src/res/dyt.aps
Normal file
BIN
src/res/models/aircraft_carrier.png
Normal file
|
After Width: | Height: | Size: 669 B |
BIN
src/res/models/chaff_interference.png
Normal file
|
After Width: | Height: | Size: 934 B |
BIN
src/res/models/missile.png
Normal file
|
After Width: | Height: | Size: 555 B |
BIN
src/res/models/radar_jamming_station.png
Normal file
|
After Width: | Height: | Size: 582 B |
BIN
src/res/models/satellite.png
Normal file
|
After Width: | Height: | Size: 1023 B |
BIN
src/res/models/warships.png
Normal file
|
After Width: | Height: | Size: 662 B |
BIN
src/res/sys_float.png
Normal file
|
After Width: | Height: | Size: 361 B |
@ -6,178 +6,85 @@
|
|||||||
#include <osg/Program>
|
#include <osg/Program>
|
||||||
#include <osg/LightSource>
|
#include <osg/LightSource>
|
||||||
#include <osgDB/ReadFile>
|
#include <osgDB/ReadFile>
|
||||||
#include <osgEarth/GLUtils>
|
#include <osgEarthUtil/EarthManipulator>
|
||||||
#include <osgEarth/EarthManipulator>
|
#include <osgGA/StateSetManipulator>
|
||||||
|
|
||||||
#include <osgShadow/ShadowedScene>
|
#include <osgShadow/ShadowedScene>
|
||||||
#include <osgShadow/ViewDependentShadowMap>
|
#include <osgShadow/ViewDependentShadowMap>
|
||||||
#include <osgViewer/ViewerEventHandlers>
|
#include <osgViewer/ViewerEventHandlers>
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "app/Application.h"
|
||||||
#include "common/SpdLogger.h"
|
#include "common/SpdLogger.h"
|
||||||
#include "common/RecourceHelper.h"
|
#include "common/RecourceHelper.h"
|
||||||
#include "scene/ScopedTimer.h"
|
#include "scene/ScopedTimer.h"
|
||||||
#include "viewer/OsgView.h"
|
#include "viewer/OsgView.h"
|
||||||
#include "viewer/OsgCameraManipulator.h"
|
#include "viewer/OsgCameraManipulator.h"
|
||||||
#include "scene/ScaleBarHandler.h"
|
#include "scene/ScaleBarHandler.h"
|
||||||
|
#include "utils/FileUtils.h"
|
||||||
#include "effects/ConeWave.h"
|
|
||||||
|
|
||||||
const osgEarth::SpatialReference* g_srs_{ nullptr };
|
const osgEarth::SpatialReference* g_srs_{ nullptr };
|
||||||
|
|
||||||
|
|
||||||
OEScene::OEScene() {
|
OEScene::OEScene() {
|
||||||
osgDB::FilePathList& pathList = osgDB::Registry::instance()->getDataFilePathList();
|
osgDB::FilePathList& pathList = osgDB::Registry::instance()->getDataFilePathList();
|
||||||
const std::string& basePath = RecourceHelper::Get().GetBasePath().toStdString();
|
const std::string& basePath = RecourceHelper::Get().GetBasePath().toStdString();
|
||||||
pathList.push_back(basePath + "/resources/earth/");
|
pathList.push_back(basePath + "/resources/earth/");
|
||||||
pathList.push_back(basePath + "/resources/textures/");
|
pathList.push_back(basePath + "/resources/textures/");
|
||||||
root_ = new osg::Group;
|
|
||||||
|
Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OEScene::AttachView(osgViewer::View* view) {
|
||||||
void OEScene::InitEventHandle(class OsgView* view) {
|
|
||||||
if (nullptr == view) {
|
|
||||||
LOG_WARN("view is nullptr");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//view->GetView()->addEventHandler(new osgEarth::Util::EarthManipulator());
|
|
||||||
|
|
||||||
view->GetView()->addEventHandler(new osgViewer::HelpHandler);
|
|
||||||
view->GetView()->addEventHandler(new osgViewer::StatsHandler);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OEScene::AttachView(OsgView* view) {
|
|
||||||
if (nullptr == view) {
|
|
||||||
LOG_WARN("view is nullptr");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
osg::Node* rootNode = view->GetView()->getSceneData();
|
|
||||||
if (nullptr != rootNode) {
|
|
||||||
int parantCount = rootNode->getNumParents();
|
|
||||||
for (int i = 0; i < parantCount; ++i) {
|
|
||||||
rootNode->getParent(i)->removeChild(rootNode);
|
|
||||||
}
|
|
||||||
root_->addChild(rootNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
view->GetView()->setSceneData(root_);
|
|
||||||
|
|
||||||
earthRootNode_ = osgDB::readNodeFile("triton.earth");
|
|
||||||
dyt_check(nullptr != earthRootNode_);
|
dyt_check(nullptr != earthRootNode_);
|
||||||
logarithmicDepthBuffer_ = std::make_unique<osgEarth::Util::LogarithmicDepthBuffer>();
|
skyDome_ = osgEarth::Util::SkyNode::create(earthMapNode_);
|
||||||
|
|
||||||
earthMapNode_ = osgEarth::MapNode::get(earthRootNode_);
|
|
||||||
dyt_check(nullptr != earthMapNode_);
|
|
||||||
LOG_INFO("earth map node get success: {}", earthMapNode_.valid());
|
|
||||||
g_srs_ = earthMapNode_->getMapSRS();
|
|
||||||
|
|
||||||
entityRoot_ = new osg::Group;
|
|
||||||
root_->addChild(entityRoot_);
|
|
||||||
|
|
||||||
skyDome_ = osgEarth::SkyNode::create();
|
|
||||||
if (!earthMapNode_) {
|
if (!earthMapNode_) {
|
||||||
LOG_WARN("eart map node is nullptr");
|
LOG_WARN("eart map node is nullptr");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
root_->addChild(skyDome_);
|
|
||||||
skyDome_->addChild(earthMapNode_);
|
|
||||||
skyDome_->attach(view->GetView());
|
|
||||||
|
|
||||||
skyDome_->setAtmosphereVisible(true);
|
dyt_check(nullptr != earthManipulator_);
|
||||||
skyDome_->setSunVisible(true);
|
view->setCameraManipulator(earthManipulator_);
|
||||||
skyDome_->setMoonVisible(true);
|
skyDome_->attach(view);
|
||||||
skyDome_->setStarsVisible(true);
|
skyDome_->getSunLight()->setAmbient(osg::Vec4(0.5,0.5,0.5,1.0));
|
||||||
|
addChild(skyDome_);
|
||||||
|
|
||||||
skyDome_->setDateTime(osgEarth::DateTime(2024, 12, 24, 3));
|
skyDome_->setDateTime(osgEarth::DateTime(2024, 12, 24, 3));
|
||||||
skyDome_->setSimulationTimeTracksDateTime(true);
|
|
||||||
|
|
||||||
logarithmicDepthBuffer_->install(view->GetView()->getCamera());
|
view->setSceneData(this);
|
||||||
|
curentView_ = view;
|
||||||
ConeWave* coneWave = new ConeWave;
|
|
||||||
|
|
||||||
osgEarth::GeoTransform *geo = new osgEarth::GeoTransform;
|
|
||||||
entityRoot_->addChild(geo);
|
|
||||||
|
|
||||||
osgEarth::GeoPoint pos(g_srs_, 120.000000,25.000000,600.000000);
|
|
||||||
geo->setPosition(pos);
|
|
||||||
coneWave->createWaveBeamCone(geo, 45, 6000, osg::Vec4(1.0, 0.0, 0.0, 0.3),
|
|
||||||
osg::Vec4(1.0, 1.0, 0.0, 0.3), 30);
|
|
||||||
osg::MatrixTransform* mt =coneWave->getWaveBeamCone();
|
|
||||||
geo->addChild(mt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OEScene::DetachView(OsgView* view) {
|
void OEScene::DetachView(osgViewer::View* view) {
|
||||||
if (nullptr != earthRootNode_) {
|
view->setSceneData(nullptr);
|
||||||
std::vector<osg::Group*> parents = earthRootNode_->getParents();
|
|
||||||
for (const auto& parent : parents) {
|
|
||||||
parent->removeChild(earthRootNode_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
logarithmicDepthBuffer_->uninstall(view->GetView()->getCamera());
|
|
||||||
view->GetView()->setSceneData(nullptr);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define USE_CUSTOM_SHADER
|
bool OEScene::AddToScene(osg::Node* node) const {
|
||||||
|
|
||||||
osg::ref_ptr<osg::TextureCubeMap> OEScene::LoadCubeMapTextures(const std::string& dir) {
|
|
||||||
enum {
|
|
||||||
POS_X, NEG_X, POS_Y, NEG_Y, POS_Z, NEG_Z
|
|
||||||
};
|
|
||||||
|
|
||||||
std::string filenames[6];
|
|
||||||
|
|
||||||
std::string basePath = RecourceHelper::Get().GetBasePath().toStdString();
|
|
||||||
|
|
||||||
filenames[POS_X] = basePath + "/resources/textures/" + dir + "/east.png";
|
|
||||||
filenames[NEG_X] = basePath + "/resources/textures/" + dir + "/west.png";
|
|
||||||
filenames[POS_Z] = basePath + "/resources/textures/" + dir + "/north.png";
|
|
||||||
filenames[NEG_Z] = basePath + "/resources/textures/" + dir + "/south.png";
|
|
||||||
filenames[POS_Y] = basePath + "/resources/textures/" + dir + "/down.png";
|
|
||||||
filenames[NEG_Y] = basePath + "/resources/textures/" + dir + "/up.png";
|
|
||||||
|
|
||||||
osg::ref_ptr<osg::TextureCubeMap> cubeMap = new osg::TextureCubeMap;
|
|
||||||
cubeMap->setInternalFormat(GL_RGBA);
|
|
||||||
|
|
||||||
cubeMap->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR);
|
|
||||||
cubeMap->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
|
|
||||||
cubeMap->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
|
|
||||||
cubeMap->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
|
|
||||||
|
|
||||||
cubeMap->setImage(osg::TextureCubeMap::NEGATIVE_X, osgDB::readImageFile(filenames[NEG_X]));
|
|
||||||
cubeMap->setImage(osg::TextureCubeMap::POSITIVE_X, osgDB::readImageFile(filenames[POS_X]));
|
|
||||||
cubeMap->setImage(osg::TextureCubeMap::NEGATIVE_Y, osgDB::readImageFile(filenames[NEG_Y]));
|
|
||||||
cubeMap->setImage(osg::TextureCubeMap::POSITIVE_Y, osgDB::readImageFile(filenames[POS_Y]));
|
|
||||||
cubeMap->setImage(osg::TextureCubeMap::NEGATIVE_Z, osgDB::readImageFile(filenames[NEG_Z]));
|
|
||||||
cubeMap->setImage(osg::TextureCubeMap::POSITIVE_Z, osgDB::readImageFile(filenames[POS_Z]));
|
|
||||||
|
|
||||||
return cubeMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
osg::Group* OEScene::GetData() {
|
|
||||||
return root_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void OEScene::AddToScene(osg::Node* node) {
|
|
||||||
dyt_check(nullptr != entityRoot_);
|
dyt_check(nullptr != entityRoot_);
|
||||||
entityRoot_->addChild(node);
|
return entityRoot_->addChild(node);
|
||||||
/* osgOcean::OceanScene* oceanScene = GetOceanScene();
|
}
|
||||||
if (nullptr == oceanScene) {
|
|
||||||
LOG_WARN("oceanScene is nullptr");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
node->setNodeMask(oceanScene->getNormalSceneMask() |
|
void OEScene::SetHomeViewpoint(const osgEarth::Viewpoint& viewpoint, double duration_s) {
|
||||||
oceanScene->getReflectedSceneMask() |
|
dyt_check(nullptr != earthManipulator_);
|
||||||
oceanScene->getRefractedSceneMask() |
|
|
||||||
CAST_SHADOW | RECEIVE_SHADOW);
|
earthManipulator_->setViewpoint(viewpoint, duration_s);
|
||||||
oceanScene->addChild(node);*/
|
if (homeViewpointSet_) {
|
||||||
/* osg::Group* root = GetScene();
|
LOG_INFO("Home viewpoint already set, skipping...");
|
||||||
root->addChild(node);*/
|
return;
|
||||||
|
}
|
||||||
|
earthManipulator_->setHomeViewpoint(viewpoint, duration_s);
|
||||||
|
|
||||||
|
homeViewpointSet_ = true;
|
||||||
|
LOG_INFO("Home viewpoint set successfully");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OEScene::TrackEntity(osg::Node* entity, bool track) const {
|
||||||
|
dyt_check(nullptr != earthManipulator_);
|
||||||
|
if (track) {
|
||||||
|
earthManipulator_->setTetherNode(entity, 5.0);
|
||||||
|
} else {
|
||||||
|
earthManipulator_->clearViewpoint();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
OESceneUI* OEScene::GetOrCreateSceneUI() {
|
OESceneUI* OEScene::GetOrCreateSceneUI() {
|
||||||
@ -189,3 +96,99 @@ OESceneUI* OEScene::GetOrCreateSceneUI() {
|
|||||||
sceneUI_ = new OESceneUI(this);
|
sceneUI_ = new OESceneUI(this);
|
||||||
return sceneUI_.get();
|
return sceneUI_.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
osg::Viewport* OEScene::GetViewport() const {
|
||||||
|
dyt_check(nullptr != curentView_);
|
||||||
|
|
||||||
|
return curentView_->getCamera()->getViewport();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OEScene::ScreenToWorldCoordinate(int x, int y, osg::Vec3d* output) const {
|
||||||
|
if (nullptr == output) {
|
||||||
|
LOG_WARN("OEScene::ScreenToWorldCoordinate - worldPoint is null");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
osg::Camera* camera = curentView_->getCamera();
|
||||||
|
if (!camera) {
|
||||||
|
LOG_WARN("OEScene::ScreenToWorldCoordinate - camera is null");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
osg::ref_ptr<osgUtil::LineSegmentIntersector> intersector =
|
||||||
|
new osgUtil::LineSegmentIntersector(osgUtil::Intersector::WINDOW, x, y);
|
||||||
|
|
||||||
|
osgUtil::IntersectionVisitor iv(intersector.get());
|
||||||
|
camera->accept(iv);
|
||||||
|
|
||||||
|
if (intersector->containsIntersections()) {
|
||||||
|
osgUtil::LineSegmentIntersector::Intersections& intersections = intersector->getIntersections();
|
||||||
|
osgUtil::LineSegmentIntersector::Intersection intersection = *intersections.begin();
|
||||||
|
|
||||||
|
osg::Vec3d worldPoint = intersection.getWorldIntersectPoint();
|
||||||
|
|
||||||
|
Vec3ToLocation(worldPoint, output);
|
||||||
|
|
||||||
|
LOG_INFO("OsgWidget::ScreenToWorldCoordinate - Screen({}, {}) -> World({:.6f}, {:.6f}, {:.2f})",
|
||||||
|
x, y, output->x(), output->y(), output->z());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_WARN("OsgWidget::ScreenToWorldCoordinate - No intersection found for screen coordinates ({}, {})", x, y);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OEScene::Vec3ToLocation(const osg::Vec3& input, osg::Vec3d* output) const {
|
||||||
|
if (nullptr == output) {
|
||||||
|
LOG_WARN("OEScene::vec3ToLocation - output is null");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const osgEarth::SpatialReference* srs = OEScene::GetSrs();
|
||||||
|
if (!srs) {
|
||||||
|
LOG_WARN("OEScene::vec3ToLocation - spatial reference system is null");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
osgEarth::GeoPoint geoPoint;
|
||||||
|
geoPoint.fromWorld(srs, input);
|
||||||
|
|
||||||
|
const osgEarth::SpatialReference* wgs84 = osgEarth::SpatialReference::get("wgs84");
|
||||||
|
if (wgs84) {
|
||||||
|
geoPoint = geoPoint.transform(wgs84);
|
||||||
|
}
|
||||||
|
|
||||||
|
output->set(geoPoint.x(), geoPoint.y(),geoPoint.z());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const osgEarth::SpatialReference* OEScene::GetSrs() {
|
||||||
|
dyt_check(nullptr != g_srs_);
|
||||||
|
return g_srs_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OEScene::Init() {
|
||||||
|
QString earthFile = QString("%1/earth/triton.earth").arg(Application::GetBinPath());
|
||||||
|
if (!FileUtils::IsExist(earthFile)) {
|
||||||
|
LOG_ERROR("earth file not found: {}", earthFile.toStdString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string earthPath(earthFile.toLocal8Bit().constData());
|
||||||
|
LOG_INFO("Loading earth file from: {}", earthPath);
|
||||||
|
// earthRootNode_ = osgDB::readNodeFile("triton.earth");
|
||||||
|
earthRootNode_ = osgDB::readNodeFile(earthPath);
|
||||||
|
dyt_check(nullptr != earthRootNode_);
|
||||||
|
addChild(earthRootNode_);
|
||||||
|
|
||||||
|
earthMapNode_ = osgEarth::MapNode::get(earthRootNode_);
|
||||||
|
dyt_check(nullptr != earthMapNode_);
|
||||||
|
LOG_INFO("earth map node get success: {}", earthMapNode_.valid());
|
||||||
|
g_srs_ = earthMapNode_->getMapSRS();
|
||||||
|
|
||||||
|
earthManipulator_ = new osgEarth::Util::EarthManipulator();
|
||||||
|
earthManipulator_->getSettings()->setMinMaxPitch(-90.0, -10.0);
|
||||||
|
|
||||||
|
|
||||||
|
entityRoot_ = new osg::Group;
|
||||||
|
addChild(entityRoot_);
|
||||||
|
}
|
||||||
|
|||||||
@ -1,56 +1,55 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <osg/Switch>
|
#include <osgEarth/MapNode>
|
||||||
#include <osg/TextureCubeMap>
|
#include <osgEarthUtil/Sky>
|
||||||
|
#include <osgEarth/Viewpoint>
|
||||||
#include <osgText/Text>
|
|
||||||
#include <osgEarth/ModelNode>
|
|
||||||
#include <osgEarth/Sky>
|
|
||||||
#include <osgEarth/LogarithmicDepthBuffer>
|
|
||||||
|
|
||||||
//#include "scene/SkyDome.h"
|
|
||||||
|
|
||||||
#include "common/SpdLogger.h"
|
#include "common/SpdLogger.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "scene/ui/OESceneUI.h"
|
#include "scene/ui/OESceneUI.h"
|
||||||
|
|
||||||
class OsgView;
|
namespace osgEarth {
|
||||||
|
namespace Util {
|
||||||
|
class EarthManipulator;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class OEScene : public osg::Referenced {
|
class OEScene : public osg::Group {
|
||||||
public:
|
public:
|
||||||
OEScene();
|
OEScene();
|
||||||
void InitEventHandle(OsgView* view);
|
void AttachView(osgViewer::View* view);
|
||||||
void AttachView(OsgView* view);
|
void DetachView(osgViewer::View* view);
|
||||||
void DetachView(OsgView* view);
|
|
||||||
|
|
||||||
osg::ref_ptr<osg::TextureCubeMap> LoadCubeMapTextures(const std::string& dir);
|
|
||||||
|
|
||||||
inline osg::Vec4f IntColor(unsigned r, unsigned g, unsigned b, unsigned a = 255) {
|
|
||||||
float div = 1.f / 255.f;
|
|
||||||
return osg::Vec4f(div * (float)r, div * (float)g, div * float(b), div * (float)a);
|
|
||||||
}
|
|
||||||
|
|
||||||
osg::Group* GetData();
|
|
||||||
|
|
||||||
inline osg::Group* GetScene(void) {
|
|
||||||
return root_.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
bool AddToScene(osg::Node* node) const;
|
||||||
|
void SetHomeViewpoint(const osgEarth::Viewpoint& viewpoint, double duration_s);
|
||||||
|
bool TrackEntity(osg::Node* entity, bool track) const;
|
||||||
|
|
||||||
osgEarth::MapNode* GetMapNode(void) const {
|
osgEarth::MapNode* GetMapNode(void) const {
|
||||||
dyt_check(earthMapNode_.valid());
|
dyt_check(earthMapNode_.valid());
|
||||||
return earthMapNode_;
|
return earthMapNode_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddToScene(osg::Node* node);
|
|
||||||
|
|
||||||
OESceneUI* GetOrCreateSceneUI();
|
OESceneUI* GetOrCreateSceneUI();
|
||||||
|
osgEarth::Util::EarthManipulator* GetManipulater() const {
|
||||||
|
return earthManipulator_.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
osg::Viewport* GetViewport() const;
|
||||||
|
bool ScreenToWorldCoordinate(int x, int y, osg::Vec3d* output) const;
|
||||||
|
bool Vec3ToLocation(const osg::Vec3& input, osg::Vec3d* output) const;
|
||||||
|
|
||||||
|
static const osgEarth::SpatialReference* GetSrs();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void Init();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
osg::ref_ptr<osg::Group> root_;
|
|
||||||
osg::ref_ptr<osg::Node> earthRootNode_;
|
osg::ref_ptr<osg::Node> earthRootNode_;
|
||||||
|
osg::ref_ptr<osgEarth::Util::EarthManipulator> earthManipulator_;
|
||||||
osg::ref_ptr<osgEarth::MapNode> earthMapNode_;
|
osg::ref_ptr<osgEarth::MapNode> earthMapNode_;
|
||||||
osg::ref_ptr<osg::Group> entityRoot_;
|
osg::ref_ptr<osg::Group> entityRoot_;
|
||||||
osg::ref_ptr<osgEarth::SkyNode> skyDome_;
|
osg::ref_ptr<osgEarth::Util::SkyNode> skyDome_;
|
||||||
std::unique_ptr<osgEarth::Util::LogarithmicDepthBuffer> logarithmicDepthBuffer_;
|
|
||||||
osg::ref_ptr<OESceneUI> sceneUI_;
|
osg::ref_ptr<OESceneUI> sceneUI_;
|
||||||
|
osgViewer::View* curentView_ {nullptr};
|
||||||
|
bool homeViewpointSet_ {false};
|
||||||
};
|
};
|
||||||
|
|||||||
@ -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
|
|
||||||
@ -1,153 +1,73 @@
|
|||||||
#include "CompositeHandle.h"
|
#include "CompositeHandle.h"
|
||||||
|
#include <osgEarthUtil/EarthManipulator>
|
||||||
#include "CompositeWidgetManager.h"
|
#include "CompositeWidgetManager.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
CompositeHandle::CompositeHandle(CompositeWidgetManager* cw) :_cw(cw),
|
#define M_PI 3.14159265358979323846 /* mathematical constant pi */
|
||||||
_operate(cw->GetcanvasO()),
|
|
||||||
_N(cw->GetcanvasN()),
|
///Radian to degree conversion factor
|
||||||
_light(cw->GetcanvasFX()),
|
static const double RAD2DEG = 180.0 / M_PI;
|
||||||
_background(cw->GetcanvasBackGround()),
|
///Degree to radian conversion factor
|
||||||
_num(0),
|
static const double DEG2RAD = M_PI / 180.0;
|
||||||
_move(false)
|
|
||||||
{
|
inline double angFix360(double in) {
|
||||||
|
in -= 45.0;
|
||||||
|
if ((in < 0.0) || (in >= 360.0)) {
|
||||||
|
in = fmod(in, 360.0);
|
||||||
|
|
||||||
|
if (in < 0.0)
|
||||||
|
in += 360.0;
|
||||||
|
}
|
||||||
|
return in;
|
||||||
}
|
}
|
||||||
|
|
||||||
CompositeHandle::~CompositeHandle(void)
|
inline bool areEqual(double a, double b, double t = 1.0e-6) {
|
||||||
{
|
return fabs(a - b) < t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CompositeHandle::CompositeHandle(CompositeWidgetManager* cw)
|
||||||
|
: _cw(cw),
|
||||||
|
_operate(cw->GetcanvasO()),
|
||||||
|
_N(cw->GetcanvasN()),
|
||||||
|
_light(cw->GetcanvasFX()),
|
||||||
|
_background(cw->GetcanvasBackGround()),
|
||||||
|
_num(0),
|
||||||
|
_move(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
bool CompositeHandle::handle(const osgGA::GUIEventAdapter&ea, osgGA::GUIActionAdapter& aa)
|
bool CompositeHandle::handle(const osgGA::GUIEventAdapter&ea, osgGA::GUIActionAdapter& aa)
|
||||||
{
|
{
|
||||||
if (_num != 0)
|
if (ea.getEventType() == osgGA::GUIEventAdapter::FRAME) {
|
||||||
{
|
constexpr double TWO_DECIMAL_PLACES = 1e-02;
|
||||||
_cw->_local_y = sin(_angle);
|
double heading = 0.0;
|
||||||
_cw->_local_x = cos(_angle);
|
osgViewer::View* activeView = static_cast<osgViewer::View*>(aa.asView());
|
||||||
|
const osgEarth::Util::EarthManipulator* manip = dynamic_cast<const osgEarth::Util::EarthManipulator*>(activeView->getCameraManipulator());
|
||||||
_angle = _angle + _num;
|
if (manip != NULL)
|
||||||
_cw->SendPosition();
|
|
||||||
|
|
||||||
if ((_num >= 0 && _angle >= osg::PI_2) || (_num < 0 && _angle < osg::PI_2))
|
|
||||||
{
|
{
|
||||||
_cw->_local_y = sin(osg::PI_2);
|
manip->getCompositeEulerAngles(&heading);
|
||||||
_cw->_local_x = cos(osg::PI_2);
|
// Convert to degrees
|
||||||
|
heading = angFix360(heading * RAD2DEG);
|
||||||
_cw->SendPosition();
|
|
||||||
|
|
||||||
_num = 0;
|
|
||||||
_cw->_autoHome = false;
|
|
||||||
_cw->_N = false;
|
|
||||||
}
|
}
|
||||||
return false;
|
else
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
switch (ea.getEventType())
|
|
||||||
{
|
{
|
||||||
case osgGA::GUIEventAdapter::DRAG:
|
// Fall back to the viewpoint's heading
|
||||||
{
|
heading = angFix360(manip->getViewpoint().heading()->as(osgEarth::Units::DEGREES));
|
||||||
if (_cw->_state == CompositeWidgetManager::MOUSE_DRAG)
|
|
||||||
{
|
|
||||||
_cw->SendPosition();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case osgGA::GUIEventAdapter::PUSH:
|
|
||||||
{
|
|
||||||
_cw->_N = false;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case osgGA::GUIEventAdapter::DOUBLECLICK:
|
|
||||||
{
|
|
||||||
if (_cw->_N == true)
|
|
||||||
{
|
|
||||||
_num = (45 - _N->getRotate())*osg::PI / (100 * 180);
|
|
||||||
|
|
||||||
if (_num != 0)
|
|
||||||
{
|
|
||||||
_angle = (_N->getRotate() - 45)*osg::PI / 180 + osg::PI_2;
|
|
||||||
|
|
||||||
_cw->_autoHome = true;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (ea.getX() >= _cw->_center_x - 42 &&
|
|
||||||
ea.getX() < _cw->_center_x + 42 &&
|
|
||||||
ea.getY() > _cw->_center_y - 42 &&
|
|
||||||
ea.getY() < _cw->_center_y + 42)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (_cw->_state)
|
// make sure that anything equivalent to 0.00 is displayed as 0.00
|
||||||
{
|
if (areEqual(heading, 0.0, TWO_DECIMAL_PLACES) || areEqual(heading, 360.0, TWO_DECIMAL_PLACES)) {
|
||||||
case CompositeWidgetManager::MOUSE_PUSH:
|
heading = 0.0;
|
||||||
{
|
}
|
||||||
if (_cw->_N != true || _cw->_autoHome == false)
|
|
||||||
{
|
|
||||||
_cw->SendPosition();
|
|
||||||
|
|
||||||
if (_cw->_local_y < 0)
|
if (!areEqual(_N->getRotate(), -heading, TWO_DECIMAL_PLACES))
|
||||||
{
|
|
||||||
if (_cw->_local_x > 0)
|
|
||||||
{
|
|
||||||
_light->setRotate(45 - (180 - 90 * asinf(_cw->_local_x / sqrtf(_cw->_local_x*_cw->_local_x + _cw->_local_y*_cw->_local_y)) / osg::PI_2));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_light->setRotate(45 - (-180 - 90 * asinf(_cw->_local_x / sqrtf(_cw->_local_x*_cw->_local_x + _cw->_local_y*_cw->_local_y)) / osg::PI_2));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_light->setRotate(45 - 90 * asinf(_cw->_local_x / sqrtf(_cw->_local_x*_cw->_local_x + _cw->_local_y*_cw->_local_y)) / osg::PI_2);
|
|
||||||
}
|
|
||||||
|
|
||||||
_light->getByName("light")->setColor(1, 1, 1, 0.5);
|
|
||||||
_light->resize();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CompositeWidgetManager::MOUSE_RELEASE:
|
|
||||||
{
|
{
|
||||||
_cw->_state = CompositeWidgetManager::DEFAULT;
|
_N->setRotate(-heading);
|
||||||
|
_N->update();
|
||||||
_light->getByName("light")->setColor(1, 1, 1, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CompositeWidgetManager::MOUSE_DRAG:
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
if (ea.getX() > _cw->_center_x - 50 &&
|
|
||||||
ea.getY() > _cw->_center_y - 200)
|
|
||||||
{
|
|
||||||
if (_cw->_center == 1)
|
|
||||||
{
|
|
||||||
_operate->getByName("center")->setColor(1, 1, 1, 1);
|
|
||||||
}
|
|
||||||
_background->getByName("backGround4")->setColor(1, 1, 1, 1);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (_cw->_center == 1)
|
|
||||||
{
|
|
||||||
_operate->getByName("center")->setColor(1, 1, 1, 0.1);
|
|
||||||
}
|
|
||||||
_background->getByName("backGround4")->setColor(1, 1, 1, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// compass_->update_();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -14,9 +14,9 @@ class CompositeHandle :public osgGA::GUIEventHandler
|
|||||||
public:
|
public:
|
||||||
CompositeHandle(CompositeWidgetManager* cw);
|
CompositeHandle(CompositeWidgetManager* cw);
|
||||||
|
|
||||||
~CompositeHandle(void);
|
~CompositeHandle(void) override = default;
|
||||||
|
|
||||||
virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter&);
|
bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter&) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
osgWidget::Canvas* _operate;
|
osgWidget::Canvas* _operate;
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
#include "CompositeWidgetManager.h"
|
#include "CompositeWidgetManager.h"
|
||||||
|
|
||||||
|
#include "BackGroundWidget.h"
|
||||||
#include "common/RecourceHelper.h"
|
#include "common/RecourceHelper.h"
|
||||||
#include "viewer/OsgViewUI.h"
|
#include "viewer/OsgViewUI.h"
|
||||||
|
|
||||||
@ -77,23 +78,7 @@ CompositeWidgetManager::CompositeWidgetManager(void)
|
|||||||
_canvasFX->getBackground()->setColor(0, 0, 0, 0);
|
_canvasFX->getBackground()->setColor(0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
CompositeWidgetManager::~CompositeWidgetManager(void)
|
CompositeWidgetManager::~CompositeWidgetManager(void) {
|
||||||
{
|
|
||||||
delete _canvasN;
|
|
||||||
delete _canvasO;
|
|
||||||
delete _canvasBackGround;
|
|
||||||
delete _canvasFX;
|
|
||||||
|
|
||||||
delete _bgLayer1;
|
|
||||||
delete _bgLayer2;
|
|
||||||
delete _bgLayer3;
|
|
||||||
delete _bgLayer4;
|
|
||||||
delete _bgShadow;
|
|
||||||
|
|
||||||
delete _widgetCenter;
|
|
||||||
delete _widgetN;
|
|
||||||
|
|
||||||
delete _widgetFX;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompositeWidgetManager::ResetCanvasPosition(double x, double y)
|
void CompositeWidgetManager::ResetCanvasPosition(double x, double y)
|
||||||
@ -114,7 +99,7 @@ void CompositeWidgetManager::ResetCanvasPosition(double x, double y)
|
|||||||
|
|
||||||
void CompositeWidgetManager::SendPosition()
|
void CompositeWidgetManager::SendPosition()
|
||||||
{
|
{
|
||||||
_mouseDirection = osg::Vec2(_local_x, _local_y);
|
_mouseDirection = osg::Vec2(static_cast<float>(_local_x), static_cast<float>(_local_y));
|
||||||
if (_center == 0 && _state != CompositeWidgetManager::MOUSE_DRAG && _autoHome != true)
|
if (_center == 0 && _state != CompositeWidgetManager::MOUSE_DRAG && _autoHome != true)
|
||||||
{
|
{
|
||||||
QVariantList varList;
|
QVariantList varList;
|
||||||
@ -127,13 +112,14 @@ void CompositeWidgetManager::SendPosition()
|
|||||||
QVariantList varList;
|
QVariantList varList;
|
||||||
varList.push_back(QVariant(_mouseDirection.x()));
|
varList.push_back(QVariant(_mouseDirection.x()));
|
||||||
varList.push_back(QVariant(_mouseDirection.y()));
|
varList.push_back(QVariant(_mouseDirection.y()));
|
||||||
|
|
||||||
//emit signalHeading(QVariant(varList));
|
//emit signalHeading(QVariant(varList));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
osg::Vec2 pos = _mouseDirection;
|
osg::Vec2 pos = _mouseDirection;
|
||||||
pos[0] = pos.x()* 0.2;
|
pos[0] = pos.x()* 0.2f;
|
||||||
pos[1] = pos.y()* 0.1;
|
pos[1] = pos.y()* 0.1f;
|
||||||
|
|
||||||
QVariantList varList;
|
QVariantList varList;
|
||||||
varList.push_back(QVariant(pos.x()));
|
varList.push_back(QVariant(pos.x()));
|
||||||
@ -142,8 +128,7 @@ void CompositeWidgetManager::SendPosition()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompositeWidgetManager::SetHeading(double angle)
|
void CompositeWidgetManager::SetHeading(double angle) {
|
||||||
{
|
|
||||||
_canvasN->setRotate(angle + 45);
|
_canvasN->setRotate(angle + 45);
|
||||||
_canvasN->update();
|
_canvasN->update();
|
||||||
}
|
}
|
||||||
@ -156,6 +141,20 @@ void CompositeWidgetManager::AttachViewUI(OsgViewUI* ui) {
|
|||||||
ui->addChild(_canvasBackGround);
|
ui->addChild(_canvasBackGround);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CompositeWidgetManager::AttachViewUI(osgWidget::WindowManager* ui) {
|
||||||
|
ui->addChild(_canvasO);
|
||||||
|
ui->addChild(_canvasN);
|
||||||
|
ui->addChild(_canvasFX);
|
||||||
|
ui->addChild(_canvasBackGround);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompositeWidgetManager::DetachViewUI(OsgViewUI* ui) {
|
||||||
|
ui->removeChild(_canvasO);
|
||||||
|
ui->removeChild(_canvasN);
|
||||||
|
ui->removeChild(_canvasFX);
|
||||||
|
ui->removeChild(_canvasBackGround);
|
||||||
|
}
|
||||||
|
|
||||||
//void CompositeWidgetManager::slotHeading(double angle)
|
//void CompositeWidgetManager::slotHeading(double angle)
|
||||||
//{
|
//{
|
||||||
// SetHeading(angle);
|
// SetHeading(angle);
|
||||||
|
|||||||
@ -1,13 +1,9 @@
|
|||||||
#ifndef CompositeWidgetManager_h__
|
#ifndef CompositeWidgetManager_h__
|
||||||
#define CompositeWidgetManager_h__
|
#define CompositeWidgetManager_h__
|
||||||
|
|
||||||
#include "BackGroundWidget.h"
|
|
||||||
#include "CompositeHandle.h"
|
|
||||||
#include "CompositeWidget.h"
|
#include "CompositeWidget.h"
|
||||||
#include "ZoomWidget.h"
|
#include "ZoomWidget.h"
|
||||||
#include "ZoomHandle.h"
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
|
|
||||||
|
|
||||||
@ -35,6 +31,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AttachViewUI(class OsgViewUI* ui);
|
void AttachViewUI(class OsgViewUI* ui);
|
||||||
|
void AttachViewUI(osgWidget::WindowManager* ui);
|
||||||
|
void DetachViewUI(class OsgViewUI* ui);
|
||||||
|
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
@ -47,23 +45,22 @@ public slots:
|
|||||||
void slotHeading(double angle);
|
void slotHeading(double angle);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
osgWidget::Canvas* _canvasN;
|
osg::ref_ptr<osgWidget::Canvas> _canvasN;
|
||||||
osgWidget::Canvas* _canvasO;
|
osg::ref_ptr<osgWidget::Canvas> _canvasO;
|
||||||
osgWidget::Canvas* _canvasBackGround;
|
osg::ref_ptr<osgWidget::Canvas> _canvasBackGround;
|
||||||
osgWidget::Canvas* _canvasFX;
|
osg::ref_ptr<osgWidget::Canvas> _canvasFX;
|
||||||
|
|
||||||
CompositeWidget* _bgLayer1;
|
osg::ref_ptr<CompositeWidget> _bgLayer1;
|
||||||
osgWidget::Widget* _bgLayer2;
|
osg::ref_ptr<osgWidget::Widget> _bgLayer2;
|
||||||
osgWidget::Widget* _bgLayer3;
|
osg::ref_ptr<osgWidget::Widget> _bgLayer3;
|
||||||
osgWidget::Widget* _bgLayer4;
|
osg::ref_ptr<osgWidget::Widget> _bgLayer4;
|
||||||
osgWidget::Widget* _bgShadow;
|
osg::ref_ptr<osgWidget::Widget> _bgShadow;
|
||||||
|
|
||||||
CompositeWidget* _widgetCenter;
|
osg::ref_ptr<CompositeWidget> _widgetCenter;
|
||||||
|
osg::ref_ptr<CompositeWidget> _widgetN;
|
||||||
|
|
||||||
CompositeWidget* _widgetN;
|
osg::ref_ptr<osgWidget::Widget> _widgetFX;
|
||||||
|
osg::ref_ptr<osgWidget::Widget> _widgetFXBackground;
|
||||||
osgWidget::Widget* _widgetFX;
|
|
||||||
osgWidget::Widget* _widgetFXBackground;
|
|
||||||
|
|
||||||
osg::Vec2 _mouseDirection;
|
osg::Vec2 _mouseDirection;
|
||||||
|
|
||||||
|
|||||||
@ -18,6 +18,11 @@ OESceneUI::OESceneUI(OEScene* oeScene)
|
|||||||
|
|
||||||
OESceneUI::~OESceneUI(void) {
|
OESceneUI::~OESceneUI(void) {
|
||||||
LOG_INFO("dctor self={}", spdlog::fmt_lib::ptr(this));
|
LOG_INFO("dctor self={}", spdlog::fmt_lib::ptr(this));
|
||||||
|
/* if (compositeWidgetManager_) {
|
||||||
|
compositeWidgetManager_->DetachViewUI();
|
||||||
|
delete compositeWidgetManager_;
|
||||||
|
compositeWidgetManager_ = nullptr;
|
||||||
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void OESceneUI::InitUI(OsgViewUI* ui) {
|
void OESceneUI::InitUI(OsgViewUI* ui) {
|
||||||
@ -27,31 +32,45 @@ void OESceneUI::InitUI(OsgViewUI* ui) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
compositeWidgetManager_ = new CompositeWidgetManager();
|
compositeWidgetManager_ = new CompositeWidgetManager();
|
||||||
compositeWidgetManager_->AttachViewUI(ui);
|
compositeWidgetManager_->AttachViewUI(ui);
|
||||||
zoomManager_ = new ZoomManager();
|
//zoomManager_ = new ZoomManager(oeScene_);
|
||||||
zoomManager_->AttachViewUI(ui);
|
//zoomManager_->AttachViewUI(ui);
|
||||||
|
|
||||||
queryElevationWidget_ = new QueryElevationWidget(oeScene_);
|
queryElevationWidget_ = new QueryElevationWidget(oeScene_);
|
||||||
queryElevationWidget_->AttachViewUI(ui);
|
queryElevationWidget_->AttachViewUI(ui);
|
||||||
|
|
||||||
ui->getView()->addEventHandler(new ZoomHandle(zoomManager_, compositeWidgetManager_));
|
//ui->getView()->addEventHandler(new ZoomHandle(zoomManager_, compositeWidgetManager_));
|
||||||
ui->getView()->addEventHandler(new CompositeHandle(compositeWidgetManager_));
|
ui->getView()->addEventHandler(new CompositeHandle(compositeWidgetManager_));
|
||||||
|
|
||||||
isInit_ = true;
|
isInit_ = true;
|
||||||
LOG_INFO("exit");
|
LOG_INFO("exit");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OESceneUI::UninitUI(OsgViewUI* ui) {
|
||||||
|
LOG_INFO("enter");
|
||||||
|
if (!isInit_) {
|
||||||
|
LOG_INFO("not init");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (compositeWidgetManager_) {
|
||||||
|
compositeWidgetManager_->DetachViewUI(ui);
|
||||||
|
compositeWidgetManager_ = nullptr;
|
||||||
|
}
|
||||||
|
if (queryElevationWidget_) {
|
||||||
|
queryElevationWidget_->DetachViewUI(ui);
|
||||||
|
queryElevationWidget_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
isInit_ = false;
|
||||||
|
LOG_INFO("exit");
|
||||||
|
}
|
||||||
|
|
||||||
void OESceneUI::OnResize(double width, double height) {
|
void OESceneUI::OnResize(double width, double height) {
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
dyt_check(compositeWidgetManager_);
|
dyt_check(compositeWidgetManager_);
|
||||||
dyt_check(zoomManager_);
|
//dyt_check(zoomManager_);
|
||||||
|
|
||||||
compositeWidgetManager_->ResetCanvasPosition(width, height);
|
compositeWidgetManager_->ResetCanvasPosition(width, height);
|
||||||
zoomManager_->ResetCanvasPosition(width, height);
|
//zoomManager_->ResetCanvasPosition(width, height);
|
||||||
queryElevationWidget_->ResetCanvasPosition(width, height);
|
queryElevationWidget_->ResetCanvasPosition(width, height);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,12 +16,13 @@ public:
|
|||||||
~OESceneUI(void) override;
|
~OESceneUI(void) override;
|
||||||
|
|
||||||
void InitUI(OsgViewUI* ui) override;
|
void InitUI(OsgViewUI* ui) override;
|
||||||
|
void UninitUI(OsgViewUI* ui) override;
|
||||||
void OnResize(double width, double height) override;
|
void OnResize(double width, double height) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class OEScene* oeScene_;
|
class OEScene* oeScene_;
|
||||||
bool isInit_{ false };
|
bool isInit_{ false };
|
||||||
osg::ref_ptr<class CompositeWidgetManager> compositeWidgetManager_{ nullptr };
|
osg::ref_ptr<class CompositeWidgetManager> compositeWidgetManager_{ nullptr };
|
||||||
osg::ref_ptr<class ZoomManager> zoomManager_{ nullptr };
|
//osg::ref_ptr<class ZoomManager> zoomManager_{ nullptr };
|
||||||
osg::ref_ptr<class QueryElevationWidget> queryElevationWidget_{ nullptr };
|
osg::ref_ptr<class QueryElevationWidget> queryElevationWidget_{ nullptr };
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
#include "scene/ui/QueryElevationWidget.h"
|
#include "scene/ui/QueryElevationWidget.h"
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <osgEarth/MapNode>
|
#include <osgEarth/MapNode>
|
||||||
@ -43,12 +43,22 @@ void QueryElevationWidget::AttachViewUI(OsgViewUI* ui) {
|
|||||||
ui->addChild(this);
|
ui->addChild(this);
|
||||||
dyt_check(nullptr != oeScene_);
|
dyt_check(nullptr != oeScene_);
|
||||||
osgEarth::MapNode* mapNode = oeScene_->GetMapNode();
|
osgEarth::MapNode* mapNode = oeScene_->GetMapNode();
|
||||||
ui->getView()->addEventHandler(new QueryElevationEventHandler(mapNode, this));
|
eventHandler_ = new QueryElevationEventHandler(mapNode, this);
|
||||||
|
ui->getView()->addEventHandler(eventHandler_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QueryElevationWidget::DetachViewUI(OsgViewUI* ui) {
|
||||||
|
dyt_check(nullptr != ui);
|
||||||
|
ui->removeChild(this);
|
||||||
|
if (nullptr != eventHandler_) {
|
||||||
|
ui->getView()->removeEventHandler(eventHandler_);
|
||||||
|
eventHandler_ = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void QueryElevationWidget::OnUpdateGeoPoint(double x, double y, double z) {
|
void QueryElevationWidget::OnUpdateGeoPoint(double x, double y, double z) {
|
||||||
// x 保存小数点后6位 c++14
|
|
||||||
dyt_check(nullptr != label_);
|
dyt_check(nullptr != label_);
|
||||||
|
|
||||||
label_->setLabel(GetElevationString(x, y, z));
|
label_->setLabel(GetElevationString(x, y, z));
|
||||||
|
|||||||
@ -24,6 +24,7 @@ public:
|
|||||||
~QueryElevationWidget() override;
|
~QueryElevationWidget() override;
|
||||||
|
|
||||||
void AttachViewUI(class OsgViewUI* ui);
|
void AttachViewUI(class OsgViewUI* ui);
|
||||||
|
void DetachViewUI(class OsgViewUI* ui);
|
||||||
|
|
||||||
void OnUpdateGeoPoint(double x, double y, double z);
|
void OnUpdateGeoPoint(double x, double y, double z);
|
||||||
void ResetCanvasPosition(double width, double height);
|
void ResetCanvasPosition(double width, double height);
|
||||||
@ -34,6 +35,7 @@ private:
|
|||||||
private:
|
private:
|
||||||
class OEScene* oeScene_;
|
class OEScene* oeScene_;
|
||||||
osg::ref_ptr<osgWidget::Label> label_;
|
osg::ref_ptr<osgWidget::Label> label_;
|
||||||
|
osg::ref_ptr<QueryElevationEventHandler> eventHandler_;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,11 +1,15 @@
|
|||||||
#include "ZoomManager.h"
|
#include "ZoomManager.h"
|
||||||
|
|
||||||
|
#include <osgEarthUtil/EarthManipulator>
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "common/SpdLogger.h"
|
#include "common/SpdLogger.h"
|
||||||
#include "viewer/OsgViewUI.h"
|
#include "viewer/OsgViewUI.h"
|
||||||
#include "common/RecourceHelper.h"
|
#include "common/RecourceHelper.h"
|
||||||
|
#include "scene/OEScene.h"
|
||||||
|
|
||||||
ZoomManager::ZoomManager(void)
|
ZoomManager::ZoomManager(OEScene* oeScene)
|
||||||
|
: oeScene_(oeScene)
|
||||||
{
|
{
|
||||||
zoom = 0.0;
|
zoom = 0.0;
|
||||||
state = ZoomManager::DEFAULT;
|
state = ZoomManager::DEFAULT;
|
||||||
@ -17,12 +21,20 @@ ZoomManager::ZoomManager(void)
|
|||||||
_canvasZoom->setStrata(osgWidget::Window::STRATA_FOREGROUND);
|
_canvasZoom->setStrata(osgWidget::Window::STRATA_FOREGROUND);
|
||||||
|
|
||||||
const std::string texturePath = RecourceHelper::Get().GetResourcesPath().toStdString();
|
const std::string texturePath = RecourceHelper::Get().GetResourcesPath().toStdString();
|
||||||
_lessen = new ZoomWidget("lessen", 18, 20, texturePath + "/northarrow/zoom_down.png", "lessen", osgWidget::Widget::LAYER_TOP, this);
|
_lessen = new ZoomWidget("lessen", 18, 20, texturePath + "/northarrow/zoom_down.png",
|
||||||
_enlargement = new ZoomWidget("enlargement", 18, 20, texturePath + "/northarrow/zoom_up.png", "enlargement", osgWidget::Widget::LAYER_TOP, this);
|
"lessen", osgWidget::Widget::LAYER_TOP, this);
|
||||||
_zoomBackground = new BackGroundWidget("zoomBackground", 18, 144, texturePath + "/northarrow/zoomactive.png");
|
_enlargement = new ZoomWidget("enlargement", 18, 20,
|
||||||
_bar = new ZoomWidget("bar", 17, 10, texturePath + "/northarrow/zoombar_norm.png", "bar", osgWidget::Widget::LAYER_TOP, this);
|
texturePath + "/northarrow/zoom_up.png", "enlargement",
|
||||||
_bar_ = new BackGroundWidget("bar_", 18, 12, texturePath + "/northarrow/zoombar_norm_.png");
|
osgWidget::Widget::LAYER_TOP, this);
|
||||||
_zoomBackground_shadow = new BackGroundWidget("background_shadow", 18, 144, texturePath + "/northarrow/zoombackground.png");
|
_zoomBackground = new BackGroundWidget("zoomBackground", 18, 144,
|
||||||
|
texturePath + "/northarrow/zoomactive.png");
|
||||||
|
_bar = new ZoomWidget("bar", 17, 10,
|
||||||
|
texturePath + "/northarrow/zoombar_norm.png", "bar",
|
||||||
|
osgWidget::Widget::LAYER_TOP, this);
|
||||||
|
_bar_ = new BackGroundWidget("bar_", 18, 12,
|
||||||
|
texturePath + "/northarrow/zoombar_norm_.png");
|
||||||
|
_zoomBackground_shadow = new BackGroundWidget("background_shadow", 18, 144,
|
||||||
|
texturePath + "/northarrow/zoombackground.png");
|
||||||
|
|
||||||
_canvasZoom->addWidget(_lessen, 0, 0);
|
_canvasZoom->addWidget(_lessen, 0, 0);
|
||||||
_canvasZoom->addWidget(_enlargement, 0, 124);
|
_canvasZoom->addWidget(_enlargement, 0, 124);
|
||||||
@ -54,7 +66,7 @@ void ZoomManager::ResetCanvasPosition(double x, double y)
|
|||||||
void ZoomManager::SendZoom()
|
void ZoomManager::SendZoom()
|
||||||
{
|
{
|
||||||
_zoomNum[0] = zoom;
|
_zoomNum[0] = zoom;
|
||||||
|
slotZoom();
|
||||||
//emit signalZoom(QVariant(_zoomNum[0]));
|
//emit signalZoom(QVariant(_zoomNum[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,3 +75,51 @@ void ZoomManager::AttachViewUI(OsgViewUI* ui) {
|
|||||||
|
|
||||||
ui->addChild(_canvasZoom);
|
ui->addChild(_canvasZoom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ZoomManager::slotZoom() {
|
||||||
|
double val = _zoomNum[0];
|
||||||
|
double dx = val*(-1.0)*(0.0005);
|
||||||
|
double dy = val*(-1.0)*(0.0005);
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
// dx *= getSettings()->getMouseSensitivity();
|
||||||
|
// dy *= getSettings()->getMouseSensitivity();
|
||||||
|
|
||||||
|
double minAlt = 500.0;
|
||||||
|
double maxAlt = 35000000.0;
|
||||||
|
auto em = oeScene_->GetManipulater();
|
||||||
|
auto vp = em->getViewpoint();
|
||||||
|
vp.setRange(vp.getRange() * 1.1);
|
||||||
|
em->setViewpoint(vp);
|
||||||
|
//
|
||||||
|
// double scale = 1.0f + dy;
|
||||||
|
// double distance = em->getDistance() * scale;
|
||||||
|
// distance = std::max(distance, maxAlt);
|
||||||
|
//
|
||||||
|
// // if (!OEScene::GetSrs()->isGeographic())
|
||||||
|
// // {
|
||||||
|
// // osg::Viewport* vp = oeScene_->GetViewport();
|
||||||
|
// // if (vp)
|
||||||
|
// // {
|
||||||
|
// // double ar = vp->width() / vp->height();
|
||||||
|
// // double y = distance * tan(0.5*osg::DegreesToRadians(em->));
|
||||||
|
// // double x = y * ar;
|
||||||
|
// //
|
||||||
|
// // osgEarth::GeoExtent extentMap = oeScene_->getMap()->getProfile()->getExtent();
|
||||||
|
// //
|
||||||
|
// // if ((_center.y() - y) < extentMap.yMin())
|
||||||
|
// // {
|
||||||
|
// // return;
|
||||||
|
// // }
|
||||||
|
// // if ((_center.y() + y) > extentMap.yMax())
|
||||||
|
// // {
|
||||||
|
// // return;
|
||||||
|
// // }
|
||||||
|
// // }
|
||||||
|
// // }
|
||||||
|
//
|
||||||
|
// em->setDistance(distance);
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
class ZoomManager : public osg::Referenced {
|
class ZoomManager : public osg::Referenced {
|
||||||
public:
|
public:
|
||||||
ZoomManager(void);
|
ZoomManager(class OEScene* oeScene);
|
||||||
~ZoomManager(void);
|
~ZoomManager(void);
|
||||||
|
|
||||||
void ResetCanvasPosition(double x, double y);
|
void ResetCanvasPosition(double x, double y);
|
||||||
@ -21,12 +21,18 @@ public:
|
|||||||
osgWidget::Canvas* GetCanvasZoom() {
|
osgWidget::Canvas* GetCanvasZoom() {
|
||||||
return _canvasZoom;
|
return _canvasZoom;
|
||||||
}
|
}
|
||||||
|
osgWidget::Widget* GetBar() const {
|
||||||
|
return _bar;
|
||||||
|
}
|
||||||
|
|
||||||
void AttachViewUI(class OsgViewUI* ui);
|
void AttachViewUI(class OsgViewUI* ui);
|
||||||
//
|
//
|
||||||
//signals:
|
//signals:
|
||||||
// void signalZoom(QVariant var);
|
// void signalZoom(QVariant var);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void slotZoom();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
osgWidget::Canvas* _canvasZoom;
|
osgWidget::Canvas* _canvasZoom;
|
||||||
|
|
||||||
@ -39,6 +45,8 @@ private:
|
|||||||
|
|
||||||
int _zoomNum[1];
|
int _zoomNum[1];
|
||||||
|
|
||||||
|
class OEScene* oeScene_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum STATE {
|
enum STATE {
|
||||||
MOUSE_PUSH,
|
MOUSE_PUSH,
|
||||||
|
|||||||
@ -30,10 +30,6 @@ ZoomWidget::ZoomWidget(std::string name,
|
|||||||
_pZoomManager = pZoomManager;
|
_pZoomManager = pZoomManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZoomWidget::~ZoomWidget(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ZoomWidget::mousePush(double x, double y, const osgWidget::WindowManager* wm)
|
bool ZoomWidget::mousePush(double x, double y, const osgWidget::WindowManager* wm)
|
||||||
{
|
{
|
||||||
_pZoomManager->state = ZoomManager::MOUSE_PUSH;
|
_pZoomManager->state = ZoomManager::MOUSE_PUSH;
|
||||||
@ -42,11 +38,14 @@ bool ZoomWidget::mousePush(double x, double y, const osgWidget::WindowManager*
|
|||||||
if ("lessen" == _order)
|
if ("lessen" == _order)
|
||||||
{
|
{
|
||||||
_pZoomManager->zoom = -43;
|
_pZoomManager->zoom = -43;
|
||||||
|
UpdateBarPosition(_pZoomManager->zoom);
|
||||||
}
|
}
|
||||||
else if ("enlargement" == _order)
|
else if ("enlargement" == _order)
|
||||||
{
|
{
|
||||||
_pZoomManager->zoom = 43;
|
_pZoomManager->zoom = 43;
|
||||||
|
UpdateBarPosition(_pZoomManager->zoom);
|
||||||
}
|
}
|
||||||
|
|
||||||
setColor(1, 1, 1, 1);
|
setColor(1, 1, 1, 1);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -55,48 +54,55 @@ bool ZoomWidget::mouseRelease(double x, double y, const osgWidget::WindowManager
|
|||||||
{
|
{
|
||||||
_pZoomManager->state = ZoomManager::MOUSE_RELEASE;
|
_pZoomManager->state = ZoomManager::MOUSE_RELEASE;
|
||||||
|
|
||||||
if ("bar" == _order)
|
//if ("bar" == _order)
|
||||||
{
|
//{
|
||||||
setOrigin(0, 67);
|
// setOrigin(0, 67);
|
||||||
getParent()->getByName("bar_")->setOrigin(0, 66);
|
// getParent()->getByName("bar_")->setOrigin(0, 66);
|
||||||
getParent()->resize();
|
// getParent()->resize();
|
||||||
}
|
//}
|
||||||
_pZoomManager->zoom = 0.0;
|
_pZoomManager->zoom = 0.0;
|
||||||
|
UpdateBarPosition(_pZoomManager->zoom);
|
||||||
setColor(1, 1, 1, 0);
|
setColor(1, 1, 1, 0);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
//
|
||||||
|
//bool ZoomWidget::mouseDrag(double x, double y, const osgWidget::WindowManager* wm)
|
||||||
|
//{
|
||||||
|
// if (_order == "bar")
|
||||||
|
// {
|
||||||
|
// _pointX += x;
|
||||||
|
// _pointY += y;
|
||||||
|
//
|
||||||
|
// while (_pZoomManager->zoom > 43)
|
||||||
|
// _pZoomManager->zoom = 43;
|
||||||
|
// while (_pZoomManager->zoom < -43)
|
||||||
|
// _pZoomManager->zoom = -43;
|
||||||
|
//
|
||||||
|
// if (y > 43 - _pZoomManager->zoom)
|
||||||
|
// {
|
||||||
|
// y = 43 - _pZoomManager->zoom;
|
||||||
|
// }
|
||||||
|
// if (y < -43 - _pZoomManager->zoom)
|
||||||
|
// {
|
||||||
|
// y = -43 - _pZoomManager->zoom;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (_pZoomManager->zoom >= -43 && _pZoomManager->zoom <= 43)
|
||||||
|
// {
|
||||||
|
// /*addOrigin(0, y);
|
||||||
|
// getParent()->getByName("bar_")->addOrigin(0, y);*/
|
||||||
|
// double y1 = _pZoomManager->GetBar()->getOrigin().y();
|
||||||
|
// UpdateBarPosition(y + y1);
|
||||||
|
// _pZoomManager->zoom += y;
|
||||||
|
// }
|
||||||
|
// else {
|
||||||
|
// _pZoomManager->zoom += y;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return true;
|
||||||
|
//}
|
||||||
|
|
||||||
bool ZoomWidget::mouseDrag(double x, double y, const osgWidget::WindowManager* wm)
|
void ZoomWidget::UpdateBarPosition(double y) {
|
||||||
{
|
_pZoomManager->GetBar()->setOrigin(0, 67 + y * 0.5);
|
||||||
if (_order == "bar")
|
_pZoomManager->GetCanvasZoom()->update();
|
||||||
{
|
}
|
||||||
_pointX += x;
|
|
||||||
_pointY += y;
|
|
||||||
|
|
||||||
while (_pZoomManager->zoom > 43)
|
|
||||||
_pZoomManager->zoom = 43;
|
|
||||||
while (_pZoomManager->zoom < -43)
|
|
||||||
_pZoomManager->zoom = -43;
|
|
||||||
|
|
||||||
if (y > 43 - _pZoomManager->zoom)
|
|
||||||
{
|
|
||||||
y = 43 - _pZoomManager->zoom;
|
|
||||||
}
|
|
||||||
if (y < -43 - _pZoomManager->zoom)
|
|
||||||
{
|
|
||||||
y = -43 - _pZoomManager->zoom;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_pZoomManager->zoom >= -43 && _pZoomManager->zoom <= 43)
|
|
||||||
{
|
|
||||||
addOrigin(0, y);
|
|
||||||
getParent()->getByName("bar_")->addOrigin(0, y);
|
|
||||||
_pZoomManager->zoom += y;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
_pZoomManager->zoom += y;
|
|
||||||
}
|
|
||||||
getParent()->resize();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|||||||
@ -21,15 +21,16 @@ public:
|
|||||||
osgWidget::Widget::Layer layer,
|
osgWidget::Widget::Layer layer,
|
||||||
ZoomManager *pZoomManager);
|
ZoomManager *pZoomManager);
|
||||||
|
|
||||||
~ZoomWidget(void);
|
~ZoomWidget(void) override = default;
|
||||||
|
|
||||||
bool mousePush(double, double, const osgWidget::WindowManager*);
|
bool mousePush(double, double, const osgWidget::WindowManager*);
|
||||||
bool mouseRelease(double, double, const osgWidget::WindowManager*);
|
bool mouseRelease(double, double, const osgWidget::WindowManager*);
|
||||||
bool mouseDrag(double, double, const osgWidget::WindowManager*);
|
//bool mouseDrag(double, double, const osgWidget::WindowManager*);
|
||||||
|
|
||||||
std::string GetOrder() { return _order; }
|
std::string GetOrder() { return _order; }
|
||||||
double GetPointerX() { return _pointX; }
|
double GetPointerX() { return _pointX; }
|
||||||
double GetpointerY() { return _pointY; }
|
double GetpointerY() { return _pointY; }
|
||||||
|
void UpdateBarPosition(double y);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
double _pointX;
|
double _pointX;
|
||||||
|
|||||||
1
src/scutcheon
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 99fe4de63326ed57f80411289763eb4449778122
|
||||||