add triton codes
This commit is contained in:
parent
9c8d78fd8b
commit
0238063243
154
Source/src/scene/OEScene.cpp
Normal file
154
Source/src/scene/OEScene.cpp
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
#include "scene/OEScene.h"
|
||||||
|
|
||||||
|
#include <osg/Shape>
|
||||||
|
#include <osg/ShapeDrawable>
|
||||||
|
#include <osg/PositionAttitudeTransform>
|
||||||
|
#include <osg/Program>
|
||||||
|
#include <osg/LightSource>
|
||||||
|
#include <osgDB/ReadFile>
|
||||||
|
#include <osgEarth/GLUtils>
|
||||||
|
#include <osgEarth/EarthManipulator>
|
||||||
|
|
||||||
|
#include <osgShadow/ShadowedScene>
|
||||||
|
#include <osgShadow/ViewDependentShadowMap>
|
||||||
|
#include <osgViewer/ViewerEventHandlers>
|
||||||
|
|
||||||
|
#include "common/SpdLogger.h"
|
||||||
|
#include "common/RecourceHelper.h"
|
||||||
|
#include "scene/ScopedTimer.h"
|
||||||
|
#include "viewer/OsgView.h"
|
||||||
|
|
||||||
|
|
||||||
|
OEScene::OEScene() {
|
||||||
|
osgDB::FilePathList& pathList = osgDB::Registry::instance()->getDataFilePathList();
|
||||||
|
const std::string& basePath = RecourceHelper::Get().GetBasePath().toStdString();
|
||||||
|
pathList.push_back(basePath + "/resources/earth/");
|
||||||
|
pathList.push_back(basePath + "resources/textures/");
|
||||||
|
|
||||||
|
earthRootNode_ = osgDB::readNodeFile("triton.earth");
|
||||||
|
if (!earthRootNode_) {
|
||||||
|
LOG_ERROR("read earth node(triton.earth) failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
earthMapNode_ = osgEarth::MapNode::get(earthRootNode_);
|
||||||
|
LOG_INFO("earth map node get success: {}", earthMapNode_.valid());
|
||||||
|
|
||||||
|
entityRoot_ = new osg::Group;
|
||||||
|
if (earthMapNode_) {
|
||||||
|
earthMapNode_->addChild(entityRoot_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OEScene::AttachView(OsgView* view) {
|
||||||
|
if (nullptr == view) {
|
||||||
|
LOG_WARN("view is nullptr");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//osg::Node* node1 = osgDB::readNodeFile("chaff_bombs.osg");
|
||||||
|
//node1->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
|
||||||
|
//osg::MatrixTransform* mt = new osg::MatrixTransform;
|
||||||
|
//mt->addChild(node1);
|
||||||
|
////GetOceanScene()->addChild(mt);
|
||||||
|
//entityRoot_->addChild(mt);
|
||||||
|
//osg::Vec3 eye(0.0f, 60.f, 50.0f);
|
||||||
|
//mt->setMatrix(osg::Matrix::translate(eye)/* * osg::Matrix::scale(osg::Vec3(10, 10, 10))*/);
|
||||||
|
//////mt->getOrCreateStateSet()-
|
||||||
|
|
||||||
|
//osg::Node* node = view->GetView()->getSceneData();
|
||||||
|
//if (nullptr == node) {
|
||||||
|
// LOG_INFO("view scene data is nullptr, root valid:{}", scene_.valid());
|
||||||
|
// view->GetView()->setSceneData(scene_);
|
||||||
|
//} else {
|
||||||
|
// osg::Group* group = node->asGroup();
|
||||||
|
// if (nullptr != group) {
|
||||||
|
// LOG_INFO("node is group");
|
||||||
|
// group->addChild(scene_);
|
||||||
|
// } else {
|
||||||
|
// LOG_INFO("node is not group");
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OEScene::DetachView(OsgView* view) {
|
||||||
|
if (nullptr != earthRootNode_) {
|
||||||
|
std::vector<osg::Group*> parents = earthRootNode_->getParents();
|
||||||
|
for (const auto& parent : parents) {
|
||||||
|
parent->removeChild(earthRootNode_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
view->GetView()->setSceneData(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define USE_CUSTOM_SHADER
|
||||||
|
|
||||||
|
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 earthMapNode_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void OEScene::AddToScene(osg::Node* node) {
|
||||||
|
assert(nullptr != entityRoot_);
|
||||||
|
entityRoot_->addChild(node);
|
||||||
|
/* osgOcean::OceanScene* oceanScene = GetOceanScene();
|
||||||
|
if (nullptr == oceanScene) {
|
||||||
|
LOG_WARN("oceanScene is nullptr");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
node->setNodeMask(oceanScene->getNormalSceneMask() |
|
||||||
|
oceanScene->getReflectedSceneMask() |
|
||||||
|
oceanScene->getRefractedSceneMask() |
|
||||||
|
CAST_SHADOW | RECEIVE_SHADOW);
|
||||||
|
oceanScene->addChild(node);*/
|
||||||
|
/* osg::Group* root = GetScene();
|
||||||
|
root->addChild(node);*/
|
||||||
|
}
|
39
Source/src/scene/OEScene.h
Normal file
39
Source/src/scene/OEScene.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <osg/Switch>
|
||||||
|
#include <osg/TextureCubeMap>
|
||||||
|
|
||||||
|
#include <osgText/Text>
|
||||||
|
#include <osgEarth/ModelNode>
|
||||||
|
|
||||||
|
#include "scene/SkyDome.h"
|
||||||
|
|
||||||
|
class OsgView;
|
||||||
|
|
||||||
|
class OEScene : public osg::Referenced {
|
||||||
|
public:
|
||||||
|
OEScene();
|
||||||
|
void InitEventHandle(OsgView* view);
|
||||||
|
void AttachView(OsgView* 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 earthMapNode_.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddToScene(osg::Node* node);
|
||||||
|
|
||||||
|
private:
|
||||||
|
osg::ref_ptr<osg::Node> earthRootNode_;
|
||||||
|
osg::ref_ptr<osgEarth::MapNode> earthMapNode_;
|
||||||
|
osg::ref_ptr<osg::Group> entityRoot_;
|
||||||
|
};
|
114
Source/src/scene/TritonAPIWrapper.cpp
Normal file
114
Source/src/scene/TritonAPIWrapper.cpp
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
/* -*-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(); }
|
112
Source/src/scene/TritonAPIWrapper.h
Normal file
112
Source/src/scene/TritonAPIWrapper.h
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
/* -*-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
|
39
Source/src/scene/TritonCallback.h
Normal file
39
Source/src/scene/TritonCallback.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/* -*-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
|
222
Source/src/scene/TritonContext.cpp
Normal file
222
Source/src/scene/TritonContext.cpp
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
/* -*-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>
|
||||||
|
|
||||||
|
#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");
|
||||||
|
}
|
||||||
|
|
||||||
|
_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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
115
Source/src/scene/TritonContext.h
Normal file
115
Source/src/scene/TritonContext.h
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
/* -*-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
|
330
Source/src/scene/TritonDrawable.cpp
Normal file
330
Source/src/scene/TritonDrawable.cpp
Normal file
@ -0,0 +1,330 @@
|
|||||||
|
/* -*-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();
|
||||||
|
}
|
102
Source/src/scene/TritonDrawable.h
Normal file
102
Source/src/scene/TritonDrawable.h
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
/* -*-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
|
434
Source/src/scene/TritonHeightMap.cpp
Normal file
434
Source/src/scene/TritonHeightMap.cpp
Normal file
@ -0,0 +1,434 @@
|
|||||||
|
/* -*-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;
|
||||||
|
}
|
109
Source/src/scene/TritonHeightMap.h
Normal file
109
Source/src/scene/TritonHeightMap.h
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
/* -*-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
|
51
Source/src/scene/TritonIntersections.cpp
Normal file
51
Source/src/scene/TritonIntersections.cpp
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/* -*-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(2.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;
|
||||||
|
}
|
72
Source/src/scene/TritonIntersections.h
Normal file
72
Source/src/scene/TritonIntersections.h
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
/* -*-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
|
386
Source/src/scene/TritonLayer.cpp
Normal file
386
Source/src/scene/TritonLayer.cpp
Normal file
@ -0,0 +1,386 @@
|
|||||||
|
/* -*-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*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;
|
||||||
|
}
|
125
Source/src/scene/TritonLayer.h
Normal file
125
Source/src/scene/TritonLayer.h
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
/* -*-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
|
@ -12,7 +12,6 @@
|
|||||||
#include "xml/tinyxml2.h"
|
#include "xml/tinyxml2.h"
|
||||||
#include "common/SpdLogger.h"
|
#include "common/SpdLogger.h"
|
||||||
#include "entities/Entity.h"
|
#include "entities/Entity.h"
|
||||||
#include "scene/OsgScene.h"
|
|
||||||
//#include "workspace/WorkSpaceItemGroup.h"
|
//#include "workspace/WorkSpaceItemGroup.h"
|
||||||
//#include "workspace/WorkSpaceRiverGroup.h"
|
//#include "workspace/WorkSpaceRiverGroup.h"
|
||||||
//#include "workspace/WorkSpaceRiverNetGroup.h"
|
//#include "workspace/WorkSpaceRiverNetGroup.h"
|
||||||
@ -45,18 +44,29 @@ bool WorkSpace::CreateScene(const std::string& scene) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*if (nullptr != activeScene_) {
|
if (nullptr != activeScene_) {
|
||||||
activeScene_->DetachView(view_);
|
activeScene_->DetachView(view_);
|
||||||
}*/
|
}
|
||||||
|
|
||||||
/* name_ = name_.fromStdString(scene);
|
name_ = name_.fromStdString(scene);
|
||||||
|
#if 0
|
||||||
activeScene_ = new OsgScene;
|
activeScene_ = new OsgScene;
|
||||||
activeScene_->UseShadows(false);
|
activeScene_->UseShadows(false);
|
||||||
|
|
||||||
activeScene_->ChangeScene(OsgScene::CLOUDY);
|
activeScene_->ChangeScene(OsgScene::CLOUDY);
|
||||||
|
|
||||||
activeScene_->AttachView(view_);
|
activeScene_->AttachView(view_);
|
||||||
activeScene_->InitEventHandle(view_);*/
|
activeScene_->InitEventHandle(view_);
|
||||||
|
#else
|
||||||
|
activeScene_ = new OEScene;
|
||||||
|
activeScene_->UseShadows(false);
|
||||||
|
|
||||||
|
activeScene_->ChangeScene(OsgScene::CLOUDY);
|
||||||
|
|
||||||
|
activeScene_->AttachView(view_);
|
||||||
|
activeScene_->InitEventHandle(view_);
|
||||||
|
#endif
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
#include "scene/OsgScene.h"
|
#include "scene/OsgScene.h"
|
||||||
|
#include "scene/OEScene.h"
|
||||||
|
|
||||||
//#include "../ui/chartPlot/DYTChart.h"
|
//#include "../ui/chartPlot/DYTChart.h"
|
||||||
|
|
||||||
@ -84,7 +85,7 @@ private:
|
|||||||
QString path_;
|
QString path_;
|
||||||
|
|
||||||
std::vector<class Entity*> entities_;
|
std::vector<class Entity*> entities_;
|
||||||
//osg::ref_ptr<OsgScene> activeScene_;
|
osg::ref_ptr<OEScene> activeScene_;
|
||||||
class OsgView* view_{ nullptr };
|
class OsgView* view_{ nullptr };
|
||||||
class Timestep* timestep_{ nullptr };
|
class Timestep* timestep_{ nullptr };
|
||||||
class LampStatus* lampStatus_{ nullptr };
|
class LampStatus* lampStatus_{ nullptr };
|
||||||
|
Loading…
Reference in New Issue
Block a user