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

手动计算了远近平面后

边栏推荐
猜你喜欢
随机推荐
【Social Media Marketing】How to know if your WhatsApp is blocked?
系统收集集
vant实现Select效果--单选和多选
字符串
卷积神经网络(CNN)mnist数字识别-Tensorflow
Go Atomic
线程池处理异常的方法
瀚高数据导入
【torch】张量乘法:matmul,einsum
Does LabVIEW really close the COM port using VISA Close?
【kali-信息收集】(1.3)探测网络范围:DMitry(域名查询工具)、Scapy(跟踪路由工具)
多线程之生产者与消费者
【Dart】dart构造函数学习记录(含dart单例模式写法)
我的驾照考试笔记(2)
【无标题】
Zheng Xiangling, Chairman of Tide Pharmaceuticals, won the "2022 Outstanding Influential Entrepreneur Award" Tide Pharmaceuticals won the "Corporate Social Responsibility Model Award"
二维、三维、四维矩阵每个维度含义解释
终于有人把AB实验讲明白了
Creo5.0 rough hexagon is how to draw
XSS range intermediate bypass









