OpenSceneGraph 相机与视图

这篇具有很好参考价值的文章主要介绍了OpenSceneGraph 相机与视图。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

视图与相机

三维视景体

视景体是指成像景物所在空间的集合。它是一个空间集合体。

注意视景体指的是一个空间集合。一般来说,集合中的每个空间都是个立方体。然后所有的这些空间堆在一起,在外侧取一个最大的外接立方体,就是可显示的区域,该可显示区域也是一个视景体。在这个可显示区域内,放置着可以显示的物体。注意,可以显示的物体仅仅是拥有显示权限,但是不一定显示,这取决于相机等其他因素。

单个的视景体,比如一个球体,若要完全显示,其视景体应该是该球体的最小外接立方体;若要只显示上半部分,则取上半球,其视景体是上半球的最小外接立方体。对于半球而言,上半球是视景体,那么其只有上半球有显示权限,下半球没有,所以就算是将该球体位置拉远,也只能看到上半球。

比如一个球体,视景体为该球体的最小外接立方体。可以这样理解:该视景体的内容完完全全绘制在一张大小正好的画布(投影)上,画布(投影)以外都是背景色,取黑色。然后摄像机刚好看着这张画布(投影),画布(投影)上的内容完全显示在摄像机屏幕上。接着,对摄像机进行了右移,在摄像机的画面上,左侧是画布上的部分内容,右侧是黑色背景色。也就是说此时立方体虽然有显示权限,但是却并没有完全显示。但未显示的部分依然是有显示的可能的。

若视景体仅仅为上半球,那么默认情况下,上半球所映射的画布刚好充满摄像机。将摄像机下移,则摄像机画面中显示的是上半球切面的水平线,水平线以下是黑色背景色。即使此时从理论上来说摄像机对着下半球,但由于视景体仅为上半球,所以下半球是没有显示权限的,是不会被显示的。

视景体就意味着可显示空间,在该空间内的一切物体都可以被显示,都可以被看到,该空间外的一切物体都不能被看到。相机若要看到该空间中的物体,则相机本身就必须处于该视景体空间中。若相机在视景体空间外,哪怕该视景体就在相机正对的面前,相机依然无法看到。

视点变换

视点变换就是设置视点的方向和位置。默认情况下,视点定为坐标原点,指向Y正方向。
OpenSceneGraph 相机与视图,OpenSceneGraph 学习,c语言,c++,图形渲染,后端

投影变换

投影的作用:将要显示的三维视景体按照指定角度和方向投影到二维平面上。

投影分为透视投影和正视投影。根据这两种投影方式的不同,映射出的二维图像也不同:透视投影会出现近大远小的透视效果;正视投影不会影响物体的相对大小,即同样长的边,在远处与在近处看到的长度是相同的。

透视投影分为透视视景体对称透视视景体:

  • 透视视景体
    OpenSceneGraph 相机与视图,OpenSceneGraph 学习,c语言,c++,图形渲染,后端
    这个函数的前4个参数定义了近裁剪平面的左下角点和右上角点的三维空间坐标,即(left,bottom,-near)和(right,top,-near)。如下图(近大远小):
    OpenSceneGraph 相机与视图,OpenSceneGraph 学习,c语言,c++,图形渲染,后端
  • 对称透视视景体

OpenSceneGraph 相机与视图,OpenSceneGraph 学习,c语言,c++,图形渲染,后端
该函数的参数fovy定义视野的角度,以z轴为中心向两侧平分,范围是[0.0, 180.0],也就是说最大为上下各90°;参数aspect是投影平面宽度与高度的比,或者说是视景体的宽高比;参数zNear和Far分别是远近裁剪面沿Z负轴到视点的距离,它们总为正值。

以上两个函数缺省时,视点都在原点,视线沿Z轴指向负方向

正视投影分为正射投影特殊正射投影:

  • 正射投影视景体
    OpenSceneGraph 相机与视图,OpenSceneGraph 学习,c语言,c++,图形渲染,后端
    这个函数的前4个参数定义了近裁剪平面的左下角点和右上角点的三维空间坐标,即(left,bottom,-near)和(right,top,-near)。
    OpenSceneGraph 相机与视图,OpenSceneGraph 学习,c语言,c++,图形渲染,后端
  • 特殊正射投影视景体
    OpenSceneGraph 相机与视图,OpenSceneGraph 学习,c语言,c++,图形渲染,后端

视口

视口就是计算器屏幕的一块矩形区域,三维物体投影为二维平面,而这个二维平面就将显示在视口上。

OpenSceneGraph 相机与视图,OpenSceneGraph 学习,c语言,c++,图形渲染,后端

裁剪变换

在OSG中,可以设置裁剪平面,将没必要显示的物体去除掉,裁剪平面法线是哪个方向就留下哪个部分

使用osg::ClipPlane类来进行裁剪。

OpenSceneGraph 相机与视图,OpenSceneGraph 学习,c语言,c++,图形渲染,后端
OpenSceneGraph 相机与视图,OpenSceneGraph 学习,c语言,c++,图形渲染,后端

也可以使用 osg::Scissor类来进行裁剪。
OpenSceneGraph 相机与视图,OpenSceneGraph 学习,c语言,c++,图形渲染,后端

相机节点

osg::Camera类可以用于获得三维物体的自定义角度和方向的二维映射(拍照)。

该类方法除了上面视口,投影的相关函数还有如下:
OpenSceneGraph 相机与视图,OpenSceneGraph 学习,c语言,c++,图形渲染,后端

OpenSceneGraph 相机与视图,OpenSceneGraph 学习,c语言,c++,图形渲染,后端

图形环境

为了更方便的控制图形渲染,可以设置各种图形渲染的属性,也可以直接采用默认的。

通过osg::GraphicsContext::Traits类来设置图形环境特性。

OpenSceneGraph 相机与视图,OpenSceneGraph 学习,c语言,c++,图形渲染,后端

通过osg::GraphicsContext类createGraphicsContext()函数来创建图形环境特性。

OpenSceneGraph 相机与视图,OpenSceneGraph 学习,c语言,c++,图形渲染,后端

图形环境属性:
OpenSceneGraph 相机与视图,OpenSceneGraph 学习,c语言,c++,图形渲染,后端

宽屏变形实例

#include <osgViewer/Viewer>
 
#include <osg/Node>
#include <osg/Geode>
#include <osg/Group>
#include <osg/Camera>
 
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
 
#include <osgUtil/Optimizer>
 
#include <iostream>
 
int main()
{
	//创建Viewer对象, 场景浏览器
	osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();
 
	//创建场景节点
	osg::ref_ptr<osg::Group> root = new osg::Group();
 
	//读取模型
	osg::ref_ptr<osg::Node> node = osgDB::readNodeFile("cow.osg");
 
	root->addChild(node.get());
 
 
	//设置图形环境特性
	osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits();
	traits->x = 0;
	traits->y = 0;
	traits->width = 1000;
	traits->height = 800;
	traits->windowDecoration = true;
	traits->doubleBuffer = true;
	traits->sharedContext = 0;
 
	//场景图形环境特性
	osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext( traits.get());
	if (gc.valid())
	{
		osg::notify(osg::INFO)<< "GraphicsWindow has been created successfully."<< std::endl;
 
		//清楚窗口颜色及清楚颜色和深度缓存
		gc->setClearColor(osg::Vec4f(0.2f, 0.2f, 0.6f, 1.0f));
		gc->setClearMask(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);
	}
	else
	{
		osg::notify(osg::NOTICE)<< "GraphicsWindow has not been created successfully."<< std::endl;
	}
 
	//根据分辨率确定合适的投影来保证显示的图形不变形
	double fovy, aspectRatio, zNear, zFar;
	viewer->getCamera()->getProjectionMatrixAsPerspective(fovy, aspectRatio, zNear, zFar);
	double newAspectRatio = double(traits->width) / double(traits->height);
	double aspectRatioChange = newAspectRatio / aspectRatio;
	if (aspectRatioChange != 1.0)
	{
		//设置投影矩阵
		viewer->getCamera()->getProjectionMatrix() *= osg::Matrix::scale(1.0 / aspectRatioChange, 1.0, 1.0);
	}
 
	//设置视口
	viewer->getCamera()->setViewport(new osg::Viewport(0, 0, traits->width, traits->height));
	//设置图形环境
	viewer->getCamera()->setGraphicsContext(gc.get());
 
	//优化场景
	osgUtil::Optimizer optimizer;
	optimizer.optimize(root.get());
 
	viewer->setSceneData(root.get());
	viewer->realize();
	viewer->run();
	return 0;
}

单窗口多相机渲染实例

OpenSceneGraph 相机与视图,OpenSceneGraph 学习,c语言,c++,图形渲染,后端

// stdafx.h
 
#include <osg/Node>
#include <osg/Geode>  
#include <osg/Geometry>
#include <osg/Group>
 
#include <osg/MatrixTransform> //移动节点的矩阵类,最常用的移动节点的类。可随动、旋转控制节点
#include <osg/PositionAttitudeTransform> //位置变换节点类,提供模型的位置变换、大小缩放、原点位置的设置、坐标系的变换
#include <osg/Camera> //相机节点,管理OSG中的模型——视图矩阵,相机的管理主要是通过各种变换实现的
 
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
 
#include <osgUtil/Optimizer>
#include <osgViewer/Viewer> //只允许单视图,单视图可以同时包含多个相机渲染,也可以在多窗口中渲染
#include <osgViewer/ViewerEventHandlers> //事件监听



//.cpp
 
/*
 *单窗口多相机渲染
 *
 *创建图形环境的步骤:
 *通过WindowingSystemInterface类得到系统窗口接口,该系统接口主要是为了管理窗口系统与图形环境
 *根据需要设置图形环境特性的参数
 *通过图形环境特性创建图形环境
 *通过图形环境创建窗口
 *
 *建立视口的关键步骤:
 *创建图形环境(创建一个设备上下文对象)
 *将该对象和一个相机关联
 *设置视口位置
 *添加相机到窗口中
 */
void singleWindowMultipleCameras(osg::ref_ptr<osgViewer::Viewer> viewer)
{
	//创建窗口系统接口(调用底层API得到绘图设备、窗口特性)
	osg::ref_ptr<osg::GraphicsContext::WindowingSystemInterface> wsi = osg::GraphicsContext::getWindowingSystemInterface();
 
	if (!wsi)
	{
		osg::notify(osg::NOTICE) << "Error, no WindowSystemInterface available, cannot create windows." << std::endl;
		return;
	}
 
	//得到当前窗口分辨率
	unsigned int width, height;
	wsi->getScreenResolution(osg::GraphicsContext::ScreenIdentifier(0), width, height);
 
	//设置图形环境特性(设置要创建的图形设备上下文)
	osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits();
	//设置图形设备的尺寸
	traits->x = 0;
	traits->y = 0;
	traits->width = width;
	traits->height = height;
	//显示标题栏
	traits->windowDecoration = true;
	traits->doubleBuffer = true;
	traits->sharedContext = 0;
 
	//创建图形环境(创建图形设备上下文)
	osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get());
 
	if (gc->valid())
	{
		osg::notify(osg::INFO) << "GraphicsWindow has been created successfully." << std::endl;
 
		gc->setClearColor(osg::Vec4f(0.2f, 0.2f, 1.6f, 1.0f));
		gc->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	}
	else
	{
		osg::notify(osg::NOTICE) << "GraphicsWindow has not been created successfully." << std::endl;
	}
 
	//设置第一个视口(创建cameraMaster主相机)
	osg::ref_ptr<osg::Camera> cameraMaster = viewer->getCamera();
	//设置图形环境
	cameraMaster->setGraphicsContext(gc.get());
 
	//根据分辨率确定合适的投影来保证显示的图形不变形
	double fovy, aspectRatio, zNear, zFar;
	cameraMaster->getProjectionMatrixAsPerspective(fovy, aspectRatio, zNear, zFar);
	double newAspectRatio = double(traits->width) / double(traits->height);
	double aspectRatioChange = newAspectRatio / aspectRatio;
	if (aspectRatioChange != 1.0)
	{
		cameraMaster->getProjectionMatrix() *= osg::Matrix::scale(1.0 / aspectRatioChange, 1.0, 1.0);
	}
 
	//设置视口位置
	cameraMaster->setViewport(new osg::Viewport(0, 0, width, height));
	//根据是否使用双缓存,确定绘制哪个缓存,如果使用双缓存,先绘制前缓存
	GLenum bufferMaster = traits->doubleBuffer ? GL_BACK : GL_FRONT;
	//设置缓冲区(设置每帧开始绘制时,绘制哪个缓存)
	cameraMaster->setDrawBuffer(bufferMaster);
	cameraMaster->setReadBuffer(bufferMaster);
 
	//设置第二个视口(创建从属相机)
	osg::ref_ptr<osg::Camera> cameraClient = new osg::Camera();
	//设置图形环境
	cameraClient->setGraphicsContext(gc.get());
	//设置视口位置,视口的坐标为左下角为坐标原点
	cameraClient->setViewport(new osg::Viewport(0, 0, 400, 400));
	//根据是否使用双缓存,确定绘制哪个缓存,如果使用双缓存,先绘制前缓存
	GLenum bufferClient = traits->doubleBuffer ? GL_BACK : GL_FRONT;
	//设置缓冲区(设置每帧开始绘制时,绘制哪个缓存)
	cameraClient->setDrawBuffer(bufferClient);
	cameraClient->setReadBuffer(bufferClient);
 
	//添加从属相机
	viewer->addSlave(cameraClient, osg::Matrix::scale(aspectRatio, 1.0, 1.0), osg::Matrix());
}
 
int main()
{
	osg::ref_ptr<osg::Node> root = osgDB::readNodeFile("cow.osg");
 
	osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();
	//启用单视图多相机渲染
	singleWindowMultipleCameras(viewer.get());
 
	//优化场景数据
	osgUtil::Optimizer optimizer;
	optimizer.optimize(root.get());
 
	viewer->setSceneData(root.get());
	viewer->realize();
 
	return viewer->run();
}

效果图:

OpenSceneGraph 相机与视图,OpenSceneGraph 学习,c语言,c++,图形渲染,后端文章来源地址https://www.toymoban.com/news/detail-823122.html

到了这里,关于OpenSceneGraph 相机与视图的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • cesium学习记录06-视图、场景与相机

    一、视图(Viewer) Viewer 是 Cesium 的最高级别的组件,它封装了很多功能,如场景(viewer.scene)、时间线、动画、相机(viewer.camera)、信息框、事件处理、实体集合(viewer.entities)、数据源管理 (viewer.dataSources)等。 Viewer 的创建通常关联到一个 HTML 元素,例如一个 div。 使用

    2024年02月13日
    浏览(41)
  • 跟随chatgpt学习如何使用GLSL进行简单的图形渲染

    运行成功页面 一个简单的glsl小实验成功了,不过我想要这个三角形动起来。 修改后的script代码如下 运行成功截图 他现在就是一个游来游去的红色三角形了。太神奇了!~

    2024年01月18日
    浏览(49)
  • Part1:使用 TensorFlow 和 Keras 的 NeRF计算机图形学和深度学习——计算机图形学世界中相机的工作原理

    是否有一种方法可以仅从一个场景多张不同视角的照片中捕获整个3D场景? 有。 NeRF:将场景表示为用于视图合成的神经辐射场中(NeRF: Representing Scenes as Neural Radiance Fields for View Synthesis),Mildenhall等人(2020)的论文解答了这个问题。NeRF的更简单实现赢得了 TensorFlow社区聚光

    2024年02月07日
    浏览(51)
  • 图形学-(视图变换,投影变换)

    在 3 维物体变到二维平面的过程中,我们需要规定好相机的位置。对于相机所做的变换就是 视图变换 (Viewing/Camera transformation)。 我们需要对相机位置进行定义,对于一个相机我们要规定下面三个属性: 相机位置(视点)(Position) 相机拍摄方向(视线)(Look-at/Gaze direction) 相机

    2024年02月11日
    浏览(40)
  • SpringBoot之视图渲染技术

    在Spring Boot中,视图渲染技术用于将动态数据渲染到用户界面,生成最终的HTML、XML、JSON等文档,以便将其返回给客户端浏览器 Freemarker是一个Java模板引擎,用于生成基于模板的动态内容。它是一种用于生成文本输出的模板引擎,常用于Web应用程序开发中的视图层。 Freemarker的

    2024年02月03日
    浏览(42)
  • 【SpringBoot】FreeMarker视图渲染

    目录 一、FreeMarker 简介 1.1 什么是FreeMarker? 1.2 Freemarker模板组成部分 1.3 为什么要使用FreeMarker 二、Springboot集成FreeMarker 2.1 配置 2.2 数据类型 2.2.1 字符串 2.2.2 数值 2.2.3 布尔值 2.2.4 日期 2.3 常见指令   2.3.2 assign 2.3.3 include ... 三、常见指令实现增删改查(综合案例)⭐ 3.1 后端

    2024年02月04日
    浏览(35)
  • QT图形视图框架——坐标系统

    图形项坐标     以图形项的左上角为原点。     创建自定义图形项时,只需要考虑图形项的坐标系统     没有父图形项的是顶层图形项,在场景坐标系中,可以用setPos()函数指定图形项的位置,没有指定时出现在原点处。子图形项的坐标不会受到父图形项的变换的影响,

    2024年02月16日
    浏览(37)
  • 【计算机图形学】三维图形投影和消隐(三视图构造)

    模块4-1 三维图形投影和消隐 一 实验目的 编写三维图形各种变换的投影算法 二 实验内容 1 :自行选择三维物体(不能选长方体),建立坐标系,给定点的三维坐标值,建立边表结构。完成三视图。 实验结果如下图所示: 左上显示为主视图,右上显示为侧视图,右下显示为

    2024年02月01日
    浏览(92)
  • easy X(C语言图形化界面)学习

    1.文件为(.cpp)后缀 运行结果如下: 第三个参数 画几个圆 举例: 运行结果: RGB画板的三原色数据 修改outtextxy函数,让其输出多个字符(字符串) 文字居中 运行结果: 举例: 输出图片相对路径时,把文件放在vs对应的项目文件中 运行结果为: 举例: 运行结果: 判断鼠标

    2024年02月02日
    浏览(42)
  • Django(5)-视图函数和模板渲染

    Django 中的视图的概念是「一类具有相同功能和模板的网页的集合」 在我们的投票应用中,我们需要下列几个视图: 问题索引页——展示最近的几个投票问题。 问题详情页——展示某个投票的问题和不带结果的选项列表。 问题结果页——展示某个投票的结果。 投票处理器—

    2024年02月11日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包