当前位置:网站首页>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;
}
截图
轴测视图下,正方体,未计算正确远近平面

手动计算了远近平面后

边栏推荐
- Redis does web page UV statistics
- 【Dart】dart之mixin探究
- 4.1 配置Mysql与注册登录模块
- Multithreaded producers and consumers
- 油猴hook小脚本
- 有用的网站
- 泰德制药董事长郑翔玲荣膺“2022卓越影响力企业家奖” 泰德制药荣获“企业社会责任典范奖”
- [Energy Conservation Institute] Ankerui Food and Beverage Fume Monitoring Cloud Platform Helps Fight Air Pollution
- 【社媒营销】如何知道自己的WhatsApp是否被屏蔽了?
- STAHL触摸屏维修一体机显示屏ET-316-TX-TFT常见故障
猜你喜欢

Debug一个ECC的ODP数据源

因斯布鲁克大学团队量子计算硬件突破了二进制
![58: Chapter 5: Develop admin management services: 11: Develop [admin face login, interface]; (not measured) (using Ali AI face recognition) (demonstrated, using RestTemplate to implement interface cal](/img/ab/1c0adeb344329e28010b6ffda5389d.png)
58: Chapter 5: Develop admin management services: 11: Develop [admin face login, interface]; (not measured) (using Ali AI face recognition) (demonstrated, using RestTemplate to implement interface cal

Get started quickly with MongoDB

第58章 结构、纪录与类

【多任务优化】DWA、DTP、Gradnorm(CVPR 2019、ECCV 2018、 ICML 2018)

9月备考PMP,应该从哪里备考?

Buttons with good user experience should not have hover state on mobile phones

Wildcard SSL/TLS certificate

【多任务学习】Modeling Task Relationships in Multi-task Learning with Multi-gate Mixture-of-Experts KDD18
随机推荐
我的驾照考试笔记(3)
New graduate students, great experience in reading English literature, worthy of your collection
Interview assault 70: what is the glue bag and a bag?How to solve?
如何记录分析你的炼丹流程—可视化神器Wandb使用笔记【1】
[Energy Conservation Institute] Ankerui Food and Beverage Fume Monitoring Cloud Platform Helps Fight Air Pollution
Godaddy域名解析速度慢问题以及如何使用DNSPod解析解决
Buttons with good user experience should not have hover state on mobile phones
Redis does check-in statistics
LTE time domain and frequency domain resources
【Untitled】
【节能学院】数据机房中智能小母线与列头柜方案的对比分析
不同的操作加不同的锁详解
虚拟机的IP地址自动变为127.0.0.1
密码学的基础:X.690和对应的BER CER DER编码
[Personal work] Wireless network image transmission module
面试突击70:什么是粘包和半包?怎么解决?
Go 语言中常见的坑
The Internet giant development process
[Multi-task learning] Modeling Task Relationships in Multi-task Learning with Multi-gate Mixture-of-Experts KDD18
Use WeChat official account to send information to designated WeChat users