osg中相机矩阵到vsg相机矩阵的转换

前言

在OSG和VSG中,相机的核心功能主要包括视图变换与投影变换:视图变换负责将世界坐标系中的物体转换到相机坐标系,而投影变换则进一步将相机坐标系中的物体映射到投影空间。由于OpenGL与Vulkan在底层实现上存在差异,Vulkan的深度范围定义为0, 1,且y轴方向由上向下,这与OpenGL有所不同。因此,本章将重点讨论从OSG相机矩阵到VSG相机矩阵的转换方法,并进一步讨论投影矩阵之间的转换。


目录

  • 1 vsg相机矩阵到CesiumNative间的矩阵转换
  • 2 osg中的相机矩阵到vsg相机矩阵的转换

1 vsg相机矩阵到CesiumNative间的矩阵转换

vsgCs(https://github.com/timoore/vsgCs/ v1.1.1)中,CesiumNative采用glm::dmat4数据结构来表达矩阵,可通过数值拷贝的方式可实现vsg中view矩阵和投影矩阵间的转换。如下所示:

cpp 复制代码
    std::optional<Cesium3DTilesSelection::ViewState>
    createViewState(const vsg::ref_ptr<vsg::View>& view, const vsg::ref_ptr<vsg::RenderGraph>& renderGraph)
    {
        auto* viewData = dynamic_cast<ViewData*>(view->getObject("vsgCsViewData"));
        if (!viewData)
        {
            return {};
        }
        vsg::dmat4 Pw = vsg::computeTransform(viewData->tilesetPath);
        vsg::dmat4 PcsInv = TilesetNode::yUp2zUp * view->camera->viewMatrix->transform() * Pw;
        vsg::dmat4 Pcs = vsg::inverse(PcsInv);
        glm::dvec3 position(Pcs[3][0], Pcs[3][1], Pcs[3][2]);
        glm::dvec3 direction(Pcs[1][0], Pcs[1][1], Pcs[1][2]);
        glm::dvec3 up(Pcs[2][0], Pcs[2][1], Pcs[2][2]);
        vsg::ref_ptr<vsg::ProjectionMatrix> projMat = view->camera->projectionMatrix;
        glm::dvec2 viewportSize;
        if (view->camera->viewportState)
        {
            VkViewport viewport = view->camera->viewportState->getViewport();
            viewportSize[0] = viewport.width;
            viewportSize[1] = viewport.height;
        }
        else
        {
            viewportSize[0] = renderGraph->renderArea.extent.width;
            viewportSize[1] = renderGraph->renderArea.extent.height;
        }
        Cesium3DTilesSelection::ViewState result =
            Cesium3DTilesSelection::ViewState(vsg2glm(view->camera->viewMatrix->transform()), vsg2glm(projMat->transform()), viewportSize);
        return {result};
    }

2 osg中的相机矩阵到vsg相机矩阵的转换

osg中采用行优先形式存储矩阵,而vsg中采用列优先形式存储矩阵,以投影矩阵为例,透视投影下两者的计算公式分别如下:

|----------------------------------------------------------------------------|
| |
| osg投影矩阵 |
| |
| vsg投影矩阵 |

从公式上看,值-1.0,两者在同一个位置,但却表达的含义不同,在osg中-1.0所在位置为第三行第四列,而在vsg中为第四行第散列。

osg矩阵到vsg矩阵的转换代码如下所示:

cpp 复制代码
vsg::dmat4 osg2vsg(const osg::Matrix& osgMat)
{
    vsg::dmat4 result;
    std::memcpy(result.data(), osgMat.ptr(), sizeof(double) * 16);
    return result;
}

考虑到vsg中投影空间深度范围为0-1,且采用了reversed-z,Y轴从上到下,因此osg的投影矩阵到vsg的投影矩阵转换函数如下:

cpp 复制代码
vsg::dmat4 osg2vsg(const osg::Matrix& osgMat)
{
    osg::Matrix oToV(
        1.0, 0.0, 0.0, 0.0,
        0.0, -1.0, 0.0, 0.0,
        0.0, 0.0, -0.5, 0,
        0.0, 0.0, 0.5, 1.0
    );
    vsg::dmat4 result;
    std::memcpy(result.data(), (osgMat* oToV).ptr(), sizeof(double) * 16);
    return result;
}

文末:本章借助vsgCs中的代码分析了vsg矩阵到CesiumNative矩阵的转换方法,可直接通过值拷贝实现转换。接着讨论了osg到vsg的矩阵转换方法,考虑到了osg中矩阵为行优先,而vsg中矩阵为列优先,在此基础上进一步讨论了两者投影矩阵的转换方法,考虑到了vsg投影空间的投影深度为1,0,且y轴由上向下的特点。

相关推荐
郝学胜_神的一滴1 天前
中级OpenGL教程 024:Assimp模型加载之Mesh解码玄功
计算机图形学·opengl
郝学胜-神的一滴2 天前
中级OpenGL教程 023:Assimp模型加载全解——从源码到架构的骈文探秘
c++·unity·游戏引擎·cmake·unreal engine·opengl
郝学胜-神的一滴3 天前
中级OpenGL教程 022:探秘三维世界的血脉传承——物体父子关系与矩阵递归奥义
c++·线性代数·unity·矩阵·游戏引擎·unreal engine·opengl
郝学胜_神的一滴5 天前
Horse3D 游戏引擎研发笔记(二):材质系统——从 JSON 配置到 GPU Uniform
游戏开发·opengl
郝学胜-神的一滴11 天前
[简化版 GAMES 101] 计算机图形学 17:纹理技术从基础原理到多场景实战应用
c++·unity·游戏引擎·图形渲染·three.js·opengl·unreal
郝学胜-神的一滴15 天前
中级OpenGL教程 013:渲染器类架构设计与逐帧渲染流程详解
开发语言·c++·unity·游戏引擎·图形渲染·opengl·unreal
郝学胜-神的一滴18 天前
[简化版 GAMES 101] 计算机图形学 16:纹理走样、Mipmap、三线性插值、各向异性过滤原理全解
unity·游戏引擎·godot·图形渲染·three.js·opengl·unreal
郝学胜-神的一滴1 个月前
[简化版 GAMES 101] 计算机图形学 13:从光栅化到着色——赋予三维像素光影灵魂
c++·计算机视觉·unity·godot·图形渲染·opengl·unreal
Strugglingler1 个月前
【Qt,OpenGL, RHI,Wayland 等概念梳理】
qt·opengl·wayland·rhi·x11·egl·glx
郝学胜-神的一滴1 个月前
中级OpenGL教程 009:用环境光告别模型死黑
前端·c++·unity·godot·图形渲染·opengl·unreal