OSG中抓取屏幕保存为图片

这篇博客主要介绍了如何在OSG(OpenSceneGraph)中实现自动抓取场景截图的功能。通过继承osgViewer::ScreenCaptureHandler类和CaptureOperation类,创建自定义事件并将其压入OSG事件队列,从而在指定时刻保存屏幕截图。

由于需要自动抓取OSG中的场景截图,对OSG掌握不好,花费了一些时间才算搞定。

首先,OSG在类osgViewer::ScreenCaptureHandler中默认情况下按下c(小写c)可以截取单张图片,而且实现得比较全面,在按下C(大写c)时可以连续截图;经过继承osgViewer::ScreenCaptureHandler类和osgViewer::ScreenCaptureHandler::CaptureOperation类,由于需要自动在某个时刻保存,所以些了一个自定义的事件,并将事件压入OSG的事件队列。

上代码:

ScreenCapture.h文件

#pragma once

#ifndef SCREENCAPTURE_H
#define SCREENCAPTURE_H

#include <string>

#include <osgDB/WriteFile>
#include <osgViewer/ViewerEventHandlers>

class CScreenCapture : public osgViewer::ScreenCaptureHandler
{
public:
	class  WriteToImageFile : public osgViewer::ScreenCaptureHandler::CaptureOperation
	{
	public:
		enum SavePolicy
		{
			OVERWRITE,
			SEQUENTIAL_NUMBER
			// ... any others?
		};

		WriteToImageFile(const std::string& filename, const std::string& extension, SavePolicy s
在 OpenSceneGraph (OSG) 中,屏幕坐标的表示方式是通过视口变换(viewport transformation)将归一化设备坐标(Normalized Device Coordinates, NDC)转换为实际的屏幕坐标。通常情况下,屏幕坐标系的原点位于窗口的左下角,X 轴向右为正方向,Y 轴向上为正方向,Z 轴则表示深度值,通常范围在 [0, 1] 之间,用于表示物体距离相机的远近[^2]。 OSG 中的屏幕坐标可以通过 `osg::Camera` 的视口(`osg::Viewport`)来定义。视口通常设置为与窗口大小一致,其定义方式如下: ```cpp osg::Camera* camera = new osg::Camera(); camera->setViewport(new osg::Viewport(0, 0, width, height)); ``` 其中 `(0, 0)` 表示视口的左下角坐标,`width` 和 `height` 分别表示窗口的宽度和高度。经过视口变换后,顶点数据从归一化设备坐标系(范围在 [-1, 1] 之间)映射到屏幕坐标系中,X 和 Y 坐标的取值范围分别为 [0, width] 和 [0, height][^2]。 此外,OSG 提供了工具函数 `osg::CoordinateSystemNode` 和 `osg::Geode` 来辅助进行坐标转换,也可以通过 `osgUtil::LineSegmentIntersector` 来实现从屏幕坐标到世界坐标的拾取操作。 ### 坐标转换示例:屏幕坐标转世界坐标 以下是一个简单的示例代码,展示如何将屏幕坐标(例如鼠标点击位置)转换为世界坐标: ```cpp osg::Geode* createWorldCoordinateIndicator() { osg::Geode* geode = new osg::Geode(); osg::ShapeDrawable* shape = new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(), 0.1)); shape->setColor(osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f)); geode->addDrawable(shape); return geode; } osg::Matrixd getWorldMatrixFromScreen(osg::Camera* camera, const osg::Vec2& screenPos, float depth) { osg::Viewport* viewport = camera->getViewport(); int width = viewport->width(); int height = viewport->height(); // 将屏幕坐标转换为归一化设备坐标 float ndcX = (screenPos.x() / static_cast<float>(width)) * 2.0f - 1.0f; float ndcY = (screenPos.y() / static_cast<float>(height)) * 2.0f - 1.0f; // 构建NDC坐标点 (z由depth提供) osg::Vec4 ndcPoint(ndcX, ndcY, depth, 1.0f); // 获取投影和模型视图矩阵的逆矩阵 osg::Matrixd invProjection = osg::Matrixd::inverse(camera->getProjectionMatrix()); osg::Matrixd invModelView = osg::Matrixd::inverse(camera->getViewMatrix()); // 转换到世界坐标 osg::Vec4 worldPoint = ndcPoint * invProjection * invModelView; // 归一化齐次坐标 worldPoint /= worldPoint.w(); return osg::Matrixd::translate(worldPoint.x(), worldPoint.y(), worldPoint.z()); } ``` 上述代码中,通过逆投影矩阵和逆视图矩阵将归一化设备坐标转换为世界坐标,并可用于在场景中放置一个表示该点的几何体(如球体)。 ### 坐标系特性总结 - **屏幕坐标系**:原点位于左下角,X 向右增长,Y 向上增长,Z 表示深度。 - **视口变换**:将 NDC 坐标 [-1, 1] 映射到屏幕坐标 [0, width] 和 [0, height]。 - **深度值**:Z 值通常在 [0, 1] 范围内,表示物体在深度缓冲中的位置。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值