当前位置:网站首页>OSG Notes: Set DO_NOT_COMPUTE_NEAR_FAR to manually calculate far and near planes
OSG Notes: Set DO_NOT_COMPUTE_NEAR_FAR to manually calculate far and near planes
2022-08-01 20:33:00 【shanql】
问题
When implementing a joystick for orthographic projection,缩放平移后,A situation where a graphics part message is generated.没研究透osgAutomatic calculation algorithm,For the time being, I think that the automatic calculation of the far and near planes may not be a problem for perspective projection,But the orthographic projection does.
思路(记录下,Not strictly scrutinized,不保证正确性)
left, right, top, bottomUse the radius of the model to enclose the sphere.The distance idea between the far and near planes is shown in the figure below,zHalf the length of the shaft shall be taken as the maximum possible length(That is, the distance from the viewpoint along the line of sight to the other side of the bounding box),This will ensure how to rotate the model,The models are all within the observation range with the eye as the coordinate origin.
代码
#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; //Corrects near and far planes
}
//Calculate the eye-to-viewpoint distance using the joystick's viewing matrix,The result of using the camera is wrong
// 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)//Scaling of orthographic projections
{
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 //Corrects near and far planes
{
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();
//Far and near planes are not automatically calculated
pViewer->getCamera()->setComputeNearFarMode(
osg::CullSettings::ComputeNearFarMode::DO_NOT_COMPUTE_NEAR_FAR);
//Set a default projection range
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;
}
截图
Axonometric view,正方体,Correct near and far planes are not calculated
After manually calculating the far and near planes
边栏推荐
- Software you should know as a programmer
- 油猴hook小脚本
- 任务调度线程池-应用定时任务
- 【luogu P1912】诗人小G(二分栈)(决策单调性优化DP)
- Go 语言中常见的坑
- 用户身份标识与账号体系实践
- Buttons with good user experience should not have hover state on mobile phones
- idea插件generateAllSetMethod一键生成set/get方法以及bean对象转换
- 【kali-信息收集】(1.3)探测网络范围:DMitry(域名查询工具)、Scapy(跟踪路由工具)
- latex paper artifact -- server deployment overleaf
猜你喜欢
基于FPGA的任意字节数(单字节、多字节)的串口(UART)发送(含源码工程)
Godaddy域名解析速度慢问题以及如何使用DNSPod解析解决
【社媒营销】如何知道自己的WhatsApp是否被屏蔽了?
Little data on how to learn?Jida latest small learning data review, 26 PDF page covers the 269 - page document small data learning theory, method and application are expounded
Fork/Join线程池
【节能学院】安科瑞餐饮油烟监测云平台助力大气污染攻坚战
【无标题】
Remove 360's detection and modification of the default browser
【nn.Parameter()】生成和为什么要初始化
9月备考PMP,应该从哪里备考?
随机推荐
【Untitled】
作为程序员你应该会的软件
Custom command to get focus
虚拟机的IP地址自动变为127.0.0.1
excel高级绘图技巧100讲(二十二)-如何对不规则数据进行分列
Oracle排序某个字段, 如果这个varchar2类型的字段有数字也有文字 , 怎么按照数字大小排序?
微信小程序云开发|个人博客小程序
Goroutine Leaks - The Forgotten Sender
【kali-信息收集】(1.2)SNMP枚举:Snmpwalk、Snmpcheck;SMTP枚举:smtp-user-enum
Redis 做签到统计
为什么限制了Oracle的SGA和PGA,OS仍然会用到SWAP?
What is the difference between a utility model patent and an invention patent?Understand in seconds!
Redis 做网页UV统计
大整数相加,相减,相乘,大整数与普通整数的相乘,相除
【节能学院】数据机房中智能小母线与列头柜方案的对比分析
【节能学院】安科瑞餐饮油烟监测云平台助力大气污染攻坚战
【ES】ES2021 我学不动了,这次只学 3 个。
【个人作品】无线网络图传模块
Convolutional Neural Network (CNN) mnist Digit Recognition - Tensorflow
研究生新同学,牛人看英文文献的经验,值得你收藏