OpenSceneGraph相机系统
一、相机的核心原理
Open Scene Graph(OSG)中相机的核心原理围绕视图变换和投影变换展开,结合场景图的层次化结构实现三维空间的动态渲染。
1、视图变换(View Transformation)
-
)视图矩阵的作用
视图矩阵将世界坐标系中的物体坐标转换为相机坐标系中的坐标。该矩阵由相机的位置、方向和朝向参数决定,本质上是将场景中的物体变换到以相机为原点的观察空间。- 例如,相机移动时,视图矩阵实时更新,确保场景物体相对于相机的正确空间关系。
-
)实现方式
在OSG中,osg::Camera类封装了视图矩阵的计算,通过设置相机的LookAt(视点、目标点、上方向)参数生成视图矩阵。
2、投影变换(Projection Transformation)
-
)投影矩阵的作用
投影矩阵将相机坐标系中的坐标转换到裁剪空间,定义视锥体(Frustum)的形状。视锥体决定了哪些物体可见,并完成透视/正交投影的转换26。- 透视投影:模拟人眼近大远小的效果,适用于自然场景。
- 正交投影:保持物体尺寸不变,常用于CAD等应用。
-
)视锥体裁剪优化
OSG利用场景图的包围体层次(BVH)结构,结合投影矩阵生成的视锥体,快速剔除不可见物体,减少渲染负载。
二、相机系统
OSG的相机系统是3D场景渲染的核心组件,提供了灵活的视图控制和渲染管线配置。
1. 相机基础类型
1.1 透视相机 (Perspective Camera)
// 创建透视相机
osg::Camera* createPerspectiveCamera(double fov, double aspect, double near, double far)
{osg::ref_ptr<osg::Camera> camera = new osg::Camera;camera->setProjectionMatrixAsPerspective(fov, aspect, near, far);camera->setViewMatrixAsLookAt(osg::Vec3(0,0,5), // 相机位置osg::Vec3(0,0,0), // 目标点osg::Vec3(0,1,0)); // 上方向camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);return camera.release();
}
1.2 正交相机 (Orthographic Camera)
// 创建正交相机
osg::Camera* createOrthoCamera(double left, double right, double bottom, double top, double near, double far)
{osg::ref_ptr<osg::Camera> camera = new osg::Camera;camera->setProjectionMatrixAsOrtho(left, right, bottom, top, near, far);camera->setViewMatrixAsLookAt(osg::Vec3(0,0,1), osg::Vec3(0,0,0), osg::Vec3(0,1,0));return camera.release();
}
2. 相机操作器 (Camera Manipulators)
2.1 内置操作器类型
// 设置轨迹球操作器 (默认)
viewer.setCameraManipulator(new osgGA::TrackballManipulator());// 飞行操作器
viewer.setCameraManipulator(new osgGA::FlightManipulator());// 驾驶操作器
viewer.setCameraManipulator(new osgGA::DriveManipulator());// 地形适配操作器
viewer.setCameraManipulator(new osgGA::TerrainManipulator());
2.2 自定义操作器
class CustomManipulator : public osgGA::CameraManipulator {
public:virtual void setByMatrix(const osg::Matrixd& matrix) override {_matrix = matrix;}virtual osg::Matrixd getMatrix() const override {return _matrix;}virtual osg::Matrixd getInverseMatrix() const override {return osg::Matrixd::inverse(_matrix);}virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) override {// 处理键盘鼠标事件switch(ea.getEventType()) {case osgGA::GUIEventAdapter::KEYDOWN:if(ea.getKey() == 'w') {_matrix.preMult(osg::Matrixd::translate(0,0,-0.1));return true;}break;// 其他事件处理...}return false;}private:osg::Matrixd _matrix;
};
3. 多相机配置
3.1 分屏视图
// 创建四视图分屏
void setupQuadView(osgViewer::Viewer& viewer)
{osg::GraphicsContext::WindowingSystemInterface* wsi = osg::GraphicsContext::getWindowingSystemInterface();unsigned width, height;wsi->getScreenResolution(osg::GraphicsContext::ScreenIdentifier(0), width, height);// 左上视图osg::ref_ptr<osg::Camera> camera1 = new osg::Camera;camera1->setViewport(0, height/2, width/2, height/2);camera1->setGraphicsContext(viewer.getCamera()->getGraphicsContext());viewer.addSlave(camera1.get(), false);// 右上视图osg::ref_ptr<osg::Camera> camera2 = new osg::Camera;camera2->setViewport(width/2, height/2, width/2, height/2);camera2->setGraphicsContext(viewer.getCamera()->getGraphicsContext());viewer.addSlave(camera2.get(), false);// 左下视图osg::ref_ptr<osg::Camera> camera3 = new osg::Camera;camera3->setViewport(0, 0, width/2, height/2);camera3->setGraphicsContext(viewer.getCamera()->getGraphicsContext());viewer.addSlave(camera3.get(), false);// 右下视图 (主相机)viewer.getCamera()->setViewport(width/2, 0, width/2, height/2);
}
3.2 HUD相机 (2D叠加)
osg::Camera* createHUDCamera(int width, int height)
{osg::ref_ptr<osg::Camera> camera = new osg::Camera;camera->setProjectionMatrix(osg::Matrix::ortho2D(0, width, 0, height));camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);camera->setViewMatrix(osg::Matrix::identity());camera->setClearMask(GL_DEPTH_BUFFER_BIT);camera->setRenderOrder(osg::Camera::POST_RENDER);camera->setAllowEventFocus(false);return camera.release();
}
4. 高级相机技术
4.1 渲染到纹理 (RTT)
osg::Texture2D* createRenderTexture(int width, int height)
{osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D;texture->setTextureSize(width, height);texture->setInternalFormat(GL_RGBA);texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR);texture->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR);return texture.release();
}osg::Camera* createRTTCamera(osg::Texture2D* texture)
{osg::ref_ptr<osg::Camera> camera = new osg::Camera;camera->setClearColor(osg::Vec4(0.1,0.1,0.3,1.0));camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);camera->setRenderOrder(osg::Camera::PRE_RENDER);camera->setViewport(0, 0, texture->getTextureWidth(), texture->getTextureHeight());camera->attach(osg::Camera::COLOR_BUFFER, texture);return camera.release();
}
4.2 后处理效果
osg::Camera* createPostProcessingCamera(osg::Texture2D* inputTexture)
{osg::ref_ptr<osg::Camera> camera = new osg::Camera;camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);camera->setClearMask(GL_DEPTH_BUFFER_BIT);camera->setRenderOrder(osg::Camera::POST_RENDER);// 创建全屏quadosg::ref_ptr<osg::Geode> geode = new osg::Geode;geode->addDrawable(osg::createTexturedQuadGeometry(osg::Vec3(-1,-1,0), osg::Vec3(2,0,0), osg::Vec3(0,2,0)));// 设置后处理着色器osg::ref_ptr<osg::Program> program = new osg::Program;program->addShader(osgDB::readShaderFile("postprocess.vert"));program->addShader(osgDB::readShaderFile("postprocess.frag"));osg::ref_ptr<osg::StateSet> stateset = geode->getOrCreateStateSet();stateset->setAttributeAndModes(program);stateset->setTextureAttributeAndModes(0, inputTexture);camera->addChild(geode);return camera.release();
}
5. 相机动画
5.1 路径动画
osg::AnimationPath* createCameraPath()
{osg::ref_ptr<osg::AnimationPath> path = new osg::AnimationPath;path->setLoopMode(osg::AnimationPath::LOOP);// 添加关键点path->insert(0.0, osg::AnimationPath::ControlPoint(osg::Vec3(0,0,5), osg::Quat()));path->insert(5.0, osg::AnimationPath::ControlPoint(osg::Vec3(5,0,5), osg::Quat(osg::PI_2, osg::Z_AXIS)));path->insert(10.0, osg::AnimationPath::ControlPoint(osg::Vec3(0,0,5), osg::Quat(osg::PI, osg::Z_AXIS)));return path.release();
}void setupCameraAnimation(osgViewer::Viewer& viewer)
{osg::ref_ptr<osg::AnimationPathCallback> apcb = new osg::AnimationPathCallback(createCameraPath());viewer.getCamera()->setUpdateCallback(apcb);
}
5.2 相机震动效果
class CameraShakeCallback : public osg::NodeCallback {
public:virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) {osg::Camera* camera = dynamic_cast<osg::Camera*>(node);if(camera && _shakeTime > 0) {float intensity = _shakeTime / _duration;osg::Vec3 offset((rand()%1000/500.0f-1) * intensity,(rand()%1000/500.0f-1) * intensity,0);osg::Matrix viewMatrix = camera->getViewMatrix();viewMatrix.setTrans(viewMatrix.getTrans() + offset);camera->setViewMatrix(viewMatrix);_shakeTime -= nv->getFrameStamp()->getSimulationTimeDelta();}traverse(node, nv);}void shake(float duration) {_duration = duration;_shakeTime = duration;}private:float _duration = 0;float _shakeTime = 0;
};
6. 相机性能优化
6.1 视锥体剔除
// 启用自动视锥体剔除
viewer.getCamera()->setCullingMode(viewer.getCamera()->getCullingMode() | osg::CullSettings::VIEW_FRUSTUM_CULLING);
6.2 小物体剔除
// 设置小物体剔除阈值 (像素)
viewer.getCamera()->setSmallFeatureCullingPixelSize(2.0f);
6.3 细节层次 (LOD)
// 相机距离相关的LOD设置
osg::LOD* createLODNode()
{osg::ref_ptr<osg::LOD> lod = new osg::LOD;lod->addChild(createHighDetailModel(), 0, 50); // 0-50米高细节lod->addChild(createMediumDetailModel(), 50, 100); // 50-100米中细节lod->addChild(createLowDetailModel(), 100, 1000); // 100-1000米低细节return lod.release();
}相关文章:
OpenSceneGraph相机系统
一、相机的核心原理 Open Scene Graph(OSG)中相机的核心原理围绕视图变换和投影变换展开,结合场景图的层次化结构实现三维空间的动态渲染。 1、视图变换(View Transformation) )视图矩阵的作用…...
KTH5772 系列游戏手柄摇杆专用3D 霍尔位置传感器
产品概述 KTH5772是一款专为游戏手柄上的摇杆应用而设计的3D霍尔磁感应芯片,主要面向对线性度、回报率、灵敏度、功耗要求严格的摇杆应用。KTH5772基于3D霍尔技术,内部分别集成了X轴、Y轴和Z轴三个独立的霍尔元件,能够通过测量和处理磁通密度…...
Soybean Admin 使用tv-focusable兼容电视TV端支持遥控器移动焦点
环境 window10 pnpm 8.15.4 node 8.15.4 vite 5.1.4 soybean admin: 1.0.0 native-ui: 2.38.0 vue-tv-focusable: 2.0.1 小米电视 MIUI TV版本:MiTV OS 2.7.1886(稳定版) 飞视浏览器:https://www.fenxm.com/1220.html这里必须使用飞视浏览器,…...
经济金融最优化:从理论到MATLAB实践——最大利润问题全解析
内容摘要 本文聚焦经济金融领域的最大利润问题,深入探讨不考虑销售影响和考虑销售影响两种情形下的利润最大化模型柯布 - 道格拉斯生产函数等理论构建与求解。 关键词:经济金融;最大利润问题;柯布-道格拉斯生产函数 1. 引言 在…...
大模型学习七:小米8闲置,直接安装ubuntu,并安装VNC远程连接手机,使劲造
一、说明 对于咱们技术人来说,就没有闲的蛋疼的时候,那不是现在机会来了 二、刷机器准备 1、申请解锁手机 申请解锁小米手机https://www.miui.com/unlock/download.html 下载工具,安装下面的步骤来,官网不欺人吧 打开开发者工…...
高可用之战:Redis Sentinal(哨兵模式)
参考:Redis系列24:Redis使用规范 - Hello-Brand - 博客园 1 背景 在我们的《Redis高可用之战:主从架构》篇章中,介绍了Redis的主从架构模式,可以有效的提升Redis服务的可用性,减少甚至避免Redis服务发生完…...
简单括号匹配_栈
课程笔记 10:数据结构(清华) 栈_opnd push-CSDN博客 括号匹配。对于一个表达式,要想确认其中所使用的括号是否匹配,可以采用减而治之的思路,将每对邻近括号消去,则剩下的达式括号匹配当且仅当…...
CSS Grid布局:从入门到放弃再到真香
Flexbox 与 Grid 布局:基础概念与特点 Flexbox Flexbox(Flexible Box Layout),即弹性盒布局模型,主要用于创建一维布局,能够轻松实现元素在一行或一列中的排列、对齐与分布。通过display: flex属性启用 Fl…...
Springboot把外部jar包打包进最终的jar包,并实现上传服务器
1、创建lib目录,把jar包放进这个目录下,然后标记lib目录为“资源根路径”(鼠标右键lib目录->将目录标记为->资源根路径。之后lib文件夹会有如下的图标变化) 文件结构如下: 2、pom文件添加依赖 <dependency…...
仿照管理系统布局配置
1.vue仿照snowy 配置,如下图: 2.代码实现 <template><div class"theme-settings"><!-- 导航栏 --><div class"nav-bar"><el-breadcrumb separator"/"><el-breadcrumb-item>导航设置…...
A2L文件解析
目录 1 摘要2 A2L文件介绍2.1 A2L文件作用2.2 A2L文件格式详解2.2.1 A2L文件基本结构2.2.2 关键元素与声明2.2.3 完整A2L文件示例 3 总结 1 摘要 A2L文件(也称为ASAP2文件)是ECU开发的核心接口文件,用于标定、测量和诊断的关键配置文件&…...
GPT - 因果掩码(Causal Mask)
本节代码定义了一个函数 causal_mask,用于生成因果掩码(Causal Mask)。因果掩码通常用于自注意力机制中,以确保模型在解码时只能看到当前及之前的位置,而不能看到未来的信息。这种掩码在自然语言处理任务(如…...
SpringBoot 数据库MySql的读写分离 多数据源 Shardingsphere高并发优化
介绍 传统的 MySQL 架构中,所有的数据库操作(包括读操作和写操作)都在同一个数据库实例上进行。随着应用程序的规模增长,单一数据库实例可能会成为瓶颈,无法满足高并发的需求。为了优化性能,可以将数据库的…...
适合工程建筑行业的OA系统有什么推荐?
工程行业具有项目周期长、协作链条复杂等特性,传统管理模式下的 “人治”“纸质化” 弊端日益凸显。OA 系统作为数字化管理的核心载体,通过流程标准化、数据可视化,精准解决工程行业项目管理核心痛点。 泛微 e-office 深度聚焦工程场景&#…...
如何使用 DeepSeek 帮助自己的工作?
1. 信息检索 信息检索是获取特定信息的过程,尤其是在大量数据或文本中查找相关内容。这个过程应用广泛,从网页搜索引擎到数据库查询,再到企业内部信息系统。在使用 DeepSeek 或其它类似工具进行信息检索时,可以考虑以下几个重要方…...
python对mysql数据库的操作
现在遇到一个问题如何将数据批量的插入mysql数据库中 基础操作 import asyncio from config import config from mysql_pool import MysqlPoolclass MysqlLoop(object):def __init__(self):self.logger config.loggerself.pool MysqlPool()def loop_query(self, queries):lo…...
MFC案例:利用CFileDialog类选择多个文件的实验
在MFC项目中使用CFileDialog打开文件时,一般的使用场景是选择一个文件,今天我们做一个选择多个文件的实验,运行环境是VS2022。 实验目标:在基于对话框的MFC项目中,通过调用CFileDialog类对象,将选择…...
深入解析栈回溯技术:如何通过异常处理精准定位程序崩溃点
一、栈回溯 1.1 栈回溯的原理 调试程序时,经常发生这类错误: 1.读写某个地址,导致程序崩溃 2.调用某个空函数,导致程序崩溃在异常处理函数中,可以打印出”发生错误瞬间”的所有寄存器。 我们调试时,可以…...
封装uniapp request promise化
uniapp request 封装 一、 封装方法1. 使用 promis 封装 request2. 封装 api 在 api.js3.在要请求的页面 调用 api 一、 封装方法 1. 使用 promis 封装 request const BASE_URL 你的url接口 //比如 http://198.12.3.3/pzexport function request(config {}){let {url,dat…...
重构居家养老安全网:从 “被动响应” 到 “主动守护”
随着全球老龄化加剧,居家养老安全成为社会关注的核心议题。 传统养老模式依赖人工巡检或单一传感器,存在响应滞后、隐私泄露、场景覆盖不足等问题。 由此智绅科技应运而生,七彩喜智慧养老系统构筑居家养老安全网。 而物联网(Io…...
深入理解 GLOG_minloglevel 与 GLOG_v:原理与使用示例
文章目录 深入理解 GLOG_minloglevel 与 GLOG_v:原理与使用示例1. GLOG_minloglevel:最低日志等级控制2. GLOG_v:控制 VLOG() 的详细输出等级3. GLOG_minloglevel 与 GLOG_v 的优先级关系4. 使用示例4.1 基础示例:不同日志等级4.2…...
Unity6下架中国区,团结引擎接棒:这是分裂,还是本地化的开始?
就在近日,一则消息在国内游戏开发圈内迅速传播开来:Unity 6 及其后续版本已在中国大陆及港澳地区下架。这意味着,未来中国用户将无法直接使用 Unity 最新的主线版本。而取而代之的,是由 Unity 中国主导推出的本地化产品 —— 团结…...
ESP8266水位监测以及温湿度数据采集
上面就是ESP8266的引脚图,水温检测使用的是水位监测传感器,温湿度测量使用的是DHT11,DHT11的反应时间是2秒,这里要注意。开发采用Arduino程序 1. 传感器初始化 功能:初始化DHT11温湿度传感器和串口通信。 代码实现&…...
国产信创数据库:PolarDB 分布式版 V2.0,支持集中分布式一体化
阿里云PolarDB数据库管理软件(分布式版)V2.0 ,安全可靠的集中分布式一体化数据库管理软件。点此查看详情https://www.aliyun.com/activity/database/polardbx-v2?spma2c6h.13046898.publish-article.8.44146ffaE0lEWT 立即咨询专家…...
iOS按键精灵辅助工具在游戏开发中的创新应用
一、iOS自动化测试辅助工具 在移动游戏开发领域,iOS按键精灵类辅助工具不同于传统的安卓自动化方案,iOS环境下的自动化测试面临更严峻的技术挑战,但通过创新方法仍可实现精准控制。 # 基于图像识别的智能定位算法示例 def find_button(butt…...
淘宝 API 与 AI 图像识别整合:开启商品主图智能解析新时代
在电商蓬勃发展的当下,淘宝作为行业巨头,承载着海量的商品信息。如何让买家更高效地筛选心仪好物,让卖家精准把握商品展示要点?淘宝 API 与 AI 图像识别技术的整合为这一难题提供了创新性解法,实现对商品主图实时解析&…...
Axure PR 9 中继器 09 删除行
大家好,我是大明同学。 接着上期的内容,这期内容,我们来了解一下Axure中继器数据表删除行交互设计。 预览地址:https://vvlmqu.axshare.com 删除行 1.打开上期RP 文件,设计一个删除弹窗元件, 创建为动态面…...
HDCP(五)
HDCP 2.2 测试用例设计详解 基于HDCP 2.2 CTS v1.1规范及协议核心机制,以下从正常流程与异常场景两大方向拆解测试用例设计要点,覆盖认证、密钥管理、拓扑验证等关键环节: 1. 正常流程测试 1.1 单设备认证 • 测试目标:验证源设…...
商城APP打包教程
下载 HBuilderX 工具 HBuilderX支持插件拓展功能。App开发版已集成相关插件、开箱即用 根据自身电脑系统选择对应软件下载,建议选择APP开发版 2. 下载好软件安装后打开 建议直接在uniapp插件页面一键导入,正常情况下uniapp插件都是最新的,大家…...
Spring 框架的核心基础:IoC 和 AOP
一、IoC(Inversion of Control,控制反转) 定义: IoC(Inversion of Control,控制反转),就是把对象创建和依赖关系的管理交给 Spring 容器,而不是由程序员手动去创建对象…...
