277 lines
11 KiB
Plaintext
277 lines
11 KiB
Plaintext
#pragma once
|
|
#include <osgEarthImGui/ImGuiPanel>
|
|
#include <osgEarthProcedural/LifeMapLayer>
|
|
#include <osgEarthProcedural/TextureSplattingLayer>
|
|
#include <osgEarth/VirtualProgram>
|
|
|
|
namespace {
|
|
const char* render_lifemap = R"(
|
|
#version 450
|
|
#pragma vp_function oeiu_render_lifemap, fragment_lighting, last
|
|
void oeiu_render_lifemap(inout vec4 color) { color.a = 1.0; }
|
|
)";
|
|
const char* render_density = R"(
|
|
#version 450
|
|
#pragma vp_function oeui_render_density, fragment_lighting, last
|
|
void oeui_render_density(inout vec4 color) { color = vec4(0,color.g,0,1); }
|
|
)";
|
|
|
|
const char* render_lush = R"(
|
|
#version 450
|
|
#pragma vp_function oeui_render_lush, fragment_lighting, last
|
|
void oeui_render_lush(inout vec4 color) { color = vec4(0,0,color.b, 1); }
|
|
)";
|
|
|
|
const char* render_rugged = R"(
|
|
#version 450
|
|
#pragma vp_function oeui_render_rugged, fragment_lighting, last
|
|
void oeui_render_rugged(inout vec4 color) { color = vec4(color.r, 0, 0, 1); }
|
|
)";
|
|
|
|
const char* render_alpha = R"(
|
|
#version 450
|
|
#pragma vp_function oeui_render_alpha, fragment_lighting, last
|
|
void oeui_render_alpha(inout vec4 color) { color = vec4(color.a, color.a, color.a, 1.0); }
|
|
)";
|
|
}
|
|
|
|
namespace osgEarth
|
|
{
|
|
namespace Procedural
|
|
{
|
|
using namespace osgEarth;
|
|
|
|
struct LifeMapLayerGUI : public ImGuiPanel
|
|
{
|
|
osg::observer_ptr<MapNode> _mapNode;
|
|
osg::observer_ptr<LifeMapLayer> _lifemap;
|
|
osg::observer_ptr<TextureSplattingLayer> _splat;
|
|
VirtualProgram* _vp;
|
|
std::string _renderMode;
|
|
bool _showLifemapUnderMouse;
|
|
Future<osg::Vec4> _lifemapUnderMouse;
|
|
bool _showLandcoverUnderMouse;
|
|
Future<LandCoverSample> _landcoverUnderMouse;
|
|
//Future<osg::Vec4> _lifemapUnderMouse;
|
|
bool _first;
|
|
|
|
LifeMapLayerGUI() : ImGuiPanel("Life Map"),
|
|
_first(true),
|
|
_vp(nullptr),
|
|
_showLifemapUnderMouse(false),
|
|
_showLandcoverUnderMouse(false)
|
|
{
|
|
//nop
|
|
}
|
|
|
|
void setRenderMode(const std::string& mode, osg::RenderInfo& ri)
|
|
{
|
|
if (!_vp)
|
|
_vp = VirtualProgram::getOrCreate(_lifemap->getOrCreateStateSet());
|
|
|
|
if (!_renderMode.empty())
|
|
ShaderLoader::unload(_vp, _renderMode);
|
|
_renderMode = mode;
|
|
if (!_renderMode.empty())
|
|
ShaderLoader::load(_vp, _renderMode);
|
|
|
|
bool show = !_renderMode.empty();
|
|
_lifemap->setVisible(show);
|
|
if (_splat.valid())
|
|
_splat->setVisible(!show);
|
|
}
|
|
|
|
void draw(osg::RenderInfo& ri) override
|
|
{
|
|
if (!findNodeOrHide(_mapNode, ri))
|
|
return;
|
|
if (!findLayerOrHide(_lifemap, ri))
|
|
return;
|
|
|
|
findLayer(_splat, ri);
|
|
|
|
if (_first)
|
|
{
|
|
EventRouter::get(view(ri))
|
|
.onMove([&](osg::View* v, float x, float y) { onMove(v, x, y); });
|
|
|
|
_first = false;
|
|
}
|
|
|
|
ImGui::Begin("Life Map");
|
|
|
|
// render the layer?
|
|
ImGui::TextColored(ImVec4(1, 1, 0, 1), "Visualization");
|
|
{
|
|
static int s_renderMode = 0;
|
|
int m = 0;
|
|
|
|
if (ImGui::RadioButton("Normal", &s_renderMode, m++)) {
|
|
setRenderMode("", ri);
|
|
}
|
|
if (ImGui::RadioButton("Ruggedness", &s_renderMode, m++)) {
|
|
setRenderMode(render_rugged, ri);
|
|
}
|
|
if (ImGui::RadioButton("Density", &s_renderMode, m++)) {
|
|
setRenderMode(render_density, ri);
|
|
}
|
|
if (ImGui::RadioButton("Lushness", &s_renderMode, m++)) {
|
|
setRenderMode(render_lush, ri);
|
|
}
|
|
if (ImGui::RadioButton("Material", &s_renderMode, m++)) {
|
|
setRenderMode(render_alpha, ri);
|
|
}
|
|
if (ImGui::RadioButton("All", &s_renderMode, m++)) {
|
|
setRenderMode(render_lifemap, ri);
|
|
}
|
|
}
|
|
|
|
LifeMapLayer::Options& o = _lifemap->options();
|
|
|
|
ImGui::Separator();
|
|
ImGui::TextColored(ImVec4(1, 1, 0, 1), "LifeMap Generator levels:");
|
|
|
|
if (ImGuiLTable::Begin("LifeMap"))
|
|
{
|
|
ImGuiLTable::SliderFloat("Coverage contrib", &o.landCoverWeight().mutable_value(), 0.0f, 1.0f);
|
|
if (o.landCoverWeight().value() > 0.0f)
|
|
{
|
|
float value = o.landCoverBlur()->as(Units::METERS);
|
|
if (ImGuiLTable::SliderFloat("Coverage blur (m)", &value, 0.0f, 100.0f, "%.2f", ImGuiSliderFlags_Logarithmic))
|
|
o.landCoverBlur()->set(value, Units::METERS);
|
|
}
|
|
|
|
if (_lifemap->getColorLayer())
|
|
{
|
|
ImGuiLTable::SliderFloat("Imagery color contrib", &o.colorWeight().mutable_value(), 0.0f, 1.0f);
|
|
}
|
|
|
|
ImGuiLTable::SliderFloat("Terrain contrib", &o.terrainWeight().mutable_value(), 0.0f, 1.0f);
|
|
//ImGuiLTable::SliderFloat("Slope contrib", &o.slopeIntensity().mutable_value(), 1.0f, 10.0f);
|
|
//ImGuiLTable::SliderFloat("Slope cutoff", &o.slopeCutoff().mutable_value(), 0.0f, 1.0f);
|
|
|
|
ImGuiLTable::SliderFloat("Noise contrib", &o.noiseWeight().mutable_value(), 0.0f, 1.0f);
|
|
|
|
ImGuiLTable::End();
|
|
}
|
|
|
|
if (ImGui::Button("Apply Changes"))
|
|
{
|
|
// make sure the cache is off
|
|
_lifemap->setCachePolicy(CachePolicy::NO_CACHE);
|
|
|
|
_mapNode->getTerrainEngine()->invalidateRegion(
|
|
{ _lifemap.get() },
|
|
GeoExtent::INVALID);
|
|
}
|
|
|
|
ImGui::Separator();
|
|
ImGui::Checkbox("Show lifemap under mouse", &_showLifemapUnderMouse);
|
|
if (_showLifemapUnderMouse && _lifemapUnderMouse.available())
|
|
{
|
|
osg::Vec4 pixel = _lifemapUnderMouse.value();
|
|
ImGui::Text("R=%.2f D=%.2f L=%.2f M=%d",
|
|
pixel.r(),
|
|
pixel.g(),
|
|
pixel.b(),
|
|
(int)(pixel.a() * 255.0f));
|
|
}
|
|
|
|
if (_lifemap.valid() && _lifemap->getLandCoverLayer())
|
|
{
|
|
ImGui::Separator();
|
|
ImGui::Checkbox("Show landcover under mouse", &_showLandcoverUnderMouse);
|
|
if (_showLandcoverUnderMouse && _landcoverUnderMouse.available())
|
|
{
|
|
LandCoverSample sample = _landcoverUnderMouse.value();
|
|
if (sample.biomeid().isSet())
|
|
ImGui::Text("biome_id = %s", sample.biomeid().get().c_str());
|
|
if (sample.dense().isSet())
|
|
ImGui::Text("dense = %.2f", sample.dense().get());
|
|
if (sample.lush().isSet())
|
|
ImGui::Text("lush = %.2f", sample.lush().get());
|
|
if (sample.rugged().isSet())
|
|
ImGui::Text("rugged = %.2f", sample.rugged().get());
|
|
if (sample.material().isSet())
|
|
ImGui::Text("material = %s", sample.material().get().c_str());
|
|
if (sample.soiltype().isSet())
|
|
ImGui::Text("soiltype = %s", sample.soiltype().get().c_str());
|
|
}
|
|
}
|
|
|
|
ImGui::End();
|
|
}
|
|
|
|
bool getKeyUnderMouse(osg::View* view, float x, float y, TileKey& key, GeoPoint& point)
|
|
{
|
|
TerrainTile* tile = _mapNode->getTerrain()->getTerrainTileUnderMouse(view, x, y);
|
|
if (tile)
|
|
{
|
|
point = _mapNode->getGeoPointUnderMouse(view, x, y);
|
|
key = _mapNode->getMap()->getProfile()->createTileKey(point.x(), point.y(), tile->getKey().getLOD());
|
|
}
|
|
return key.valid();
|
|
}
|
|
|
|
void onMove(osg::View* view, float x, float y)
|
|
{
|
|
TileKey keyUnderMouse;
|
|
GeoPoint pointUnderMouse;
|
|
|
|
if (_showLifemapUnderMouse)
|
|
{
|
|
_lifemapUnderMouse.reset();
|
|
getKeyUnderMouse(view, x, y, keyUnderMouse, pointUnderMouse);
|
|
|
|
TileKey key = _lifemap->getBestAvailableTileKey(keyUnderMouse, false);
|
|
if (key.valid())
|
|
{
|
|
auto task = [this, key, pointUnderMouse](Cancelable& c)
|
|
{
|
|
osg::Vec4 result(0, 0, 0, 1);
|
|
osg::ref_ptr<ProgressCallback> prog = new ProgressCallback(&c);
|
|
auto g = _lifemap->createImage(key, prog.get());
|
|
if (g.valid())
|
|
{
|
|
g.getReader().setBilinear(false);
|
|
g.read(result, pointUnderMouse);
|
|
}
|
|
return result;
|
|
};
|
|
|
|
_lifemapUnderMouse = jobs::dispatch(task);
|
|
}
|
|
}
|
|
|
|
if (_showLandcoverUnderMouse)
|
|
{
|
|
auto coverage = _lifemap->getLandCoverLayer();
|
|
|
|
_landcoverUnderMouse.reset();
|
|
|
|
if (!keyUnderMouse.valid())
|
|
getKeyUnderMouse(view, x, y, keyUnderMouse, pointUnderMouse);
|
|
|
|
TileKey key = coverage->getBestAvailableTileKey(keyUnderMouse, false);
|
|
if (key.valid())
|
|
{
|
|
auto task = [this, key, pointUnderMouse](Cancelable& c)
|
|
{
|
|
LandCoverSample result;
|
|
osg::ref_ptr<ProgressCallback> prog = new ProgressCallback(&c);
|
|
auto factory = LandCoverSample::Factory::create(_lifemap->getLandCoverLayer());
|
|
auto g = factory->createCoverage(key, prog.get());
|
|
if (g.valid())
|
|
{
|
|
g.readAtCoords(result, pointUnderMouse.x(), pointUnderMouse.y());
|
|
}
|
|
return result;
|
|
};
|
|
_landcoverUnderMouse = jobs::dispatch(task);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
}
|