一、环境配置
新建QT空项目
添加QT Model
记得加入osgQT.lib到附加依赖项里面
二、代码
代码来源:OSG的b站小讲堂
main.cpp
#include <QApplication>
#include "mainWindow.h"
#include "ListWidget.h"
int main(int argc, char** argv)
{
QApplication app(argc, argv);
//CMainWindow为qt和osg结合类
CMainWindow mainWindow;
//CListWidget为列表展示
CListWidget listWidget(&mainWindow);
mainWindow.setGeometry(100, 100, 800, 600);
mainWindow.show();
return app.exec();
}
?mainWindow.cpp
#include <osgGA/TrackballManipulator>
#include <osgQt/GraphicsWindowQt>
#include <osgGA/StateSetManipulator>
#include <osgViewer/ViewerEventHandlers>
#include <QApplication>
#include<osgDB/ReadFile>
#include "mainWindow.h"
CMainWindow::CMainWindow(QWidget* parent, Qt::WindowFlags f)
: QWidget(parent, f)
{
//根据qt版本决定使用单线程或多线程,以及qt应用程序属性
osgViewer::ViewerBase::ThreadingModel threadingModel;
#if QT_VERSION >= 0x050000
threadingModel = osgViewer::ViewerBase::SingleThreaded;
#else
threadingModel = osgViewer::ViewerBase::CullDrawThreadPerContext;
#endif
#if QT_VERSION >= 0x040800
if (threadingModel != osgViewer::ViewerBase::SingleThreaded)
QApplication::setAttribute(Qt::AA_X11InitThreads);
#endif
m_rpViewer = new osgViewer::Viewer;
m_rpViewer->setThreadingModel(threadingModel);//设置线程
m_rpViewer->setCameraManipulator(new osgGA::TrackballManipulator);//设置相机操作器
m_rpViewer->setKeyEventSetsDone(0);// disable the default setting of viewer.done() by pressing Escape.//设置不接受esc退出事件
m_rpViewer->addEventHandler(new osgViewer::StatsHandler);//添加s键事件
m_rpViewer->addEventHandler(new osgGA::StateSetManipulator(m_rpViewer->getCamera()->getOrCreateStateSet()));//添加w键事件
m_rpRoot = new osg::Group;
//m_rpRoot->addChild(osgDB::readNodeFile("clear.earth"));
m_rpViewer->setSceneData(m_rpRoot.get());
//初始化qt主窗口布局
m_pVLayout = new QVBoxLayout;
//表示控件与窗体的左右边距
m_pVLayout->setMargin(1);
//表示各个控件之间的上下间距
m_pVLayout->setSpacing(0);
m_pHLayout = new QHBoxLayout;
m_pHLayout->setMargin(0);
m_pHLayout->setSpacing(0);
//创建场景widget指针
QWidget* pSceneWidget = createGraphicsWindow(0, 0, 800, 600, "main window", true);
//最小尺寸
pSceneWidget->setMinimumSize(500, 500);
m_pHLayout->addWidget(pSceneWidget);
m_pVLayout->addLayout(m_pHLayout);
setLayout(m_pVLayout);
//设置每10ms更新场景
//connect(Sender,SIGNAL(signal),Receiver,SLOT(slot));
connect(&m_timer, SIGNAL(timeout()), this, SLOT(update())); //this指CMainWindow这个类
//10ms执行一次定时器
m_timer.start(10);
}
void CMainWindow::home()
{
if (m_rpViewer.valid() && m_rpViewer->getCameraManipulator())
{
m_rpViewer->getCameraManipulator()->home(0);
}
}
QWidget* CMainWindow::createGraphicsWindow(int nX, int nY, int nW, int nH, const std::string& strName, bool bWindowDecoration)
{
//显示设置
osg::DisplaySettings* pDS = osg::DisplaySettings::instance().get();
osg::ref_ptr<osg::GraphicsContext::Traits> pTraits = new osg::GraphicsContext::Traits(pDS);
//场景内容显示特征
pTraits->windowName = strName;//窗口名称
pTraits->windowDecoration = false;//窗口装饰
pTraits->overrideRedirect = true;//重定向
pTraits->x = nX;//x位置
pTraits->y = nY;//y位置
pTraits->width = nW;//宽
pTraits->height = nH;//高
pTraits->doubleBuffer = true;//双缓存
pTraits->alpha = pDS->getMinimumNumAlphaBits();
pTraits->stencil = pDS->getMinimumNumStencilBits();//模具
pTraits->sampleBuffers = pDS->getMultiSamples();//采样缓存
pTraits->samples = pDS->getNumMultiSamples();
osgQt::GraphicsWindowQt* pGW = new osgQt::GraphicsWindowQt(pTraits.get());//新建窗口
if (!pGW)
{
return nullptr;
}
if (!m_rpViewer)
{
return nullptr;
}
osg::Camera* pCamera = m_rpViewer->getCamera();
if (!pCamera)
{
return nullptr;
}
pCamera->setGraphicsContext(pGW);
pCamera->setClearColor(osg::Vec4(0.2, 0.2, 0.6, 1.0));
pCamera->setViewport(new osg::Viewport(0, 0, pTraits->width, pTraits->height));
//设置远近裁截面
pCamera->setProjectionMatrixAsPerspective(30.0f, static_cast<double>(pTraits->width) / static_cast<double>(pTraits->height), 1.0f, 10000.0f);
return pGW->getGLWidget();
}
void CMainWindow::paintEvent(QPaintEvent* event)
{
m_rpViewer->frame();
}
?mainWindow.h
/**************************************************************************************************
* @file name 文件名:MainWindow.h
* @note 描述:主界面
* @author 作者:z00105
* @data 创建时间:2021 -2 -23
**************************************************************************************************/
#ifndef MAIN_WINDOW_H
#define MAIN_WINDOW_H
#include <QBoxLayout>
#include <QTimer>
#include <QWidget>
#include <osgViewer/Viewer>
//#include <CommonLib/MainWindow/Export.h>
/**
* @class 类名:CMainWindow
* @brief 简要说明:主窗口显示
* @note详细说明:
* @author 作者:z00105
*/
class CMainWindow : public QWidget
{
public:
/**
* @brief 简要说明:主窗口的初始化
* @note 详细说明:
* @param parent [in]:父窗口
* @param f [in]:窗口属性
*/
CMainWindow(QWidget* parent = 0, Qt::WindowFlags f = 0);
/**
* @brief 简要说明:获取视景器
* @note 详细说明:
* @return m_rpViewer:场景视景器
*/
osgViewer::Viewer* getViewer() { return m_rpViewer.get(); }
/**
* @brief 简要说明:获取根节点
* @note 详细说明:
* @return m_rpRoot:场景根节点
*/
osg::Group* getRoot() { return m_rpRoot.get(); }
/**
* @brief 简要说明:获取主窗口垂直布局
* @note 详细说明:
* @return m_pVLayout:主窗口垂直布局
*/
QVBoxLayout* getVLayout() { return m_pVLayout; }
/**
* @brief 简要说明:获取主窗口水平布局
* @note 详细说明:
* @return m_pVLayout:主窗口水平布局
*/
QHBoxLayout* getHLayout() { return m_pHLayout; }
/**
* @brief 简要说明:视口复位
* @note 详细说明:三维窗口的视口回到初始设置的位置
* @return :
*/
void home();
protected:
/**
* @brief 简要说明:三维窗口与qt窗口的结合
* @note 详细说明:
* @param nX [in]:x位置
* @param nY [in]:y位置
* @param nW [in]:宽度
* @param nH [in]:高度
* @param strName [in]:窗口名
* @param bWindowDecoration [in]:是否装饰
* @return QWidget:三维与qt结合的窗口
*/
QWidget* createGraphicsWindow(int nX, int nY, int nW, int nH, const std::string& strName = "", bool bWindowDecoration = false);
/**
* @brief 简要说明:绘制事件
* @note 详细说明:qt的窗口绘制事件,用于三维场景的刷新
* @param event [in]:绘制事件
* @return 返回值以及说明:
*/
virtual void paintEvent(QPaintEvent* event);
protected:
osg::ref_ptr<osgViewer::Viewer> m_rpViewer; //视景器
osg::ref_ptr<osg::Group> m_rpRoot; //根节点
QVBoxLayout* m_pVLayout; //垂直布局
QHBoxLayout* m_pHLayout; //水平布局
QTimer m_timer; //定时器
};
#endif MAIN_WINDOW_H
ListWidget.cpp?
#include <QFileDialog>
#include <osg/MatrixTransform>
#include "mainWindow.h"
#include "ModelObject.h"
#include "PropertyWidget.h"
#include "ListWidget.h"
//通过Q_DECLARE_METATYPE声明后,就可以让自定义的类型设置到QVariant
Q_DECLARE_METATYPE(CModelObject*)
CListWidget::CListWidget(CMainWindow* pMainWindow)
:m_pMainWindow(pMainWindow)
, m_pListWidget(nullptr)
, m_pAxesItem(nullptr)
, m_pCurItem(nullptr)
, m_pMenu(nullptr)
, m_pAddAction(nullptr)
, m_pDelAction(nullptr)
, m_pClearAction(nullptr)
, m_pPropertyAction(nullptr)
{
//创建列表控件
m_pListWidget = new QListWidget;
m_pListWidget->setContextMenuPolicy(Qt::CustomContextMenu);//菜单格式
m_pListWidget->setFixedWidth(120);//固定宽度
m_pListWidget->setStyleSheet("QListWidget { background-color: rgba(255,255,255,100); font-size:12px; border: 1px solid rgba(249,133,0,255);}");//样式配置
m_pMainWindow->getHLayout()->insertWidget(0, m_pListWidget);//插入列表到主窗口0位置
//添加坐标轴到三维场景
osg::ref_ptr<CModelObject> rpModelObject = new CModelObject("axes.osgt");
rpModelObject->setMatrix(osg::Matrix::scale(1, 1, 1));
m_pMainWindow->getRoot()->addChild(rpModelObject.get());
//添加坐标轴到列表
m_pAxesItem = new QListWidgetItem(QString::fromLocal8Bit("坐标轴"));//新建列表项
m_pAxesItem->setCheckState(Qt::Checked);//设置为已选
m_pAxesItem->setData(Qt::UserRole, QVariant::fromValue(rpModelObject.get()));//设置用户数据绑定到选项
m_pListWidget->addItem(m_pAxesItem);//添加到列表
m_pMainWindow->home();//视点重置
//信号槽连接,属性窗口应用,模型显隐设置
connect(m_pListWidget, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(slotShowMenu(const QPoint &)));//绑定鼠标点击事件信号槽
connect(m_pListWidget, SIGNAL(itemClicked(QListWidgetItem *)), this, SLOT(slotVisible(QListWidgetItem *)));//绑定选项勾选状态信号槽
m_pMenu = new QMenu(m_pListWidget);//新建菜单
m_pMenu->setStyleSheet("QMenu { background-color: rgba(255,255,255,100); font-size:12px; border:1px solid rgba(249,133,0,255);}");//设置样式表
m_pAddAction = new QAction(QString::fromLocal8Bit("添加"), m_pMenu);//添加按钮动作
connect(m_pAddAction, SIGNAL(triggered()), this, SLOT(slotAdd()));//绑定信号槽
m_pDelAction = new QAction(QString::fromLocal8Bit("删除"), m_pMenu);//添加删除动作
connect(m_pDelAction, SIGNAL(triggered()), this, SLOT(slotDel()));
m_pClearAction = new QAction(QString::fromLocal8Bit("清空"), m_pMenu);//添加清空动作
connect(m_pClearAction, SIGNAL(triggered()), this, SLOT(slotClear()));
m_pPropertyAction = new QAction(QString::fromLocal8Bit("属性"), m_pMenu);//添加属性动作
connect(m_pPropertyAction, SIGNAL(triggered()), this, SLOT(slotProperty()));
m_pMenu->addAction(m_pAddAction);//添加动作
m_pMenu->addAction(m_pDelAction);
m_pMenu->addAction(m_pClearAction);
m_pMenu->addAction(m_pPropertyAction);
}
CListWidget::~CListWidget()
{
}
void CListWidget::slotShowMenu(const QPoint &pos)
{
m_pCurItem = m_pListWidget->currentItem();
if (m_pCurItem)//所选位置是列表项
{
if (m_pCurItem == m_pAxesItem)//如果是坐标轴,则不显示删除事件
{
m_pDelAction->setVisible(false);
}
else
{
m_pDelAction->setVisible(true);
}
m_pAddAction->setVisible(true);
m_pClearAction->setVisible(true);
m_pPropertyAction->setVisible(true);
}
else
{
//添加动作
m_pAddAction->setVisible(true);
//删除动作
m_pDelAction->setVisible(false);
//清除动作
m_pClearAction->setVisible(true);
//属性动作
m_pPropertyAction->setVisible(false);
}
m_pMenu->exec(m_pListWidget->mapToGlobal(pos));//显示菜单到鼠标点击的位置
}
void CListWidget::slotAdd()
{
QStringList strPathList = QFileDialog::getOpenFileNames(m_pMainWindow, QString::fromLocal8Bit("添加模型"), ".", "*.ive *.osg *.osgt *.3ds");//通过打开资源管理窗口添加模型
foreach(auto strPath, strPathList)
{
addModel(strPath);
}
}
void CListWidget::addModel(const QString& strPath)
{
osg::ref_ptr<CModelObject> rpModelObject = new CModelObject(strPath);
m_pMainWindow->getRoot()->addChild(rpModelObject.get());
QStringList strList = strPath.split("/");
if (strList.size() < 2)
{
strList = strPath.split("\\");
}
QListWidgetItem* m_pItem = new QListWidgetItem(strList.back());
m_pItem->setCheckState(Qt::Checked);
m_pItem->setData(Qt::UserRole, QVariant::fromValue(rpModelObject.get()));
m_pListWidget->addItem(m_pItem);
}
void CListWidget::addModel(const QString& strName, osg::Node* pNode)
{
if (pNode)
{
osg::ref_ptr<CModelObject> rpModelObject = new CModelObject(pNode);
m_pMainWindow->getRoot()->addChild(rpModelObject.get());
QListWidgetItem* m_pItem = new QListWidgetItem(strName);
m_pItem->setCheckState(Qt::Checked);
m_pItem->setData(Qt::UserRole, QVariant::fromValue(rpModelObject.get()));
m_pListWidget->addItem(m_pItem);
}
}
bool CListWidget::changeModelState(bool bState)
{
int nRow = m_pListWidget->model()->rowCount();
for (int i = 0; i < nRow; ++i)
{
auto pItem = m_pListWidget->item(i);
if (pItem)
{
CModelObject* pModelObject = pItem->data(Qt::UserRole).value<CModelObject*>();
if (pModelObject)
{
if (bState)
{
pItem->setCheckState(Qt::CheckState::Checked);
pModelObject->setNodeMask(0xffffffff);
}
else
{
pItem->setCheckState(Qt::CheckState::Unchecked);
pModelObject->setNodeMask(0x00000000);
}
}
}
}
return false;
}
void CListWidget::slotDel()
{
if (m_pCurItem)
{
del(m_pListWidget->row(m_pCurItem));
}
}
void CListWidget::slotClear()
{
int nRow = m_pListWidget->model()->rowCount();
for (int i = 1; i < nRow; ++i)
{
del(1);
}
}
void CListWidget::slotProperty()
{
CModelObject* pModelObject = m_pCurItem->data(Qt::UserRole).value<CModelObject*>();
if (pModelObject)
{
CPropertyWidget* pPropertyWidget = new CPropertyWidget(pModelObject, m_pMainWindow);
pPropertyWidget->show();
}
}
void CListWidget::slotVisible(QListWidgetItem * pItem)
{
if (pItem)
{
CModelObject* pModelObject = pItem->data(Qt::UserRole).value<CModelObject*>();
if (pModelObject)
{
if (pItem->checkState() == Qt::Checked)
{
pModelObject->setNodeMask(0xffffffff);
}
else if (pItem->checkState() == Qt::Unchecked)
{
pModelObject->setNodeMask(0x00000000);
}
}
}
}
void CListWidget::del(int nRow)
{
auto pItem = m_pListWidget->item(nRow);
if (pItem)
{
CModelObject* pModelObject = pItem->data(Qt::UserRole).value<CModelObject*>();
if (pModelObject)
{
m_pMainWindow->getRoot()->removeChild(pModelObject);
}
m_pListWidget->takeItem(nRow);
pItem = nullptr;
}
}
ListWidget.h?
#ifndef LIST_WIDGET_H
#define LIST_WIDGET_H
#include <osg/Node>
#include <QListWidget>
#include <QListWidgetItem>
#include <QMenu>
#include <QAction>
class CMainWindow;
class CListWidget : public QObject
{
Q_OBJECT
public:
/**
* @class 结构体名:SModelInfo
* @brief 简要说明:添加模型所需信息
* @note详细说明:bUseLLH决定是否使用vec3LLH
* @author 作者:z00105
*/
struct SModelInfo
{
//初始化数据
SModelInfo()
{
bUseLLH = false;
vec3Scale = osg::Vec3d(1.0,1.0,1.0);
}
bool bUseLLH; //是否使用经纬高
osg::Vec3d vec3LLH; //经纬高
osg::Vec3d vec3Scale; //模型缩放比例
osg::Vec3d vec3Rotate; //模型姿态
};
CListWidget(CMainWindow* pMainWindow);
~CListWidget();
/**
* @brief 简要说明:添加模型
* @note 详细说明:通过路径添加模型
* @param strPath [in]:绝对路径或相对data目录的路径
* @return :
*/
void addModel(const QString& strPat);
/**
* @brief 简要说明:添加模型
* @note 详细说明:模型名称和节点指针添加
* @param strName [in]:模型名称
* @param pNode [in]:模型节点
* @return :
*/
void addModel(const QString& strName,osg::Node* pNode);
/**
* @brief 简要说明:改变模型状态
* @note 详细说明:显隐控制
* @param bState [in]:模型状态
* @return :
*/
bool changeModelState(bool bState);
protected slots:
/**
* @brief 简要说明:显示右键菜单
* @note 详细说明:根据位置和选择的对象进行菜单显示
* @param pos [in]:位置
* @return :
*/
void slotShowMenu(const QPoint &pos);
/**
* @brief 简要说明:添加选项
* @note 详细说明:添加模型节点
* @return :
*/
void slotAdd();
/**
* @brief 简要说明:删除选项
* @note 详细说明:删除当前选中的列表项和三维场景中的对应节点
* @return :
*/
void slotDel();
/**
* @brief 简要说明:显示清除菜单
* @note 详细说明:
* @return :
*/
void slotClear();
/**
* @brief 简要说明:显示属性菜单
* @note 详细说明:
* @return :
*/
void slotProperty();
/**
* @brief 简要说明:设置选项对应控制节点的显隐
* @note 详细说明:通过选项控制三维场景节点显隐
* @param pItem [in]:列表项
* @return :
*/
void slotVisible(QListWidgetItem * pItem);
protected:
void del(int nRow);
protected:
CMainWindow* m_pMainWindow;//主窗口
QListWidget* m_pListWidget;//列表控件
QListWidgetItem* m_pAxesItem;//坐标轴项
QListWidgetItem* m_pCurItem;//当前项
QMenu* m_pMenu;//菜单
QAction* m_pAddAction;//添加动作
QAction* m_pDelAction;//删除动作
QAction* m_pClearAction;//清除动作
QAction* m_pPropertyAction;//属性动作
};
#endif LIST_WIDGET_H
ModelObject.cpp?
#include "ModelObject.h"
CModelObject::CModelObject(const QString& strPath)
{
osg::ref_ptr<osg::Node> rpNode = readNode(strPath.toStdString());
this->addChild(rpNode.get());
}
CModelObject::CModelObject( osg::Node* pNode )
{
this->addChild(pNode);
}
CModelObject::~CModelObject()
{
}
osg::Node* CModelObject::readNode(const std::string& strPath)
{
osg::ref_ptr<osg::Node> rpNode = osgDB::readNodeFile(strPath);//读取路径所在的模型
if (rpNode.valid())
{
rpNode->getOrCreateStateSet()->setMode(GL_RESCALE_NORMAL, osg::StateAttribute::ON);//重新设置节点规模后,重置法向量
}
return rpNode.release();//release()释放超级指针并传出节点指针
}
ModelObject.h
#ifndef MODEL_OBJECT_H
#define MODEL_OBJECT_H
#include <QString>
#include <osg/MatrixTransform>
#include <osgDB/ReadFile>
class CModelObject : public osg::MatrixTransform
{
public:
CModelObject(const QString& strPath);
CModelObject(osg::Node* pNode);
~CModelObject();
/**
* @brief 简要说明:读取模型
* @note 详细说明:根据路径,读取模型
* @param strPath [in]:路径信息,要求绝对路径
* @return :模型指针
*/
osg::Node* readNode(const std::string& strPath);
};
#endif MODEL_OBJECT_H
?PropertyWidget.cpp
#include <QLabel>
#include <QDoubleSpinBox>
#include "ModelObject.h"
#include "PropertyWidget.h"
CPropertyWidget::CPropertyWidget(CModelObject* pModelObject,QWidget* pParent)
:QWidget(pParent)
,m_pModelObject(pModelObject)
{
setWindowFlags(Qt::Dialog);
setAttribute(Qt::WA_DeleteOnClose);
QVBoxLayout* pVlayout = new QVBoxLayout;
this->setLayout(pVlayout);
osg::Matrix mat = m_pModelObject->getMatrix();
{
m_vecPosition = mat.getTrans();
QHBoxLayout* pHLayout = new QHBoxLayout;
pVlayout->addLayout(pHLayout);
QLabel* pLabel = new QLabel(QString::fromLocal8Bit("位移"));
pLabel->setFixedWidth(30);
pHLayout->addWidget(pLabel);
{
QDoubleSpinBox* pDSBox = new QDoubleSpinBox;
pDSBox->setRange(-10000,10000);
pDSBox->setValue(m_vecPosition.x());
connect(pDSBox,SIGNAL(valueChanged(double)),this,SLOT(slotTX(double)));
pHLayout->addWidget(pDSBox);
}
{
QDoubleSpinBox* pDSBox = new QDoubleSpinBox;
pDSBox->setRange(-10000,10000);
pDSBox->setValue(m_vecPosition.y());
connect(pDSBox,SIGNAL(valueChanged(double)),this,SLOT(slotTY(double)));
pHLayout->addWidget(pDSBox);
}
{
QDoubleSpinBox* pDSBox = new QDoubleSpinBox;
pDSBox->setRange(-10000,10000);
pDSBox->setValue(m_vecPosition.z());
connect(pDSBox,SIGNAL(valueChanged(double)),this,SLOT(slotTZ(double)));
pHLayout->addWidget(pDSBox);
}
}
{
Quat2DegreesRotate(mat.getRotate(),m_vecRotation);
QHBoxLayout* pHLayout = new QHBoxLayout;
pVlayout->addLayout(pHLayout);
QLabel* pLabel = new QLabel(QString::fromLocal8Bit("旋转"));
pLabel->setFixedWidth(30);
pHLayout->addWidget(pLabel);
{
QDoubleSpinBox* pDSBox = new QDoubleSpinBox;
pDSBox->setRange(-360,360);
pDSBox->setValue(m_vecRotation.x());
connect(pDSBox,SIGNAL(valueChanged(double)),this,SLOT(slotRX(double)));
pHLayout->addWidget(pDSBox);
}
{
QDoubleSpinBox* pDSBox = new QDoubleSpinBox;
pDSBox->setRange(-360,360);
pDSBox->setValue(m_vecRotation.y());
connect(pDSBox,SIGNAL(valueChanged(double)),this,SLOT(slotRY(double)));
pHLayout->addWidget(pDSBox);
}
{
QDoubleSpinBox* pDSBox = new QDoubleSpinBox;
pDSBox->setRange(-360,360);
pDSBox->setValue(m_vecRotation.z());
connect(pDSBox,SIGNAL(valueChanged(double)),this,SLOT(slotRZ(double)));
pHLayout->addWidget(pDSBox);
}
}
{
m_vecScale = mat.getScale();
QHBoxLayout* pHLayout = new QHBoxLayout;
pVlayout->addLayout(pHLayout);
QLabel* pLabel = new QLabel(QString::fromLocal8Bit("缩放"));
pLabel->setFixedWidth(30);
pHLayout->addWidget(pLabel);
{
QDoubleSpinBox* pDSBox = new QDoubleSpinBox;
pDSBox->setRange(0,10000);
pDSBox->setValue(m_vecScale.x());
connect(pDSBox,SIGNAL(valueChanged(double)),this,SLOT(slotSX(double)));
pHLayout->addWidget(pDSBox);
}
{
QDoubleSpinBox* pDSBox = new QDoubleSpinBox;
pDSBox->setRange(0,10000);
pDSBox->setValue(m_vecScale.y());
connect(pDSBox,SIGNAL(valueChanged(double)),this,SLOT(slotSY(double)));
pHLayout->addWidget(pDSBox);
}
{
QDoubleSpinBox* pDSBox = new QDoubleSpinBox;
pDSBox->setRange(0,10000);
pDSBox->setValue(m_vecScale.z());
connect(pDSBox,SIGNAL(valueChanged(double)),this,SLOT(slotSZ(double)));
pHLayout->addWidget(pDSBox);
}
}
}
CPropertyWidget::~CPropertyWidget()
{
}
osg::Vec3d CPropertyWidget::DegreesToRadians(const osg::Vec3& vecRotate)
{
osg::Vec3 vecRotateNew;
vecRotateNew.x() = osg::DegreesToRadians(vecRotate.x());
vecRotateNew.y() = osg::DegreesToRadians(vecRotate.y());
vecRotateNew.z() = osg::DegreesToRadians(vecRotate.z());
return vecRotateNew;
}
osg::Vec3d CPropertyWidget::RadiansToDegrees(const osg::Vec3& vecRotate)
{
osg::Vec3 vecRotateNew;
vecRotateNew.x() = osg::RadiansToDegrees(vecRotate.x());
vecRotateNew.y() = osg::RadiansToDegrees(vecRotate.y());
vecRotateNew.z() = osg::RadiansToDegrees(vecRotate.z());
return vecRotateNew;
}
void CPropertyWidget::Quat2DegreesRotate(const osg::Quat& quat, osg::Vec3& vecRotate)
{
Quat2RadiansRotate(quat, vecRotate);
vecRotate = RadiansToDegrees(vecRotate);
}
void CPropertyWidget::Quat2RadiansRotate(const osg::Quat& quat, osg::Vec3& vecRotate)
{
double q0 = quat.w();
double q1 = quat.x();
double q2 = quat.y();
double q3 = quat.z();
vecRotate.x() = float(atan2(2 * (q2*q3 + q0 * q1), (q0*q0 - q1 * q1 - q2 * q2 + q3 * q3)));
vecRotate.y() = float(asin(-2 * (q1*q3 - q0 * q2)));
vecRotate.z() = float(atan2(2 * (q1*q2 + q0 * q3), (q0*q0 + q1 * q1 - q2 * q2 - q3 * q3)));
}
osg::Matrix CPropertyWidget::DegreesRotate2Matrix(const osg::Vec3d& vecRotate)
{
return RadiansRotate2Matrix(DegreesToRadians(vecRotate));
}
osg::Matrix CPropertyWidget::RadiansRotate2Matrix(const osg::Vec3d& vecRotate)
{
return osg::Matrix::rotate(vecRotate.x(), osg::X_AXIS, vecRotate.y(), osg::Y_AXIS, vecRotate.z(), osg::Z_AXIS);
}
void CPropertyWidget::slotTX(double dValue)
{
m_vecPosition.x() = dValue;
updateMatrix();
}
void CPropertyWidget::slotTY(double dValue)
{
m_vecPosition.y() = dValue;
updateMatrix();
}
void CPropertyWidget::slotTZ(double dValue)
{
m_vecPosition.z() = dValue;
updateMatrix();
}
void CPropertyWidget::slotRX( double dValue )
{
m_vecRotation.x() = dValue;
updateMatrix();
}
void CPropertyWidget::slotRY( double dValue )
{
m_vecRotation.y() = dValue;
updateMatrix();
}
void CPropertyWidget::slotRZ( double dValue )
{
m_vecRotation.z() = dValue;
updateMatrix();
}
void CPropertyWidget::slotSX( double dValue )
{
m_vecScale.x() = dValue;
updateMatrix();
}
void CPropertyWidget::slotSY( double dValue )
{
m_vecScale.y() = dValue;
updateMatrix();
}
void CPropertyWidget::slotSZ( double dValue )
{
m_vecScale.z() = dValue;
updateMatrix();
}
void CPropertyWidget::updateMatrix()
{
m_pModelObject->setMatrix(osg::Matrix::scale(m_vecScale)*DegreesRotate2Matrix(m_vecRotation)*osg::Matrix::translate(m_vecPosition));
}
PropertyWidget.h?
#ifndef PROPERTY_WIDGET_H
#define PROPERTY_WIDGET_H
#include <QWidget>
#include<osg/Node>
#include "MainWindow.h"
class CModelObject;
class CPropertyWidget : public QWidget
{
Q_OBJECT
public:
CPropertyWidget(CModelObject* pModelObject,QWidget* pParent);
~CPropertyWidget();
/**
*@note: 度转弧度
*/
osg::Vec3d DegreesToRadians(const osg::Vec3& vecRotate);
/**
*@note: 弧度转度
*/
osg::Vec3d RadiansToDegrees(const osg::Vec3& vecRotate);
/**
*@note: 四元数转度欧拉角
*/
void Quat2DegreesRotate(const osg::Quat& quat, osg::Vec3& vecRotate);
/**
*@note: 四元数转弧度欧拉角
*/
void Quat2RadiansRotate(const osg::Quat& quat, osg::Vec3& vecRotate);
/**
*@note: 度欧拉角转旋转矩阵
*/
osg::Matrix DegreesRotate2Matrix(const osg::Vec3d& vecRotate);
/**
*@note: 弧度欧拉角转旋转矩阵
*/
osg::Matrix RadiansRotate2Matrix(const osg::Vec3d& vecRotate);
protected slots:
void slotTX(double dValue);
void slotTY(double dValue);
void slotTZ(double dValue);
void slotRX(double dValue);
void slotRY(double dValue);
void slotRZ(double dValue);
void slotSX(double dValue);
void slotSY(double dValue);
void slotSZ(double dValue);
protected:
void updateMatrix();
protected:
CModelObject* m_pModelObject;
osg::Vec3 m_vecPosition;
osg::Vec3 m_vecRotation;
osg::Vec3 m_vecScale;
};
#endif PROPERTY_WIDGET_H
代码下载: 博客资源里面
三、展示
|