首页 > 其他分享 >OSG开发笔记(四十):使用OSG自绘拟合球形顶点

OSG开发笔记(四十):使用OSG自绘拟合球形顶点

时间:2024-12-20 14:20:52浏览次数:4  
标签:pGeometry 自绘 ptr OSG 拟合 顶点 ref 坐标系 osg

前言

  OSG内置的几何图形并没有球面,那么绘制球面先要绘制球面的组成顶点,本篇解说绘制球面组成顶点的详细过程。

 

Demo

  在这里插入图片描述

  组成面的时候,为了看到是否正确,取中间的几个圆环:
  在这里插入图片描述

  在这里插入图片描述

  

 

回顾OSG坐标系理解

  OSG的坐标系类似于Qt场景坐标系,场景有场景的坐标系,图元有图元的坐标系,视图有视图的坐标系。与此类似,OSG坐标系也相似,差别在于视图坐标系在OSG是相机坐标系。

世界坐标系

  世界坐标系描述的是整个场景中所有的对象,可以理解为绝对坐标系,所有对象的位置都是绝对坐标。从整体上考虑,它为所有对象的位置提供一个绝对的参考标准,从而避免了物体之间由于独立的物体坐标系而导致的坐标系混乱。

物体坐标系

  每一个物体都有自己的坐标系,当物体发生交换时,实际上是它本身的坐标系相对于世界坐标系发生变换的过程。
物体坐标系通常描述的问题是特定物体的内部对象,主要包括物体的顶点,物体的法向量和物体的方向。

摄像机坐标系

  摄像机坐标系与屏幕坐标系类似,只不过摄像机坐标系位于3D空间,而屏幕坐标系位于2D空间。
  坐标系三轴正方向

  • opengl坐标系,即z轴正向朝外,y轴正向朝上,x轴正向朝右(符合软件研发标准坐标);
  • osg坐标系,即z轴正向朝上,y轴正向朝内,x轴正向朝右(笛卡尔坐标系);
  • Directx坐标系,即z轴正向朝里,y轴正向朝上,x轴正向朝右.(左手坐标系);

笛卡尔坐标系-右手法则

  在这里插入图片描述

 

球面顶点计算原理

  平行面计算平行角度θ,其一周的x和y计算:
  在这里插入图片描述

  得到了最大横截面的时候圆圈点的求解公式。
  垂直平面计算垂直的z坐标系:
  在这里插入图片描述

  以上两个绘制出来就是圆柱了:
  在这里插入图片描述

  纵轴的角度也要参与到之前圆圈的计算中,得到上下走的时候圆圈缩小:
  在这里插入图片描述

  在这里插入图片描述

  那么x和y都需要额外乘以垂直角度来缩小,按照代码的计算方式,是从y从0°开始,所以是cos,不是sin,绘制出来如下图:
  在这里插入图片描述

 

绘制球面顶点过程

步骤一:创建几何节点和几何信息节点

  在这里插入图片描述

// 步骤一:创建一个用户保存集合信息的对象osg::Geode
osg::ref_ptr<osg::Geode> pGeode = new osg::Geode;
osg::ref_ptr<osg::Geometry> pGeometry = new osg::Geometry;

步骤二:计算顶点,设置顶点颜色

  在这里插入图片描述

    // 步骤二:计算顶点,颜色
    osg::ref_ptr<osg::Vec3Array> pVec3ArrayVertex = new osg::Vec3Array;
    osg::ref_ptr<osg::Vec4Array> pVec4ArrayColor = new osg::Vec4Array;
    // 计算步长数量
    int xyStepTotal = qCeil(360.0f / xyCircleStepAngle);
    // 纵轴,因为只提供了z坐标,走180°即可
    int xzStepTotal = qCeil(180.0f / xzCircleStepAngle);
    {
        // 计算步长角度
        double xyStepAngle = 360.0f / xyStepTotal;
        double xzStepAngle = 180.0f / xzStepTotal;
#if 1
        // 计算顶点,颜色
        for(int xzStepIndex = 0; xzStepIndex < xzStepTotal; xzStepIndex++)
        {
            for(int xyStepIndex = 0; xyStepIndex < xyStepTotal; xyStepIndex++)
            {
//                LOG << xyStepIndex << xyStepIndex * xyStepAngle
//                    << xzStepIndex << xzStepIndex * xzStepAngle;
                LOG << radius * cos(qDegreesToRadians(xyStepIndex * xyStepAngle))
                    << radius * sin(qDegreesToRadians(xyStepIndex * xyStepAngle))
                    << radius * cos(qDegreesToRadians(xzStepIndex * xzStepAngle));
                // 绘制点
                pVec3ArrayVertex->push_back(osg::Vec3f(radius * cos(qDegreesToRadians(xyStepIndex * xyStepAngle)) * sin(qDegreesToRadians(xzStepIndex * xzStepAngle)),
                                                       radius * sin(qDegreesToRadians(xyStepIndex * xyStepAngle)) * sin(qDegreesToRadians(xzStepIndex * xzStepAngle)),
                                                       radius * cos(qDegreesToRadians(xzStepIndex * xzStepAngle))));
                // 绘制颜色
                pVec4ArrayColor->push_back(osg::Vec4f(1.0, 0.0, 0.0, 1.0));
            }
        }
#endif
    }
pGeometry->setVertexArray(pVec3ArrayVertex.get());

步骤三:设置顶点颜色

  在这里插入图片描述

// 步骤三:设置顶点颜色
    pGeometry->setColorArray(pVec4ArrayColor.get());
pGeometry->setColorBinding(osg::Geometry::BIND_OVERALL);

步骤四:设置顶点法向量

  在这里插入图片描述

// 步骤四:添加法线、设置法线
osg::ref_ptr<osg::Vec3Array> pVec3ArrayNormal = new osg::Vec3Array;
pVec3ArrayNormal->push_back(osg::Vec3f(0, 1, 0));
pGeometry->setNormalArray(pVec3ArrayNormal);

步骤五:设置几何图形绘制方式

  在这里插入图片描述

// 步骤五:设置顶点几何绘制方式
//LOG << pVec3ArrayVertex->size() << pVec4ArrayColor->size();
pGeometry->addPrimitiveSet(new osg::DrawArrays(osg::DrawArrays::POINTS, 0, pVec3ArrayVertex->size()));

步骤六:绘制几何图形

  在这里插入图片描述

// 步骤六:绘制几何图形
pGeode->addDrawable(pGeometry.get());

步骤七:设置顶点绘制大小

  在这里插入图片描述

#if 1
    // 步骤七:设置顶点大小
    osg::ref_ptr<osg::Point> pPoint = new osg::Point();
    pPoint->setSize(1);
    pGeometry->getOrCreateStateSet()->setAttributeAndModes(pPoint, osg::StateAttribute::ON);
#endif
 

Demo源码

节点完整绘制函数

osg::ref_ptr<osg::Node> OsgWidget::getSpherialSurface()
{
    // 其他demo的控件
    updateControlVisible(false);

    osg::ref_ptr<osg::Group> pGroup = new osg::Group();

    {
        // 创建球面
        osg::ref_ptr<osg::Geode> pGeode = OsgManager::createSpherialSurface(Point3F(0, 0, 0), 50, 10, 10);
        // 关闭光照
        OsgManager::setLighting(pGeode.get(), false);

        pGroup->addChild(pGeode.get());
    }

    return pGroup.get();
}

绘制球面点函数

osg::ref_ptr<osg::Geode> OsgManager::createSpherialSurface(Point3F center, double radius, double xyCircleStepAngle, double xzCircleStepAngle)
{
    // 绘制球面
    // 步骤一:创建一个用户保存集合信息的对象osg::Geode
    osg::ref_ptr<osg::Geode> pGeode = new osg::Geode;
    osg::ref_ptr<osg::Geometry> pGeometry = new osg::Geometry;
    // 步骤二:计算顶点,颜色
    osg::ref_ptr<osg::Vec3Array> pVec3ArrayVertex = new osg::Vec3Array;
    osg::ref_ptr<osg::Vec4Array> pVec4ArrayColor = new osg::Vec4Array;
    // 计算步长数量
    int xyStepTotal = qCeil(360.0f / xyCircleStepAngle);
    // 纵轴,因为只提供了z坐标,走180°即可
    int xzStepTotal = qCeil(180.0f / xzCircleStepAngle);
    {
        // 计算步长角度
        double xyStepAngle = 360.0f / xyStepTotal;
        double xzStepAngle = 180.0f / xzStepTotal;
#if 1
        // 计算顶点,颜色
        for(int xzStepIndex = 0; xzStepIndex < xzStepTotal; xzStepIndex++)
        {
            for(int xyStepIndex = 0; xyStepIndex < xyStepTotal; xyStepIndex++)
            {
//                LOG << xyStepIndex << xyStepIndex * xyStepAngle
//                    << xzStepIndex << xzStepIndex * xzStepAngle;
                LOG << radius * cos(qDegreesToRadians(xyStepIndex * xyStepAngle))
                    << radius * sin(qDegreesToRadians(xyStepIndex * xyStepAngle))
                    << radius * cos(qDegreesToRadians(xzStepIndex * xzStepAngle));
                // 绘制点
                pVec3ArrayVertex->push_back(osg::Vec3f(radius * cos(qDegreesToRadians(xyStepIndex * xyStepAngle)) * sin(qDegreesToRadians(xzStepIndex * xzStepAngle)),
                                                       radius * sin(qDegreesToRadians(xyStepIndex * xyStepAngle)) * sin(qDegreesToRadians(xzStepIndex * xzStepAngle)),
                                                       radius * cos(qDegreesToRadians(xzStepIndex * xzStepAngle))));
                // 绘制颜色
                pVec4ArrayColor->push_back(osg::Vec4f(1.0, 0.0, 0.0, 1.0));
            }
        }
#endif
    }
    pGeometry->setVertexArray(pVec3ArrayVertex.get());
    // 步骤三:设置顶点颜色
    pGeometry->setColorArray(pVec4ArrayColor.get());
    pGeometry->setColorBinding(osg::Geometry::BIND_OVERALL);
    // 步骤四:添加法线、设置法线
    osg::ref_ptr<osg::Vec3Array> pVec3ArrayNormal = new osg::Vec3Array;
    pVec3ArrayNormal->push_back(osg::Vec3f(0, 1, 0));
    pGeometry->setNormalArray(pVec3ArrayNormal);
    // 步骤五:设置顶点几何绘制方式
//    LOG << pVec3ArrayVertex->size() << pVec4ArrayColor->size();
    pGeometry->addPrimitiveSet(new osg::DrawArrays(osg::DrawArrays::POINTS, 0, pVec3ArrayVertex->size()));
    // 步骤六:绘制几何图形
    pGeode->addDrawable(pGeometry.get());
#if 0
    // 步骤七:设置顶点大小
    osg::ref_ptr<osg::Point> pPoint = new osg::Point();
    pPoint->setSize(1);
    pGeometry->getOrCreateStateSet()->setAttributeAndModes(pPoint, osg::StateAttribute::ON);
#endif
    return pGeode.get();
}

关闭光照函数

void OsgManager::setLighting(osg::Node *pNode, bool open)
{
    // 步骤一:获取状态集
    osg::ref_ptr<osg::StateSet> pStateSet = pNode->getOrCreateStateSet();
    // 步骤二:状态集 设置深度测试开启,确保透明的物体深度测试开启
    pStateSet->setMode(GL_LIGHTING, open ? osg::StateAttribute::ON : osg::StateAttribute::OFF);
}
 

工程模板v1.40.0

  在这里插入图片描述

 

入坑

入坑一:测试绘制顶点的时候,绘制顶点不显示

问题

  顶点不显示
  在这里插入图片描述

  结点代码:
  在这里插入图片描述

尝试

  改成直线后也不现实,然后拽托下变换视角,发现可以显示
  在这里插入图片描述

  在这里插入图片描述

  所以绘制时出来了,只是看不到,关闭光照就好:
  在这里插入图片描述

  改回点即可。

解决

  关闭光照即可
  在这里插入图片描述

  查看点,是为了检查点对错,上面就是少计算了一个,所以变成圆柱,下面是对的了:
  在这里插入图片描述

标签:pGeometry,自绘,ptr,OSG,拟合,顶点,ref,坐标系,osg
From: https://www.cnblogs.com/qq21497936/p/18619168

相关文章

  • 优化SHAP主效应图拟合曲线与交点标注直观展示特征影响变化与趋势
    背景SHAP主效应值,即该特征在独立作用时对模型预测的贡献,这种方式剥离了交互效应的影响,更加直观地展现了主效应的变化趋势,为分析特征的独立作用提供了清晰的视角,有助于更深入地理解模型的特征行为,详情参考文章——期刊配图:SHAP主效应图绘制解释单个特征在独立作用时对模型预测......
  • 第三章 3.12 dropout 和 正则化 克服过拟合
    代码:#https://github.com/PacktPublishing/Modern-Computer-Vision-with-PyTorch#https://github.com/PacktPublishing/Modern-Computer-Vision-with-PyTorch###################ChapterThree########################################第三章读取数据集并显示fro......
  • Qt QHeaderView自绘实现表头双击编辑
    在使用QTreeWidget展示数据时,想要让表头可以编辑。但是QTreeWidget并没有提供这样的API。于是想到了,通过QHeaderView自绘去实现这样的需求。效果图:头文件://CustomHeader.h#pragmaonce#include<QHeaderView>#include<QLineEdit>#include<QHeaderView>#inclu......
  • OSG开发笔记(三十九):OSG中模型的透明度实现、球体透明度Demo
    前言  在OSG中,对于一些效果未被选中或者包含等业务,需要半透明效果来实现。  本篇描述OSG的半透明实现方式。 Demo   透明功能概述  透明效果在三维场景中扮演着重要角色,它能够模拟玻璃、水体、烟雾等自然现象,增加场景的层次感和真实感。然而,透明效......
  • OSG开发笔记(三十八):osg3.0.0基于windows平台msvc2017x64编译器编译并移植Demo
    前言  本篇编译osg3.3.0的msvc2017x64版本,验证书中的从相机demo。 OSG编译步骤一:下载解压  下载版本,由于官方的其他路径没有直接给出3.0.0,需要自己切换分支,代码地址:https://github.com/openscenegraph/OpenSceneGraph/tree/OpenSceneGraph-3.6.4  然后:  ......
  • 如何避免过拟合?如何避免梯度消失和梯度爆炸?
    如何避免过拟合?避免过拟合(overfitting)是机器学习中非常重要的一部分,因为过拟合会导致模型在训练数据上表现很好,但在测试数据或新数据上表现差。为了减少过拟合,可以采取以下几种策略:1.增加训练数据   方法:通过增加更多的数据样本,尤其是多样化的数据,可以帮助模型更好地学......
  • Halcon 中各种拟合算子原理及应用场景
    一、引言在机器视觉和图像处理领域,拟合操作是一种非常重要的技术手段。Halcon作为一款强大的机器视觉软件库,提供了多种拟合算子来处理不同类型的数据,如点、线、曲线等,从而帮助用户从复杂的数据中提取出有价值的几何信息。这些拟合算子基于严谨的数学原理,并且在不同的工业检测......
  • 【人工智能基础06】人工神经网络基础(二):1. 权值初始化(权值优化、避免梯度)、2. 权值衰减
    文章目录一.权值初始化1.零初始化(ZeroInitialization)2.随机初始化(RandomInitialization)3.Xavier初始化4.Kaiming初始化(KaimingInitialization)二.权值衰减:通过正则防止过拟合1.作用机制2.目的3.应用场景三.权值共享与卷积:处理过拟合的问题1.定义2.作用2.......
  • 3DTiles文件如何转换OSGB文件?来试试这款免费GIS工具箱
    概述3DTiles格式被广泛用于Web端三维场景展示,而OSGB格式因其优秀的离线性能和支持大规模三维模型处理的能力,在本地应用中尤为出色。但在实际项目中,因需求不同,经常需要将3DTiles格式转换为OSGB格式。面对这种转换需求,许多工具操作复杂且费用高昂。然而,现在有一款免费的GIS工具箱可......
  • HALCON机器视觉之测量拟合(C# + HALCON,含完整代码)
    HALCON机器视觉之测量拟合(C#+HALCON)一、引言在当今的工业和民用领域,机器视觉技术发挥着越来越重要的作用。其中,测量拟合是机器视觉中的关键环节,它能够从图像中提取物体的各种信息,并将其转化为数学模型,为后续的分析、控制和决策提供依据。HALCON作为一款领先的机器视觉软......