当前位置:网站首页>OSG笔记:设置DO_NOT_COMPUTE_NEAR_FAR,手动计算远近平面
OSG笔记:设置DO_NOT_COMPUTE_NEAR_FAR,手动计算远近平面
2022-08-01 20:31:00 【shanql】
问题
实现正交投影的操作杆时,缩放平移后,会产生图形部分消息的情况。没研究透osg自动计算算法,暂时认为自动计算远近平面对透视投影可能没啥问题,但正交投影则有。
思路(记录下,没有严格推敲,不保证正确性)
left, right, top, bottom使用模型包围球的半径即可。远近平面的距离思路如下图所示,z轴一半的长度需取最大可能的长度(即视点沿着视线到包围盒另一侧的距离),这样才能保证怎么旋转模型,模型都在以眼睛为坐标原点的观察范围内。
代码
#include <iostream>
#include <osgViewer/Viewer>
#include <osg/Group>
#include <osg/ShapeDrawable>
#include <osgGA/GUIEventHandler>
#include <osg/Viewport>
#include <osg/NodeCallback>
#include <osgGA/StandardManipulator>
#include <osgGA/EventVisitor>
using namespace std;
class MyGUIEventHandler : public osgGA::GUIEventHandler
{
public:
virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa,
osg::Object* pObject, osg::NodeVisitor* pNodeVisitor)
{
osgViewer::Viewer* pViewer = dynamic_cast<osgViewer::Viewer*>(aa.asView());
if (!pViewer || !pViewer->getSceneData() )
{
return false;
}
osg::ref_ptr<osg::Camera> pCamera = pViewer->getCamera();
if (!pCamera)
{
return false;
}
osg::Viewport* pViewport = pCamera->getViewport();
if (!pViewport)
{
return false;
}
osgGA::StandardManipulator* pManipulator = dynamic_cast<osgGA::StandardManipulator*>(
pViewer->getCameraManipulator());
if (!pManipulator)
{
return false;
}
double aspecRadio = double(pViewport->width()) / double(pViewport->height());
osg::BoundingSphere modelBound = pViewer->getSceneData()->getBound();
double dModelHalfSize = modelBound.radius();
static double s_dScale = 1.0;
switch (ea.getEventType())
{
case osgGA::GUIEventAdapter::EventType::KEYDOWN:
{
bool bZoom = false;
if (int(osgGA::GUIEventAdapter::KeySymbol::KEY_R) == ea.getKey())
{
s_dScale = 1.0; //恢复
bZoom = true;
}
else if (int(osgGA::GUIEventAdapter::KeySymbol::KEY_D) == ea.getKey())
{
s_dScale *= 1.2; //缩小
bZoom = true;
}
else if (int(osgGA::GUIEventAdapter::KeySymbol::KEY_U) == ea.getKey())
{
s_dScale *= 0.8;//放大
bZoom = true;
}
else
{
bZoom = false; //修正远近平面
}
//计算眼睛到视点距离使用操作杆的观察矩阵,使用相机的结果不对
// osg::Vec3d eye0;
// osg::Vec3d center0;
// osg::Vec3d up0;
// pCamera->getViewMatrixAsLookAt(eye0, center0, up0);
// double dDistance0 = (eye0 - center0).length();
double left = 0.0;
double right = 0.0;
double bottom = 0.0;
double top = 0.0;
double zNear = 0.0;
double zFar = 0.0;
if (pViewer->getCamera()->getProjectionMatrixAsOrtho(left, right, bottom, top, zNear, zFar))
{
//正交投影
osg::Vec3d eye1;
osg::Vec3d center1;
osg::Vec3d up1;
pManipulator->getTransformation(eye1, center1, up1);
double dDistance1 = (eye1 - center1).length();
double dDistance2 = (center1 - modelBound.center()).length();
std::cout << "dDistance1:" << dDistance1
<< ", dDistance2:" << dDistance2 << std::endl;
if (bZoom)//正交投影的缩放
{
double dHalfRange = dModelHalfSize * s_dScale;
if (aspecRadio > 1.0)
{
pViewer->getCamera()->setProjectionMatrixAsOrtho(
-dHalfRange*aspecRadio, dHalfRange*aspecRadio,
-dHalfRange, dHalfRange, zNear * s_dScale, zFar * s_dScale);
}
else
{
pViewer->getCamera()->setProjectionMatrixAsOrtho(
-dHalfRange, dHalfRange,
-dHalfRange*aspecRadio, dHalfRange*aspecRadio,
zNear * s_dScale, zFar * s_dScale);
}
}
else //修正远近平面
{
double dHalfRangeZ = dDistance1 + dDistance2 + dModelHalfSize*0.7;
pViewer->getCamera()->setProjectionMatrixAsOrtho(
left, right, bottom, top, -dHalfRangeZ, dHalfRangeZ);
}
}
break;
}
}
return osgGA::GUIEventHandler::handle(ea, aa, pObject, pNodeVisitor);
}
};
int main(int argc, char** argv)
{
osgViewer::Viewer* pViewer = new osgViewer::Viewer();
osg::ref_ptr<osg::Group> pRoot = new osg::Group();
osg::ref_ptr<osg::Geode> pGeode = new osg::Geode();
pRoot->addChild(pGeode);
osg::ref_ptr<osg::Box> pBox = new osg::Box(osg::Vec3(0, 0, 0), 100.0);
pGeode->addDrawable(new osg::ShapeDrawable(pBox));
const osg::BoundingSphere& boundingSphere = pRoot->getBound();
pViewer->addEventHandler(new MyGUIEventHandler());
pViewer->setSceneData(pRoot);
pViewer->getCamera()->setClearColor(osg::Vec4(0, 0, 0, 1.0));
pViewer->setUpViewInWindow(450, 220, 720, 450);
pViewer->realize();
//不自动计算远近平面
pViewer->getCamera()->setComputeNearFarMode(
osg::CullSettings::ComputeNearFarMode::DO_NOT_COMPUTE_NEAR_FAR);
//设置个默认的投影范围
const osg::Viewport* pViewport = pViewer->getCamera()->getViewport();
if (pViewport)
{
double dHalfRange = 100;
double aspecRadio = double(pViewport->width()) / double(pViewport->height());
if (aspecRadio > 1.0)
{
pViewer->getCamera()->setProjectionMatrixAsOrtho(
-dHalfRange*aspecRadio, dHalfRange*aspecRadio,
-dHalfRange, dHalfRange, -dHalfRange, dHalfRange);
}
else
{
pViewer->getCamera()->setProjectionMatrixAsOrtho(
-dHalfRange, dHalfRange,
-dHalfRange*aspecRadio, dHalfRange*aspecRadio, -dHalfRange, dHalfRange);
}
}
//aspecRadio
pViewer->run();
return 0;
}
截图
轴测视图下,正方体,未计算正确远近平面
手动计算了远近平面后
边栏推荐
- Interview assault 70: what is the glue bag and a bag?How to solve?
- 【节能学院】数据机房中智能小母线与列头柜方案的对比分析
- 【无标题】
- 【Untitled】
- 微信小程序云开发|个人博客小程序
- 密码学的基础:X.690和对应的BER CER DER编码
- What is the difference between a utility model patent and an invention patent?Understand in seconds!
- deploy zabbix
- Failed to re-init queues : Illegal queue capacity setting (abs-capacity=0.6) > (abs-maximum-capacity
- [Multi-task model] Progressive Layered Extraction: A Novel Multi-Task Learning Model for Personalized (RecSys'20)
猜你喜欢
Debug一个ECC的ODP数据源
[Multi-task optimization] DWA, DTP, Gradnorm (CVPR 2019, ECCV 2018, ICML 2018)
解除360对默认浏览器的检测与修改
【节能学院】安科瑞餐饮油烟监测云平台助力大气污染攻坚战
【nn.Parameter()】生成和为什么要初始化
【kali-信息收集】(1.2)SNMP枚举:Snmpwalk、Snmpcheck;SMTP枚举:smtp-user-enum
】 【 nn. The Parameter () to generate and why do you want to initialize
【多任务学习】Modeling Task Relationships in Multi-task Learning with Multi-gate Mixture-of-Experts KDD18
Application of Acrel-5010 online monitoring system for key energy consumption unit energy consumption in Hunan Sanli Group
XSS range intermediate bypass
随机推荐
kingbaseV8R3和postgreSQL哪个版本最接近?
Failed to re-init queues : Illegal queue capacity setting (abs-capacity=0.6) > (abs-maximum-capacity
C语言实现-直接插入排序(带图详解)
终于有人把AB实验讲明白了
[Multi-task learning] Modeling Task Relationships in Multi-task Learning with Multi-gate Mixture-of-Experts KDD18
专利检索常用的网站有哪些?
Software you should know as a programmer
myid file is missing
Wildcard SSL/TLS certificate
洛谷 P2440 木材加工
The graphic details Eureka's caching mechanism/level 3 cache
【kali-信息收集】(1.5)系统指纹识别:Nmap、p0f
Where should I prepare for the PMP exam in September?
Does LabVIEW really close the COM port using VISA Close?
线程池处理异常的方法
nacos installation and configuration
Which websites are commonly used for patent searches?
Digital twin Beijing the imperial palace, yuan universe is the process of tourism
Fork/Join线程池
【节能学院】安科瑞餐饮油烟监测云平台助力大气污染攻坚战