项目实战:Qt+OSG三维建模基础框架v1.0.0(绘制直线,输入参数,绘制通道,支持windows、linux、国产麒麟系统)
需求
1.使用osg替换opengl建模,osg三维对象管理,性能优化,而opengl依赖cpu计算,且对场景管控不好;
2.右侧鼠标绘图,绘制长度的通道,可以一边画图,同步根据图来进行长度的创建通道;(这部分暂没继续实现了);
3.左侧侧是三维场景的框架,实现基本的功能:缩放、旋转、拽托场景中心,固定轴旋转;(这块是三维引擎,没有针对项目进行漫游器、事件处理器、相机口的调整了。)
4.基准面,绘制预计大小的基准面(这块要做无限平面,暂时这么多,无限平面得做显示范围正交投影,否则远处的会扎堆成一块黑色,已解决未放入);
本项目v1.0.0,实现一个建模的雏形,后续会逐渐完善。
《OSG开发笔记(三十):OSG加载动力学仿真K模型文件以及测试Demo》
《项目实战:Qt+OSG爆破动力学仿真三维引擎测试工具v1.1.0(加载.K模型,子弹轨迹模拟动画,支持windows、linux、国产麒麟系统)》
《项目实战:Qt+OSG三维建模基础框架v1.0.0(绘制直线,输入参数,绘制通道,支持windows、linux、国产麒麟系统)》
#ifndef OSGMANAGER_H
#define OSGMANAGER_H
#include "osgQt/GraphicsWindowQt.h"
#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <osgGA/CameraManipulator>
#include <osgGA/StandardManipulator>
#include <osgGA/OrbitManipulator>
#include <osgGA/TrackballManipulator>
#include <osgGA/MultiTouchTrackballManipulator>
#include <osgGA/NodeTrackerManipulator>
#include <osgGA/TerrainManipulator>
#include <osgGA/FirstPersonManipulator>
#include <osgGA/FlightManipulator>
#include <osgGA/AnimationPathManipulator>
#include <osgGA/SphericalManipulator>
#include <osgGA/CameraViewSwitchManipulator>
#include <osgGA/DriveManipulator>
#include <osgGA/KeySwitchMatrixManipulator>
#include <osgGA/UFOManipulator>
#include <osgGA/StateSetManipulator>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <osg/Switch>
#include <osg/MatrixTransform>
#include <osg/Depth>
#include <osg/LineWidth>
#include <osg/Point>
#include <osg/Shape>
#include <osg/ShapeDrawable>
#include <osg/Multisample>
#include <osg/PositionAttitudeTransform>
#include "osgCommon.h"
class OsgManager
{
public:
OsgManager();
public:
// 创建一个隧道
static osg::ref_ptr<osg::Node> createTunnel(Point3F centerP, double width, double height, double length, double thickness);
public:
// 创建一个面,输入四个点,输入四个点颜色
static osg::ref_ptr<osg::Node> createOneFace(Point3F p1, Point3F p2, Point3F p3, Point3F p4,
double r = 1.0f, double g = 1.0f, double b = 1.0f,double a = 1.0f,
Point3F normal = Point3F(0.0f, 1.0f, 0.0f));
// 创建一个长方体,输入中心点坐标,输入宽度,输入长度,输入颜色
static osg::ref_ptr<osg::Node> createOneCuboid(Point3F centerP, double width, double height, double length,
double r = 1.0f, double g = 1.0f, double b = 1.0f,double a = 1.0f);
public:
static QString debugInfo(Point3F point3f);
};
#endif // OSGMANAGER_H
#include "OsgManager.h"
#include <QDebug>
#include <QDateTime>
//#define LOG qDebug()<<__FILE__<<__LINE__
//#define LOG qDebug()<<__FILE__<<__LINE__<<__FUNCTION__
//#define LOG qDebug()<<__FILE__<<__LINE__<<QThread()::currentThread()
//#define LOG qDebug()<<__FILE__<<__LINE__<<QDateTime::currentDateTime().toString("yyyy-MM-dd")
#define LOG qDebug()<<__FILE__<<__LINE__<<QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz")
OsgManager::OsgManager()
{
}
osg::ref_ptr<osg::Node> OsgManager::createTunnel(Point3F centerP, double width, double height, double length, double thickness)
{
LOG << "隧道的中心点:" << debugInfo(centerP) << ", 宽度:" << width << "高度:" << height << "长度" << length;
/**
// 上
// =====
// // \\
// ___ ___
// | | | |
// 左 | | | | 右
// | | | |
// ___ ___
**/
osg::ref_ptr<osg::Group> pGroup = new osg::Group;
// 绘制左边部件
{
// 横向左是x轴正,里外外是y轴正,纵向上是z轴正
// 计算左侧部件的中心点、宽度、高度、长度
Point3F leftCenterP;
leftCenterP.x = centerP.x - width / 2;
leftCenterP.z = centerP.z;
leftCenterP.y = centerP.y;
LOG << "(" << leftCenterP.x << "," << leftCenterP.y << "," << leftCenterP.z << ")" << thickness << height << length;
// 创建长方体
pGroup->addChild(createOneCuboid(leftCenterP, thickness, height, length));
}
// 绘制右侧部件
{
// 横向左是x轴正,里外外是y轴正,纵向上是z轴正
// 计算左侧部件的中心点、宽度、高度、长度
Point3F rightCenterP;
rightCenterP.x = centerP.x + width / 2;
rightCenterP.z = centerP.z;
rightCenterP.y = centerP.y;
LOG << "(" << rightCenterP.x << "," << rightCenterP.y << "," << rightCenterP.z << ")" << thickness << height << length;
// 创建长方体
pGroup->addChild(createOneCuboid(rightCenterP, thickness, height, length));
}
// 顶部部件(注意:暂时用一个长方体替代)
{
// 横向左是x轴正,里外外是y轴正,纵向上是z轴正
// 计算左侧部件的中心点、宽度、高度、长度
Point3F topCenterP;
topCenterP.x = centerP.x;
topCenterP.z = centerP.z + height / 2 + thickness / 2;
topCenterP.y = centerP.y;
LOG << "(" << topCenterP.x << "," << topCenterP.y << "," << topCenterP.z << ")" << thickness << height << length;
// 创建长方体
pGroup->addChild(createOneCuboid(topCenterP, width + thickness, thickness, length));
}
return pGroup.get();
}
osg::ref_ptr<osg::Node> OsgManager::createOneFace(Point3F p1, Point3F p2, Point3F p3, Point3F p4,
double r, double g, double b, double a,
Point3F normal)
{
// 绘制面
osg::ref_ptr<osg::Geode> pGeode = new osg::Geode;
{
// 创建一个用户保存几何信息的对象
osg::ref_ptr<osg::Geometry> pGeometry = new osg::Geometry;
// 创建两个顶点的数组
osg::ref_ptr<osg::Vec3Array> pVec3Array = new osg::Vec3Array;
// 顶点关联
pGeometry->setVertexArray(pVec3Array.get());
// 添加顶点
{
pVec3Array->push_back(osg::Vec3(p1.x, p1.y, p1.z));
pVec3Array->push_back(osg::Vec3(p2.x, p2.y, p2.z));
pVec3Array->push_back(osg::Vec3(p3.x, p3.y, p3.z));
pVec3Array->push_back(osg::Vec3(p4.x, p4.y, p4.z));
}
// 创建种颜色的数据
osg::ref_ptr<osg::Vec4Array> pVec4Array = new osg::Vec4Array;
// 颜色关联
pGeometry->setColorArray(pVec4Array.get());
{
// 设置绑定方式颜色:所有顶点都绑定在一个颜色上(注意:此处若不绑定画笔,则表示使用之前绑定的画笔)
pGeometry->setColorBinding(osg::Geometry::BIND_OVERALL);
pVec4Array->push_back(osg::Vec4(r, g, b, a));
}
// 为唯一的法线创建一个数组 法线: normal
osg::ref_ptr<osg::Vec3Array> pVec3ArrayNormal = new osg::Vec3Array;
pGeometry->setNormalArray(pVec3ArrayNormal.get());
{
pGeometry->setNormalBinding(osg::Geometry::BIND_OVERALL);
pVec3ArrayNormal->push_back(osg::Vec3(normal.x, normal.y, normal.z));
}
// 由保存的数据绘制2顶点的直线(注意:传入数据量不是直线数量,而是顶点数量,2个顶线一根线)
pGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, pVec3Array->size()));
// pGeometry->setDataVariance(osg::Object::DYNAMIC);
// 入坑: 一直动态不刷新,写了这条之后,禁用显示列表就可以了
pGeometry->setUseDisplayList(false);
// 向Geode类添加几何体(Drawable)
pGeode->addDrawable(pGeometry.get());
}
return pGeode.get();
}
osg::ref_ptr<osg::Node> OsgManager::createOneCuboid(Point3F centerP, double width, double height, double length,
double r, double g, double b, double a)
{
LOG << "长方体的中心点:" << debugInfo(centerP) << ", 宽度:" << width << "高度:" << height << "长度" << length;
osg::ref_ptr<osg::Group> pGroup = new osg::Group;
{
osg::ref_ptr<osg::Group> pGroupLeft = new osg::Group;
// 左侧的中心点计算
// 横向左是x轴正,里外外是y轴正,纵向上是z轴正
double x = centerP.x - width / 2;
double y = centerP.y - length / 2;
double z = centerP.z - height / 2;
LOG << centerP.z << height;
// 左侧长方体的8点计算
// 注意:这里点的左右保持视角相同,是正向观看,所以前后得左边都在屏幕左边
Point3F frontLeftTop = Point3F(x , y , z + height);
Point3F frontRightTop = Point3F(x + width, y , z + height);
Point3F frontRightBottom = Point3F(x + width, y , z );
Point3F frontLeftBottom = Point3F(x , y , z );
Point3F behindLeftTop = Point3F(x , y + length, z + height);
Point3F behindRightTop = Point3F(x + width, y + length, z + height);
Point3F behindRightBottom = Point3F(x + width, y + length, z );
Point3F behindLeftBottom = Point3F(x , y + length, z );
// 创建面具体操作
{
// 这里得方向是正对正方体
osg::ref_ptr<osg::Node> pNodeFaceFront;
osg::ref_ptr<osg::Node> pNodeFaceRight;
osg::ref_ptr<osg::Node> pNodeFaceBehind;
osg::ref_ptr<osg::Node> pNodeFaceLeft;
osg::ref_ptr<osg::Node> pNodeFaceTop;
osg::ref_ptr<osg::Node> pNodeFaceBottom;
pNodeFaceFront = OsgManager::createOneFace(frontLeftTop , frontRightTop , frontRightBottom , frontLeftBottom,
1.0, 0.0, 0.0);
pNodeFaceRight = OsgManager::createOneFace(frontRightTop , behindRightTop , behindRightBottom, frontRightBottom,
0.0, 1.0, 0.0);
pNodeFaceBehind = OsgManager::createOneFace(behindRightTop , behindLeftTop , behindLeftBottom , behindRightBottom,
0.0, 0.0, 1.0);
pNodeFaceLeft = OsgManager::createOneFace(behindLeftTop , behindLeftBottom , frontLeftBottom , frontLeftTop,
1.0, 1.0, 0.0);
pNodeFaceTop = OsgManager::createOneFace(behindLeftTop , behindRightTop , frontRightTop , frontLeftTop,
0.0, 1.0, 1.0);
pNodeFaceBottom = OsgManager::createOneFace(behindLeftBottom, behindRightBottom, frontRightBottom , frontLeftBottom,
1.0, 0.0, 1.0);
pGroupLeft->addChild(pNodeFaceFront);
pGroupLeft->addChild(pNodeFaceRight);
pGroupLeft->addChild(pNodeFaceBehind);
pGroupLeft->addChild(pNodeFaceLeft);
pGroupLeft->addChild(pNodeFaceTop);
pGroupLeft->addChild(pNodeFaceBottom);
}
pGroup->addChild(pGroupLeft);
}
return pGroup.get();
}
QString OsgManager::debugInfo(Point3F point3f)
{
return QString("(%1, %2, %3)").arg(point3f.x).arg(point3f.y).arg(point3f.z);
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步