osg操纵器解析

OSG 多视图 实现导航拖拽器 OSG基于多视图实现的导航器。 阅读详情

转载自:http://lzchenheng.blog.163.com/blog/static/8383353620106710534514/

 osg操纵器是我们实现场景漫游的主要手段,osg提供了驾驶操纵器、飞行操纵器、轨迹球操纵器等,这些操纵器的基类为osgGA::MatrixManipulator,有时为了漫游的需要,我们需要编写自己的操纵器,要想编写好自己的操纵器,必须对osg操纵器的实现方式进行剖分,知道其实现的机理,才能有的放矢,编写一个“听话”的操纵器,下面我们从源代码入手,对操纵器的实现进行剖分。

      设置操纵器的代码为:viewer->setCameraManipulator(),其中setCameraManipulator()的代码如下:

      void View::setCameraManipulator(osgGA::MatrixManipulator* manipulator)
     {
           _cameraManipulator = manipulator;
    
          if (_cameraManipulator.valid())
          {
                    _cameraManipulator->setCoordinateFrameCallback(new ViewerCoordinateFrameCallback(this));

                    //得到场景的根节点

                    if (getSceneData()) _cameraManipulator->setNode(getSceneData());
                    //得到当前事件适配器
                    osg::ref_ptr<osgGA::GUIEventAdapter> dummyEvent = _eventQueue->createEvent();

                    //执行home

                     _cameraManipulator->home(*dummyEvent, *this);
           }
      }

      在这段代码中,首先得到根节点,调用setNode()方法给操纵器设置根节点,然后调用操纵器本身的home方法,osgGA::MatrixManipulator类的home()和setNode()方法为一个虚方法,其实现在其派生类中,我们看一下TrackballManipulator类的实现方式。

      我们先来看一下setNode()方法的代码:

      void TrackballManipulator::setNode(osg::Node* node)
      {
           _node = node;
           if (_node.get())
           {
                //得到根节点包围球的范围

                const osg::BoundingSphere& boundingSphere=_node->getBound();
                 _modelScale = boundingSphere._radius;
           }
           //是否自动计算视点的位置

           if (getAutoComputeHomePosition()) computeHomePosition();
      }  
      该方法主要得到根节点的包围球范围,然后计算视点的位置。

      那么我们来看一下home方法在做什么

       void TrackballManipulator::home(double /*currentTime*/)
       {
              //自动计算

               if (getAutoComputeHomePosition()) computeHomePosition();
               //计算视点的位置

               computePosition(_homeEye, _homeCenter, _homeUp);
              _thrown = false;
       }

       在osgGA::MatrixManipulator类中,相关的参数如下:

       MatrixManipulator::MatrixManipulator()
       {
           _minimumDistance = 0.001;
    
          _intersectTraversalMask = 0xffffffff;

          //自动计算

          _autoComputeHomePosition = true;
          //视点的默认位置
          _homeEye.set(0.0,-1.0,0.0);
          _homeCenter.set(0.0,0.0,0.0);
          _homeUp.set(0.0,0.0,1.0);
     }

     由于_autoComputeHomePosition = true,所以,首先执行 computeHomePosition()方法,该方法在MatrixManipulator类中实现如下:

        virtual void computeHomePosition()
        {
            if(getNode())  //如果根节点存在
            {
               //计算根节点的包围球

               const osg::BoundingSphere& boundingSphere=getNode()->getBound();

               //根据根节点包围球的大小,设置视点位置

                setHomePosition(boundingSphere._center+osg::Vec3( 0.0,-3.5f * boundingSphere._radius,0.0f),
                                boundingSphere._center,
                                osg::Vec3(0.0f,0.0f,1.0f),
                                _autoComputeHomePosition);
            }
        }

        setHomePosition()方法的实现如下:

         virtual void setHomePosition(const osg::Vec3d& eye, const osg::Vec3d& center, const osg::Vec3d& up,

                                                          bool autoComputeHomePosition=false)
            {
                  setAutoComputeHomePosition(autoComputeHomePosition);
                  _homeEye = eye;
                  _homeCenter = center;
                  _homeUp = up;
            }
            下面我们再看一下computePosition()方法的实现:

            void TrackballManipulator::computePosition(const osg::Vec3& eye,const osg::Vec3& center,const osg::Vec3& up)
            {

                 //生成观察坐标系

                 osg::Vec3 lv(center-eye);

                  osg::Vec3 f(lv);
                  f.normalize();
                  osg::Vec3 s(f^up);
                  s.normalize();
                  osg::Vec3 u(s^f);
                  u.normalize();
                  //建立观察旋转矩阵
                  osg::Matrix rotation_matrix(  s[0],     u[0],     -f[0],     0.0f,
                                                           s[1],     u[1],     -f[1],     0.0f,
                                                           s[2],     u[2],     -f[2],     0.0f,
                                                            0.0f,     0.0f,     0.0f,      1.0f);
                   
                  _center = center;
                 _distance = lv.length();
                _rotation = rotation_matrix.getRotate().inverse();
           }
           从以上的代码可以看出,要编写一个好的操纵器,必须首先重载setNode()和home()方法,根据根节点的包围球,确定视点的初始位置,然后,根据视点的初始位置和用户的操作(移动、旋转等操作),重载getInverseMatrix()和getMatrix()方法,构建观察矩阵或物体的位置姿态矩阵,这两个矩阵互为逆矩阵。

          场景在更新遍历时,不再调用操纵器的setCameraManipulator()方法,该方法只能在初始时设置,场景在每次更新遍历时,只调用getInverseMatrix()方法获取观察矩阵,更新相机的姿态、位置,实现场景的漫游,如下代码所示:

void Viewer::updateTraversal()
{
    ...........

      if (_cameraManipulator.valid())
     {
            setFusionDistance( getCameraManipulator()->getFusionDistanceMode(),
                            getCameraManipulator()->getFusionDistanceValue() );

            //得到操纵器的观察矩阵,更新相机

            _camera->setViewMatrix(_cameraManipulator->getInverseMatrix());
      }

    ...............................

}


osg视图操作关于Manipulator 想看干货,还是FreeSouth总结的东西,写的很全 http://www.d3dweb.com/Documents/201203/31-22251384929.html以下是我自己项目的记录及碎碎念,为了梳理和加深印象: 1.KeySwitchMatrixManipulator类可以看做一个各类操作器的管理类,用按键来切换这些操作器。比如‘1’会被切换到TrackBall‘2’会被切换到Dri 阅读详情

相关推荐

osgEarth在地图里读取飞机模型

一、思路 先设置地图节点,把.earth地图文件读取到地图节点里,然后再创建一个模型节点,读取.osg模型文件进入模型节点,并通过computeLocalToWorldTransformFromLatLongHeight函数设置模型出现的坐标及高度,最终显示 二、代码 earth+model.cpp文件 //https://blog.youkuaiyun.com/trevor_k/article/details/102643849?utm_source=app&app_version=4.5.0

ljjjjjjjjjjj的博客 4478

osg中漫游器的原理(一)

对osg中漫游器的解析,从中可以了解到漫游器的添加、更新、处理和自定义自己漫游器的方式

Frank的专栏 1万+

OSG三维渲染引擎编程学习之五:“第一章:OSG介绍” 之 “1.5 OSG模块”

第一章:OSG介绍;1.5 OSG模块

LuckyHanMo的博客 1502

OSG中获取任一时刻相机的位置

就是在有漫游器的程序中获取相机任一时刻的位置,有时使用漫游器漫游时需要

7344

3、建筑信息模型(BIM)与增强现实(AR)、虚拟现实(VR)、混合现实(MR)集成技术解析

本文深入解析了建筑信息模型(BIM)与增强现实(AR)、虚拟现实(VR)和混合现实(MR)技术的集成应用。重点探讨了这些技术在建筑生命周期不同阶段(设计、施工、运营)的应用分布、技术方法及优势特点,同时分析了其局限性与未来发展趋势。通过对比分析,展示了BIM与AR、VR、MR集成技术的各自优势和挑战,并展望了技术融合深化、标准化推进及设备性能提升等未来发展方向。

web39explorer的博客 273

告别 RPA 和 Selenium,MCP + Playwright 成为自动化开发新宠!

摘要: 随着数字化转型加速,传统自动化工具(如RPA和Selenium)在复杂场景中暴露出开发成本高、灵活性不足等问题。新一代解决方案MCP(Model Context Protocol)与Playwright的结合,通过AI与自动化的无缝对接,实现了智能化的任务处理。MCP支持自然语言交互和上下文感知,开发者无需编写复杂代码即可生成自动化脚本;Playwright则提供多浏览器支持、高性能和易用性。二者结合显著提升开发效率,使自动化更智能、灵活。文章还对比了VS Code与Trae中配置Playwrigh

我先测了 2209

osg示例程序解析之osgterrain

2010-07-10 11:30:38|  分类: osg开发|字号 订阅 该示例程序主要讲述如何绘制地形,该示例程序在main()函数中首先定义操纵器,并将定义的操纵器添加到osgGA::KeySwitchMatrixManipulator类中,实现按数字键切换不同的操纵器,主要代码如下: //设置切换操纵器  osg::ref_ptr keyswitchM

llw01的专栏 5309

告别Godot默认编辑器:手把手教你用VSCode配置C#开发环境(附中文注释避坑指南)

本文详细介绍了如何将VSCode配置为Godot引擎的C#开发环境,提升游戏开发效率。从环境准备、扩展配置到解决中文编码问题,提供完整的避坑指南和高级调试技巧,帮助开发者充分利用VSCode的智能补全和调试功能,打造高效工作流。

weixin_30596023的博客 189

OSG能够在当前帧截图,也就是能转换视角后马上截图

#include <Windows.h> #include <osg/GraphicsContext> #include <osg/Group> #include <osg/Node> #include <osg/Geode> #include <osgViewer/Viewer> #include ...

dianxiaochuang7777的博客 601

图的一些基本知识:图,邻居,度矩阵,邻接矩阵

目录前言图(graph)邻居(neighborhood)度矩阵(degree)邻接矩阵(adjacency)参考文献 前言       本文介绍了一些图论的基础知识,包括图的表示、邻接矩阵、度矩阵等(边不带权值的情况),本文中某些图片或者知识的参考/来源已列于本文最后。 图(graph)       图用G=(V, E)表示,V中元素为...

luzaijiaoxia0618的博客 6万+

SAP 物料的分割评估

SAP 物料的分割评估 前言 本文主要讲解SAP中物料的分割评估,通过分割评估来区分出同一物料不同来源下的核算方式。例如:同一物料分为自产或者采购,或者同一物料分为进口或者国内采购等。 一、概述 分割评估一般用于以下场景: 1、物料分为内部采购和外部采购; 2、物料分属于进口或者国内采购; 3、物料分属于不同的批次; 4、物料分为自制或者采购。 由于物料的来源不同可能导致物料的价格或者性质不同,需要用不同价格来区分出 二、配置步骤 1.激活分割评估 ...

五谷散熊 6792

osg源码分析osgGA/KeySwitchMatrixManipulator

/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified und...

chenyijie1529的博客 394

华为私有云HCS 8.1.1实战:从镜像制作到云主机发放全流程指南

本文详细解析了华为私有云HCS 8.1.1从镜像制作到云主机发放的全流程实战指南。内容涵盖制作标准化QCOW2镜像、配置云主机规格与主机组、规划外部网络,以及在运营面为租户初始化资源、配置审批流与产品目录。最后,通过用户视角演示了从创建VPC网络到申请、审批并最终绑定EIP访问云主机的完整操作步骤,为运维人员和架构师提供了一套清晰、可落地的HCS部署与管理实践方案。

weixin_29305313的博客 1128

osg解析系列-[osgSim::OverlayNode] 自带阴影效果的节点

运行结果:模拟飞机绕地球飞行。

qq_42531872的博客 366

毕设-YOLOv8-OBB 实现自有数据集缺陷旋转检测全过程记录

这次项目让我深入理解了 YOLOv8-OBB 的原理和使用流程。步骤内容工具数据标注制作倾斜缺陷样本格式转换从 HBB 转换为 OBB模型训练使用 Ultralytics YOLOv8 OBBCLI 命令模型测试推理与结果可视化通过 OBB 模型,我的缺陷检测系统获得了更高的精度和鲁棒性。未来我打算继续优化数据增强方式,比如引入随机旋转、仿射变换等,让模型更适应不同角度的样本。

FJN110的博客 447

【通信原理】基于【MATLAB】的通信OFDM系统仿真

主要进行OFDM系统的仿真,使用MATLAB软件对OFDM系统的接收端和发射端分别进行模拟仿真。

ALi.S的博客 5793

osg实例介绍

osg实例介绍 转自:http://blog.youkuaiyun.com/yungis/article/list/1 [原]osgmotionblur例子 该例子演示了运动模糊的效果。一下内容是转自网上的:原理:引用内容对于运动画面,将当前帧画面与上一帧画面进行alpha融合,以产生出残影——运动模糊效果。通过使用累积缓存来完成这项工作。OpenGL提供一个累积缓存,可...

weixin_34064653的博客 840

串口通信的性能瓶颈分析:如何提高数据吞吐量和降低延迟

摘要: 串口通信在高频或大数据场景下存在吞吐量不足、延迟高、丢帧等问题,主要瓶颈包括波特率限制、缓冲区不足、CPU轮询延迟等。优化策略包括:提升波特率至硬件上限、增大缓冲区、采用异步I/O(如ReadAsync)减少线程切换,使用二进制协议降低解析开销。实时性方面需启用硬件流控、批量发送数据,并优化线程优先级。跨平台适配需区分Windows/Linux的缓冲区设置与异步机制。性能测试可通过吞吐量、延迟及回环测试验证优化效果,核心原则是硬件匹配、异步处理、协议优化与跨平台适配。(150字)

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 985

TrackballManipulator分析

转载:http://blog.youkuaiyun.com/tmljs1988/article/details/7815729 void TrackballManipulator::computePosition(const osg::Vec3& eye,const osg::Vec3& center,const osg::Vec3& up) {    osg::Vec3 lv(center-

3535

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

第09节 实例-最简单的第一人称漫游操作器

缘由 群友:挑战高起点 在群里问了这么一个问题: image.png 因此我觉得它是对操作器的视口默认值以及旋转方式搞糊涂了。如果不理理清楚,基本上后面很多事情都没法办。我准备写个小例子帮助大家理一理。完整代码在本节最后和在网盘中: 注意:务必使用浏览器打开: 链接:https://pan.baidu.com/s/13gwJLwo_LbRnN3Bl2NXXXw 提取码:xrf5 功能 这一...

一切皆可视 304

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

第一日学习(二)osgViewer/view.cpp————osgViewer::View::init()

这里事先说下,作者在一开始说到了单窗口和多窗口是同样的流程,但是单窗口类不是osgViewer::View,而是osgViewer::viewer,这里要记住。 那么为什么要用到osgviewer::View类?因为osgViewer::viewer派生于osgViewer::View, 类的声明如下: namespace osgViewer { class Viewer : public...

coder 743

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

osgEarth的Earth格式文件说明

Earth 格式文件说明(初学者,请斧正) 地图 Map MAP是根节点。 <map name = "my map" type = "geocentric" version = "2" > <options> <image> <elevation> <model> <mask> <libraries> Property Des

robinfoxnan的专栏 3633

OSGEarth实战指南:从编译部署到三维GIS态势显示的优化技巧

三维地球渲染引擎是构建桌面级GIS应用的核心技术,基于OpenSceneGraph的OSGEarth通过地形分页调度、多源数据融合等机制,实现了全球高程与影像数据的高效加载与渲染。它在数字孪生、态势显示、路径推演等场景中展现出离线运行能力强、渲染逻辑可深度定制等优势。本文从编译部署、earth文件配置、坐标转换、动态特效到性能瓶颈排查,系统梳理实际项目中的工程经验,帮助C++开发者快速上手OSGEarth,规避依赖库冲突、数据格式不一致、多线程崩溃等常见坑点,提升三维地理信息系统的开发效率与运行稳定性。

weixin_34315485的博客 252

OSG学习之示例遇到的问题二图形不能显示网格模式

代码中加了 viewer.addEventHandler(new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()));   但是不能显示成网格模式 解决方法: W键切换显示模式,如果不行,注意自己是否有输入法错误。

wuwangrun的专栏 2875

浅谈在操控器类中,为何要通过osgGA::CameraManipulator的逆矩阵改变视点位置

这个变换的过程其实相当于需要求出把B点移回世界坐标原点的矩阵,A点再乘以这个矩阵就可以,这个移回的矩阵是这样计算的,把人从世界坐标原点移到B点的变换是Matrix,而把B点移回世界坐标原点的变换就是InverseMatrix,现在我们要把A点放在以B点为局部坐标下,则需要变换的就是InverseMatrix。原因这里有点绕,大家认真理解一下,世界坐标下,一个盒子在A点(xa,ya,za),视点在B点(xb,yb,zb),先不管朝向不朝向的。虽然入参不一样,但是跟踪一下会发现会调用过去的。

danshiming的博客 548

osg实现镜面成像、倒影效果

osg实现镜面成像、倒影效果

danshiming的博客 919
上一篇: http://blog.youkuaiyun.com/imyfriend/article/details/7823803
下一篇: GLSL 三种变量类型(uniform,attribute和varying)
三流文人
博客等级 码龄16年 10粉丝 3原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值