osg系列文章目录
前言
我使用的是osg3.6.5,osgearth3.2版本,使用osgearth使渲染地球,运行效果中间被黑色遮挡,不知道具体原因,请看下图

一、代码
#pragma once
#include <osg/Group>
#include <osgviewer/Viewer>
#include <osgDB/ReadFile>
#include <osgviewer/api/Win32/GraphicsWindowWin32>
#include <osgGA/TrackballManipulator>
#include <osgEarth/MapNode>
#include <osgEarth/Utils>
#include <osgEarth/EarthManipulator>
#include <osgEarth/SkyView>
#include <osgEarth/Units>
//#include <osgEarth/Util/SkyNode> // 确保包含 SkyNode 的定义
using namespace osgEarth;
using namespace osgEarth::Util;
class COSGObject
{
public:
COSGObject(HWND hWnd);
~COSGObject();
void InitOSG();
void InitSceneGraph();
void InitCameraConfig();
void PreFrameUpdate();
void PostFrameUpdate();
static void Render(void* ptr);
void InitOsgEarth();
osgViewer::Viewer* GetViewer();
private:
HWND m_hWnd;
osg::ref_ptr<osgViewer::Viewer> m_viewer;
osg::ref_ptr<osg::Group> m_root;
osg::ref_ptr<osgEarth::MapNode> m_mapNode;
osg::ref_ptr<osgEarth::EarthManipulator> m_em;
};
#include "pch.h"
#include "COSGObject.h"
COSGObject::COSGObject(HWND hWnd)
{
m_hWnd = hWnd;
m_viewer = NULL;
m_root = NULL;
}
COSGObject::~COSGObject()
{
}
void COSGObject::InitOSG()
{
InitSceneGraph();
InitCameraConfig();
InitOsgEarth();
}
void COSGObject::InitSceneGraph()
{
//osg::ref_ptr<osg::Group> rr = new osg::Group;
try {
osgEarth::initialize();
m_root = new osg::Group;
m_root->addChild(osgDB::readNodeFile("../../vs2022_64bit_3rdParty_osg365_oe32/runtime/test/earthFile/china-simple.earth"));
}
catch(const std::exception& e) {
AfxMessageBox(CString("Failed to create osg::Group in constructor: ") + CString(e.what()));
throw std::runtime_error(std::string("Failed to create osg::Group in constructor: ") + e.what());
}
}
void COSGObject::InitCameraConfig()
{
RECT rect;
m_viewer = new osgViewer::Viewer;
//osg::ref_ptr<osgViewer::View> viewer = new osgViewer::Viewer;
//osg::ref_ptr<osgViewer::Viewer> m_vv = new osgViewer::Viewer;
::GetWindowRect(m_hWnd, &rect);
osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
osg::ref_ptr<osg::Referenced> winData = new osgViewer::GraphicsWindowWin32::WindowData(m_hWnd);
traits->x = 0;
traits->y = 0;
traits->width = rect.right - rect.left;
traits->height = rect.bottom - rect.top;
traits->windowDecoration = false;
traits->doubleBuffer = true;
traits->sharedContext = 0;
traits->setInheritedWindowPixelFormat = true;
traits->inheritedWindowData = winData;
osg::GraphicsContext* gc = osg::GraphicsContext::createGraphicsContext(traits);
osg::ref_ptr<osg::Camera> camera = new osg::Camera;
camera->setGraphicsContext(gc);
camera->setViewport(new osg::Viewport(traits->x, traits->y, traits->width, traits->height));
camera->setProjectionMatrixAsPerspective(30.0f, static_cast<double>(traits->width) / static_cast<double>(traits->height),
1.0f, 1000.f);
m_viewer->setCamera(camera);
m_viewer->setCameraManipulator(new osgGA::TrackballManipulator);
m_viewer->setSceneData(m_root);
m_viewer->realize();
m_viewer->getCamera()->setComputeNearFarMode(osg::CullSettings::COMPUTE_NEAR_FAR_USING_PRIMITIVES);
m_viewer->getCamera()->setNearFarRatio(0.000003f);
}
void COSGObject::PreFrameUpdate()
{
}
void COSGObject::PostFrameUpdate()
{
}
void COSGObject::Render(void* ptr)
{
COSGObject* osg = (COSGObject*)ptr;
osgViewer::Viewer* viewer = osg->GetViewer();
while (!viewer->done())
{
osg->PreFrameUpdate();
viewer->frame();
osg->PostFrameUpdate();
}
_endthread();
}
osgViewer::Viewer* COSGObject::GetViewer()
{
return m_viewer;
}
void COSGObject::InitOsgEarth()
{
osgEarth::initialize();
//初始化操作器
m_em = new osgEarth::EarthManipulator;
if (m_mapNode)
{
m_em->setNode(m_mapNode.get());
}
m_em->getSettings()->setArcViewpointTransitions(true);
m_viewer->setCameraManipulator(m_em);
//初始化天空
osgEarth::Config skyConf;
double hours = skyConf.value("hours", 12.0);
//osg::ref_ptr<osgEarth::SkyNode> skyNode = new osgEarth::SkyNode(skyConf);
}
二、分析原因
1.刚开始我以为是我下载的全球30米高程图片和影像图片不匹配导致的原因,我还专门求教了国内osgearth顶尖大佬—杨石兴老师,他直接给出了结论是:“应该不是,应该是远近裁切面的问题”,大佬就是大佬一下就定位到问题所在,在此特别感恩一下杨老师的的耐心解答。杨老师还在B站无私奉献了:OSG的B站小讲堂 --35讲osgEarth视频教程
以及OSG的B站小讲堂—72讲OSG视频教程
全部免费观看,还有资料下载地址
2.经过调试发现问题是:
setComputeNearFarMode这个函数,
m_viewer->getCamera()->setComputeNearFarMode(osg::CullSettings::COMPUTE_NEAR_FAR_USING_PRIMITIVES);
在CullSettings中,camera和cullvisitor都使用了这个函数进
行远近平面的自动计算,可以优化远近平面的深度范围。
把
m_viewer->getCamera()->setComputeNearFarMode(osg::CullSettings::COMPUTE_NEAR_FAR_USING_PRIMITIVES);
这行代码修改成:
m_viewer->getCamera()->setComputeNearFarMode(osg::CullSettings::COMPUTE_NEAR_FAR_USING_BOUNDING_VOLUMES);
运行效果如下图:

我还是贴出完整代码,方便读者查看
#pragma once
#include <osg/Group>
#include <osgviewer/Viewer>
#include <osgDB/ReadFile>
#include <osgviewer/api/Win32/GraphicsWindowWin32>
#include <osgGA/TrackballManipulator>
#include <osgEarth/MapNode>
#include <osgEarth/Utils>
#include <osgEarth/EarthManipulator>
#include <osgEarth/SkyView>
#include <osgEarth/Units>
//#include <osgEarth/Util/SkyNode> // 确保包含 SkyNode 的定义
#include <osgEarth/Sky>
#include <osgEarth/Ephemeris>
#include <osgEarth/ImageLayer>
using namespace osgEarth;
using namespace osgEarth::Util;
class COSGObject
{
public:
COSGObject(HWND hWnd);
~COSGObject();
void InitOSG();
void InitSceneGraph();
void InitCameraConfig();
void PreFrameUpdate();
void PostFrameUpdate();
static void Render(void* ptr);
void InitOsgEarth();
void setChinaBoundariesOpacity(double opt);
double getChinaBoundariesOpacity();
void initializeChinaBoundaries();
osgViewer::Viewer* GetViewer();
private:
HWND m_hWnd;
osg::ref_ptr<osgViewer::Viewer> m_viewer;
osg::ref_ptr<osg::Group> m_root;
osg::ref_ptr<osgEarth::MapNode> m_mapNode;
osg::ref_ptr<osgEarth::EarthManipulator> m_em;
osg::ref_ptr<osgEarth::SkyNode> m_skyNode;
time_t m_nowTime;
tm* m_tm;
//国界线图层
//osg::ref_ptr<osgEarth::Layer> m_chinaBoundaries;
osg::ref_ptr<osgEarth::ImageLayer> m_chinaBoundaries;
};
#include "pch.h"
#include "COSGObject.h"
COSGObject::COSGObject(HWND hWnd)
{
m_hWnd = hWnd;
m_viewer = NULL;
m_root = NULL;
}
COSGObject::~COSGObject()
{
}
void COSGObject::InitOSG()
{
InitSceneGraph();
InitCameraConfig();
InitOsgEarth();
}
void COSGObject::InitSceneGraph()
{
//osg::ref_ptr<osg::Group> rr = new osg::Group;
try {
osgEarth::initialize();
m_root = new osg::Group;
//m_root->addChild(osgDB::readNodeFile("../../vs2022_64bit_3rdParty_osg365_oe32/runtime/test/earthFile/china-simple.earth"));
//osg::ref_ptr<osg::Node> mp = osgDB::readNodeFile("../../vs2022_64bit_3rdParty_osg365_oe32/runtime/test/earth/TestCommon10/output.ive");
osg::ref_ptr<osg::Node> mp = osgDB::readNodeFile("../../vs2022_64bit_3rdParty_osg365_oe32/runtime/test/earthFile/china-simple.earth");
m_root->addChild(mp);
//注意:osgEarth::MapNode只能加载earth文件,加载会ive失败
m_mapNode = dynamic_cast<osgEarth::MapNode*>(mp.get());
}
catch(const std::exception& e) {
AfxMessageBox(CString("Failed to create osg::Group in constructor: ") + CString(e.what()));
throw std::runtime_error(std::string("Failed to create osg::Group in constructor: ") + e.what());
}
}
void COSGObject::InitCameraConfig()
{
RECT rect;
m_viewer = new osgViewer::Viewer;
//osg::ref_ptr<osgViewer::View> viewer = new osgViewer::Viewer;
//osg::ref_ptr<osgViewer::Viewer> m_vv = new osgViewer::Viewer;
::GetWindowRect(m_hWnd, &rect);
osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
osg::ref_ptr<osg::Referenced> winData = new osgViewer::GraphicsWindowWin32::WindowData(m_hWnd);
traits->x = 0;
traits->y = 0;
traits->width = rect.right - rect.left;
traits->height = rect.bottom - rect.top;
traits->windowDecoration = false;
traits->doubleBuffer = true;
traits->sharedContext = 0;
traits->setInheritedWindowPixelFormat = true;
traits->inheritedWindowData = winData;
osg::GraphicsContext* gc = osg::GraphicsContext::createGraphicsContext(traits);
osg::ref_ptr<osg::Camera> camera = new osg::Camera;
camera->setGraphicsContext(gc);
camera->setViewport(new osg::Viewport(traits->x, traits->y, traits->width, traits->height));
camera->setProjectionMatrixAsPerspective(30.0f, double(traits->width) / static_cast<double>(traits->height),
1.0f, 1000.f);
m_viewer->setCamera(camera);
//m_viewer->setCameraManipulator(new osgGA::TrackballManipulator);
m_viewer->setSceneData(m_root);
m_viewer->realize();
m_viewer->getCamera()->setComputeNearFarMode(osg::CullSettings::COMPUTE_NEAR_FAR_USING_BOUNDING_VOLUMES);
m_viewer->getCamera()->setNearFarRatio(0.000003f);
}
void COSGObject::PreFrameUpdate()
{
}
void COSGObject::PostFrameUpdate()
{
}
void COSGObject::Render(void* ptr)
{
COSGObject* osg = (COSGObject*)ptr;
osgViewer::Viewer* viewer = osg->GetViewer();
while (!viewer->done())
{
osg->PreFrameUpdate();
viewer->frame();
osg->PostFrameUpdate();
}
_endthread();
}
osgViewer::Viewer* COSGObject::GetViewer()
{
return m_viewer;
}
void COSGObject::InitOsgEarth()
{
//初始化操作器
m_em = new osgEarth::EarthManipulator;
if (m_mapNode.valid())
{
m_em->setNode(m_mapNode);
}
m_em->getSettings()->setArcViewpointTransitions(true);
m_viewer->setCameraManipulator(m_em);
//获取当前时间
m_nowTime = time(0);
m_tm = localtime(&m_nowTime);
osgEarth::DateTime currTime(m_nowTime);
osg::ref_ptr<osgEarth::Ephemeris> ephemeris = new osgEarth::Ephemeris;
//初始化天空
osgEarth::Util::SkyOptions skyOptions;
m_skyNode = osgEarth::SkyNode::create(skyOptions);
//osgEarth::Util::SkyOptions skyOptions;
osgEarth::Config skyConf;
double hours = skyConf.value("hours", 12.0);
m_skyNode->setName("skyNode");
m_skyNode->setEphemeris(ephemeris);
m_skyNode->setDateTime(currTime);
m_viewer->setLightingMode(osg::View::SKY_LIGHT);
m_skyNode->attach(m_viewer, 0);
m_skyNode->setLighting(true);
m_skyNode->addChild(m_mapNode);
m_root->addChild(m_skyNode);
//获取国界线图层
//m_chinaBoundaries = m_mapNode->getMap()->getImageLayerByName("china_boundaries");
osg::ref_ptr<osgEarth::Layer> layer = m_mapNode->getMap()->getLayerByName("china_boundaries");
if (layer)
{
auto imageLayer = dynamic_cast<osgEarth::ImageLayer*>(layer.get());
if (imageLayer)
{
m_chinaBoundaries = imageLayer;
}
}
setChinaBoundariesOpacity(1.0);
}
void COSGObject::initializeChinaBoundaries()
{
/*for (auto layer : m_mapNode->getMap()->getLayers())
{
if (layer && layer->getName() == "china_boundaries")
{
auto imageLayer = dynamic_cast<osgEarth::ImageLayer*>(layer.get());
if (imageLayer)
{
m_chinaBoundaries = imageLayer;
break;
}
}
}*/
}
void COSGObject::setChinaBoundariesOpacity(double opt)
{
if (m_chinaBoundaries)
{
m_chinaBoundaries->setOpacity(opt);
}
}
double COSGObject::getChinaBoundariesOpacity()
{
if (m_chinaBoundaries)
{
return m_chinaBoundaries->getOpacity();
}
else
{
return -1.0;
}
}
1180

被折叠的 条评论
为什么被折叠?



