最终效果
下载地址
github:https://github.com/yibobunengyuntian/Scene_Editor
百度网盘(bin目录含打包好的exe应用程序及场景):https://pan.baidu.com/s/1islrLbo2mdaNvzTcXVYY7Q?pwd=1008
目录
前话
Qt中有封装好的opengl窗口和函数接口 比较方便,不需要构建GLFW 和 配置GLAD等;此文章只关心模型加载之后的应用部分; opengl初学教程参考https://learnopengl-cn.github.io ;在qt中的教程直接csdn能搜到一些, 学习到加载模型不是问题。
opengl个人理解(可能有误):几乎所有三维图形在模型文件和计算机中的表现都可以看作是由三角形拼起来的, 而这些三角形, 需要大量的顶点来表示, 就有了opengl中的顶点数据, 当然一般情况顶点数据可能还包含 这个点的 颜色、法线、纹理(贴在这个模型上的图片)坐标等数据给顶点提供着色处理数据;而在opengl中, 需要的就是把这些顶点数据提供给显卡(分配显存),就对应了相关教程中的 顶点数组、顶点缓存等概念;将这些顶点数据传入显存后, 显卡并不明白你要将这些数据怎么处理,就需要写着色器(可以理解为几个车间轮流对这些数据加工)了,还需通过调相关函数, 指定处理方式(比如: 你可以指定你传入的每个顶点数据中, 前3个数值代表顶点坐标,后3个数值为法线方向, 最后两个为纹理坐标; 你也可以告诉显卡, 你想将这些点连接成线、画三角形、矩形等) ; 有了这些后, 显卡大概知道了你要画个什么东西,但是你想将这个图形展现在你的屏幕上希望出现的位置, 就对应了坐标变换等概念......
刚毕业那会儿开始写的, 陆陆续续搞了几个月, 遇到了些许问题未解决, 就一直拖着, 有点烂尾, 可能还会修改, 代码有点混乱, 后续有空可能会重新整理。
项目分析
当你能通过assimp加载模型之后, 此项目理解起来就很简单了; 无非就是多了点界面数据交互,加载了较多的模型, 然后改变这些模型的位置、旋转、缩放、材质信息, 在保存的时候将所有模型路径和这些数据写入到文件就完事了。
主要代码
RenderWgt
渲染窗口
renderwgt.h
#ifndef RENDERWGT_H
#define RENDERWGT_H
#include "plc.h"
class RenderWgt : public QOpenGLWidget, public GLFUNC
{
Q_OBJECT
public:
explicit RenderWgt(QWidget *parent = nullptr);
protected:
virtual void initializeGL() override;
virtual void resizeGL(int w,int h) override;
virtual void paintGL() override;
virtual void wheelEvent(QWheelEvent *pEvent) override;
virtual void mousePressEvent(QMouseEvent *pEvent) override;
virtual void mouseMoveEvent(QMouseEvent *pEvent) override;
virtual void mouseReleaseEvent(QMouseEvent *pEvent) override;
virtual void mouseDoubleClickEvent(QMouseEvent *pEvent) override;
virtual void keyPressEvent(QKeyEvent *event) override;
virtual void keyReleaseEvent(QKeyEvent *event) override;
void dropEvent(QDropEvent *event) override; //放下动作
void dragEnterEvent(QDragEnterEvent *event) override; //托到进入窗口动作
void dragMoveEvent(QDragMoveEvent *event) override; //拖着物体在窗口移动
void dragLeaveEvent(QDragLeaveEvent *event) override; //拖走了没有释放
void initialize();
void initializeShader();
void createFloor();
void createDepthTexture();
void loadWorld();
void loadModel();
void renderDepthMap();
void renderNode();
public:
QVector4D worldPosFromViewPort(int posX, int posY);
void setBackgroundColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a = 1.0);
public slots:
void addModelByFile();
void setLightDir(QVector3D dir){
m_lightDir = dir;
}
void setUseCameraDir(bool is){m_isUseCameraDir = is;}
void setHiddenShadow(bool is){m_isDepthMap = is; m_isUpDateShadow = true;}
void setShadowUpDate(int n){m_shadowUpDate = n; m_isUpDateShadow = true;}
private:
QOpenGLShaderProgram m_ShaderProgram;
QOpenGLShaderProgram m_DepthMapShaderProgram;
CameraTool *m_pCameraTool = nullptr;
ViewCube *m_pViewCube = nullptr;
QMatrix4x4 m_projection;
private:
QTimer timer;
// Camera camera;
bool m_isKeyCtrlDown = false;
bool m_isMouseLeftDown = false;
bool m_isMouseRightDown = false;
bool m_isSelectManipulator = false;
QPoint m_mouseRightDownPos;
QCursor cursor;
QVector3D m_oldDir;
float yaw = 0; //偏航角
float pitch = 0; //俯视角
float sensitivity = 0.005f; //鼠标灵敏度
QMap<Qt::Key, bool> m_keys;
Node *m_pLoadModel = nullptr;
QList<Node *> m_loadModelList;
Node *m_pCopyNode = nullptr;
Node *m_pTmpNode = nullptr;
bool m_isLoadModel = false;
QString m_modelPath;
TipWgt *m_pTip = nullptr;
bool m_isCopyModel = false;
bool m_isMouseMoveCamera = false;
bool m_isUseCameraDir = false;
bool m_isDepthMap = false;
bool m_isUpDateShadow = true;
QVector3D m_lightDir = QVector3D(-0.2f, -1.0f, -0.3f);
QVector4D m_backgroundColor = QVector4D(0, 0.4f, 0.6f, 1.0f);
const unsigned int m_SHADOW_WIDTH = 10240, m_SHADOW_HEIGHT = 10240;
unsigned int m_depthMapFBO;
unsigned int m_depthMap;
int m_shadowUpDate = 0;
QVector3D m_tmpLightDir;
QMutex m_loadModelMutex;
};
#endif // RENDERWGT_H
renderwgt.cpp
#include "renderwgt.h"
RenderWgt::RenderWgt(QWidget *parent) :
QOpenGLWidget(parent)
{
setAcceptDrops(true); /* 允许拖放 */
setFocusPolicy(Qt::ClickFocus);
setFocusPolicy(Qt::StrongFocus);
setFocus();
initialize();
}
void RenderWgt::initializeGL()
{
// 创建着色器程序对象
initializeOpenGLFunctions();
initializeShader();
g_PropertyManager->camera()->init();
m_pCameraTool->setData(g_PropertyManager->camera()->getMoveSpeed(), g_PropertyManager->camera()->getCameraPos());
createDepthTexture();
// 开启剔除操作效果
// glEnable(GL_CULL_FACE);
//禁用背面的的光照和阴影效果,避免不必要的计算
glCullFace(GL_BACK);
glEnable(GL_MULTISAMPLE);
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); // 可以根据需要设置不同的提示参数
glEnable(GL_DEPTH_TEST);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
createFloor();
}
void RenderWgt::resizeGL(int w, int h)
{
glViewport(0,0,w,h); //定义视口区域
m_projection.setToIdentity();
m_projection.perspective(45.0f,width()/float(height()),CAM_NEAR,CAM_FAR);
g_PropertyManager->camera()->setProjection(m_projection);
m_pViewCube->move(w - m_pViewCube->size().width(), 0);
}
void RenderWgt::paintGL()
{
glClearColor(m_backgroundColor.x(), m_backgroundColor.y(), m_backgroundColor.z(), m_backgroundColor.w()); // 背景颜色
// 开启模板测试
glEnable(GL_STENCIL_TEST);
// 指定如何更新模板缓冲区的值
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
// 不允许向模板缓冲区写入值
glStencilMask(0x00);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
loadWorld();
loadModel();
if(g_PropertyManager->manipulator())
{
g_PropertyManager->manipulator()->setupGlFunc(QOpenGLContext::currentContext()->versionFunctions<GLFUNC>());
}
if(m_isCopyModel && g_PropertyManager->selectNode() != nullptr)
{
m_isCopyModel = false;
}
emit g_PropertyManager->renderLogic();
if(m_isUseCameraDir)
{
m_tmpLightDir = g_PropertyManager->camera()->getDir().normalized();
}
else
{
m_tmpLightDir = m_lightDir.normalized();
}
renderDepthMap();
renderNode();
}
void RenderWgt::wheelEvent(QWheelEvent *pEvent)
{
int i = pEvent->angleDelta().y()/120;
if(i < 0)
{
for(int j = 0; j < -i; ++j)
{
g_PropertyManager->camera()->moveCamera(CAMERA_MOVE_DIR::FRONT);
}
}
else
{
for(int j = 0; j < i; ++j)
{
g_PropertyManager->camera()->moveCamera(CAMERA_MOVE_DIR::BACK);
}
}
m_pCameraTool->setData(g_PropertyManager->camera()->getMoveSpeed(), g_PropertyManager->camera()->getCameraPos());
if(m_shadowUpDate == 2)
{
m_isUpDateShadow = true;
}
}
void RenderWgt::mousePressEvent(QMouseEvent *pEvent)
{
switch (pEvent->button())
{
case Qt::LeftButton:
{
if(m_isMouseRightDown == false)
{
if(m_isCopyModel && m_pTmpNode)
{
m_pTmpNode->setHideMesh(true);
// g_PropertyManager->addNode(m_pTmpNode);
g_PropertyManager->undoStack()->push(new UndoCommandAddNode(m_pTmpNode, "add node::" + m_pTmpNode->name()));
m_pTmpNode = g_PropertyManager->copyNode(m_pCopyNode);
m_pTmpNode->setHideMesh(false);
m_isLoadModel = true;
return;
}
m_isMouseLeftDown = true;
setMouseTracking(true); //开启鼠标追踪
if(g_PropertyManager->manipulator() && g_PropertyManager->selectNode())
{
m_isSelectManipulator = g_PropertyManager->manipulator()->mouseDetection(this->mapFromGlobal(QCursor::pos()), this->width(), this->height());
if(m_isSelectManipulator)
{
g_PropertyManager->manipulator()->setMouesPressPos(this->mapFromGlobal(QCursor::pos()));
g_PropertyManager->manipulator()->setIsMouesPress(true);
}
//qDebug() << m_isSelectManipulator;
}
else
{
m_isMouseMoveCamera = true;
}
}
}
break;
case Qt::RightButton:
{
m_oldDir = g_PropertyManager->camera()->getDir();
m_mouseRightDownPos = QCursor::pos();
setCursor(Qt::BlankCursor); //隐藏鼠标光标
//QCursor::setPos(geometry().center()); //将鼠标移动窗口中央
setMouseTracking(true); //开启鼠标追踪
m_isMouseLeftDown = false;
m_isMouseRightDown = true;
}
break;
default:
break;
}
}
void RenderWgt::mouseMoveEvent(QMouseEvent *pEvent)
{
Q_UNUSED(pEvent)
if(m_isMouseRightDown)
{
float xoffset = QCursor::pos().x() - m_mouseRightDownPos.x();
float yoffset = m_mouseRightDownPos.y() - QCursor::pos().y();
g_PropertyManager->camera()->setDir(xoffset, yoffset);
QCursor::setPos(m_mouseRightDownPos);
m_pViewCube->setModelMat(g_PropertyManager->camera()->getDir(), g_PropertyManager->camera()->getUp());
return;
}
if(m_isCopyModel && m_pTmpNode)
{
QVector4D worldPostion=worldPosFromViewPort(pEvent->pos().x(),
pEvent->pos().y());
if(worldPostion.w() > 1.2)
{
m_pTmpNode->setHide(true);
return;
}
m_pTmpNode->setTranslate(worldPostion.toVector3D());
m_pTmpNode->setHide(false);
return;
}
if(g_PropertyManager->manipulator() != nullptr && g_PropertyManager->selectNode() != nullptr)
{
g_PropertyManager->manipulator()->mouseDetection(this->mapFromGlobal(QCursor::pos()), this->width(), this->height());
if(m_isSelectManipulator)
{
g_PropertyManager->manipulator()->transformByMouesmove(this->mapFromGlobal(QCursor::pos()), this->width(), this->height());
g_PropertyManager->nodeEditWgt()->update();
}
}
if(m_isMouseMoveCamera)
{
}
}
void RenderWgt::mouseReleaseEvent(QMouseEvent *pEvent)
{
switch (pEvent->button())
{
case Qt::LeftButton:
{
m_isMouseLeftDown = false;
m_isSelectManipulator = false;
m_isMouseMoveCamera = false;
if(g_PropertyManager->manipulator())
{
g_PropertyManager->manipulator()->setIsMouesPress(false);
}
}
break;
case Qt::RightButton:
{
QCursor::setPos(m_mouseRightDownPos);
setCursor(cursor); //恢复鼠标光标
m_isMouseRightDown = false;
}
break;
default:
break;
}
}
void RenderWgt::mouseDoubleClickEvent(QMouseEvent *pEvent)
{
if(pEvent->button() == Qt::LeftButton)
{
if(m_isCopyModel && m_pTmpNode)
{
return;
}
//m_isMouseLeftDown = false;
QVector4D worldPostion=worldPosFromViewPort(pEvent->pos().x(), pEvent->pos().y());
QVector4D pos = m_projection * g_PropertyManager->camera()->getView() * worldPostion;
pos/=pos.w();
foreach(auto node, g_PropertyManager->nodes())
{
node->selectNode(worldPostion);
// if(selectNode)
// {
// g_PropertyManager->selectNode(selectNode);
// return;
// }
}
if(g_PropertyManager->selectTmpNodes().size()>0)
{
g_PropertyManager->selectNode(g_PropertyManager->selectTmpNodes().first());
g_PropertyManager->removeSelectTmpNodes();
return;
}
g_PropertyManager->selectNode(nullptr);
}
if(pEvent->button() == Qt::RightButton)
{
if(m_isCopyModel && m_pTmpNode)
{
delete []m_pTmpNode;
m_pTmpNode = nullptr;
m_isCopyModel = false;
}
m_oldDir = g_PropertyManager->camera()->getDir();
m_mouseRightDownPos = QCursor::pos();
setCursor(Qt::BlankCursor); //隐藏鼠标光标
//QCursor::setPos(geometry().center()); //将鼠标移动窗口中央
setMouseTracking(true); //开启鼠标追踪
m_isMouseLeftDown = false;
m_isMouseRightDown = true;
}
}
void RenderWgt::keyPressEvent(QKeyEvent *event)
{
switch (event->key())
{
case Qt::Key_Control:
{
m_isKeyCtrlDown = true;
m_keys[Qt::Key_Control] = true;
}
break;
case Qt::Key_C:
{
if(m_isKeyCtrlDown && g_PropertyManager->selectNode() != nullptr)
{
m_isCopyModel = true;
m_pCopyNode = g_PropertyManager->selectNode();
m_pTmpNode = g_PropertyManager->copyNode(m_pCopyNode);
m_pTmpNode->setHideMesh(false);
m_isLoadModel = true;
g_PropertyManager->selectNode(nullptr);
}
}
break;
case Qt::Key_Z:
{
if(m_isKeyCtrlDown)
{
g_PropertyManager->undoStack()->undo();
}
}
break;
case Qt::Key_Y:
{
if(m_isKeyCtrlDown)
{
g_PropertyManager->undoStack()->redo();
}
}
break;
case Qt::Key_Delete:
{
if(g_PropertyManager->selectNode() != nullptr)
{
Node *node = g_PropertyManager->selectNode();
g_PropertyManager->selectNode(nullptr);
// g_PropertyManager->delNode(node);
g_PropertyManager->undoStack()->push(new UndoCommandDelNode(node, "del node::" + node->name()));
}
}
break;
case Qt::Key_W:
{
m_keys[Qt::Key_W] = true;
m_keys[Qt::Key_S] = false;
}
break;
case Qt::Key_S:
{
m_keys[Qt::Key_S] = true;
m_keys[Qt::Key_W] = false;
}
break;
case Qt::Key_A:
{
m_keys[Qt::Key_A] = true;
m_keys[Qt::Key_D] = false;
}
break;
case Qt::Key_D:
{
m_keys[Qt::Key_D] = true;
m_keys[Qt::Key_A] = false;
}
break;
case Qt::Key_E:
{
m_keys[Qt::Key_E] = true;
m_keys[Qt::Key_Q] = false;
}
break;
case Qt::Key_Q:
{
m_keys[Qt::Key_Q] = true;
m_keys[Qt::Key_E] = false;
}
break;
case Qt::Key_Up:
{
m_keys[Qt::Key_Up] = true;
m_keys[Qt::Key_Down] = false;
}
break;
case Qt::Key_Down:
{
m_keys[Qt::Key_Down] = true;
m_keys[Qt::Key_Up] = false;
}
break;
case Qt::Key_Left:
{
m_keys[Qt::Key_Left] = true;
m_keys[Qt::Key_Right] = false;
}
break;
case Qt::Key_Right:
{
m_keys[Qt::Key_Right] = true;
m_keys[Qt::Key_Left] = false;
}
break;
default:
break;
}
bool isShadowUpDate = false;
for (QMap<Qt::Key, bool>::const_iterator it = m_keys.constBegin(); it != m_keys.constEnd(); it++)
{
if(it.value())
{
switch (it.key())
{
case Qt::Key_W:
{
g_PropertyManager->camera()->moveCamera(CAMERA_MOVE_DIR::FRONT);
isShadowUpDate = true;
}
break;
case Qt::Key_S:
{
g_PropertyManager->camera()->moveCamera(CAMERA_MOVE_DIR::BACK);
isShadowUpDate = true;
}
break;
case Qt::Key_A:
{
g_PropertyManager->camera()->moveCamera(CAMERA_MOVE_DIR::LEFT);
isShadowUpDate = true;
}
break;
case Qt::Key_D:
{
g_PropertyManager->camera()->moveCamera(CAMERA_MOVE_DIR::RIGHT);
isShadowUpDate = true;
}
break;
case Qt::Key_E:
{
g_PropertyManager->camera()->moveCamera(CAMERA_MOVE_DIR::UP);
isShadowUpDate = true;
}
break;
case Qt::Key_Q:
{
g_PropertyManager->camera()->moveCamera(CAMERA_MOVE_DIR::DOWN);
isShadowUpDate = true;
}
break;
case Qt::Key_Up:
{
g_PropertyManager->camera()->setDir(0, 5);
m_pViewCube->setModelMat(g_PropertyManager->camera()->getDir(), g_PropertyManager->camera()->getUp());
}
break;
case Qt::Key_Down:
{
g_PropertyManager->camera()->setDir(0, -5);
m_pViewCube->setModelMat(g_PropertyManager->camera()->getDir(), g_PropertyManager->camera()->getUp());
}
break;
case Qt::Key_Left:
{
g_PropertyManager->camera()->setDir(-5, 0);
m_pViewCube->setModelMat(g_PropertyManager->camera()->getDir(), g_PropertyManager->camera()->getUp());
}
break;
case Qt::Key_Right:
{
g_PropertyManager->camera()->setDir(5, 0);
m_pViewCube->setModelMat(g_PropertyManager->camera()->getDir(), g_PropertyManager->camera()->getUp());
}
break;
default:
break;
}
}
m_pCameraTool->setData(g_PropertyManager->camera()->getMoveSpeed(), g_PropertyManager->camera()->getCameraPos());
}
if(isShadowUpDate == true && m_shadowUpDate == 2)
{
m_isUpDateShadow = true;
}
}
void RenderWgt::keyReleaseEvent(QKeyEvent *event)
{
switch (event->key())
{
case Qt::Key_Control:
{
m_isKeyCtrlDown = false;
m_keys[Qt::Key_Control] = false;
}
break;
case Qt::Key_W:
{
m_keys[Qt::Key_W] = false;
}
break;
case Qt::Key_S:
{
m_keys[Qt::Key_S] = false;
}
break;
case Qt::Key_A:
{
m_keys[Qt::Key_A] = false;
}
break;
case Qt::Key_D:
{
m_keys[Qt::Key_D] = false;
}
break;
case Qt::Key_E:
{
m_keys[Qt::Key_E] = false;
}
break;
case Qt::Key_Q:
{
m_keys[Qt::Key_Q] = false;
}
break;
case Qt::Key_Up:
{
m_keys[Qt::Key_Up] = false;
}
break;
case Qt::Key_Down:
{
m_keys[Qt::Key_Down] = false;
}
break;
case Qt::Key_Left:
{
m_keys[Qt::Key_Left] = false;
}
break;
case Qt::Key_Right:
{
m_keys[Qt::Key_Right] = false;
}
break;
default:
break;
}
}
void RenderWgt::dropEvent(QDropEvent *event)
{
Q_UNUSED(event)
if(m_pTmpNode)
{
// g_PropertyManager->addNode(m_pTmpNode);
g_PropertyManager->undoStack()->push(new UndoCommandAddNode(m_pTmpNode, "add node::" + m_pTmpNode->name()));
g_PropertyManager->selectNode(m_pTmpNode);
m_pTmpNode = nullptr;
}
}
void RenderWgt::dragEnterEvent(QDragEnterEvent *event)
{
if (!event->mimeData()->hasFormat("application/x-qabstractitemmodeldatalist"))
{
event->ignore();
return;
}
QListWidget *pListwidget = qobject_cast<QListWidget *>(event->source());
PropertyFile propertyFile = g_PropertyManager->propertysWgt()->propertyFile(pListwidget->currentItem());
if(propertyFile.path == "" || propertyFile.type != 1)
{
event->ignore();
return;
}
g_PropertyManager->selectNode(nullptr);
event->acceptProposedAction();
m_modelPath = propertyFile.path;
if(!m_modelPath.isEmpty())
{
m_pTmpNode = g_PropertyManager->loadModel(m_modelPath);
m_pTmpNode->setHideMesh(false);
m_loadModelMutex.lock();
m_isLoadModel = true;
m_loadModelMutex.unlock();
}
}
void RenderWgt::dragMoveEvent(QDragMoveEvent *event)
{
if(!m_pTmpNode)
{
event->ignore();
return;
}
QVector4D worldPostion=worldPosFromViewPort(event->pos().x(),
event->pos().y());
// qDebug() << worldPostion;
if(worldPostion.w() > 1.2)
{
m_pTmpNode->setHide(true);
event->ignore();
return;
}
event->acceptProposedAction();
m_pTmpNode->setTranslate(worldPostion.toVector3D());
m_pTmpNode->setHide(false);
}
void RenderWgt::dragLeaveEvent(QDragLeaveEvent *event)
{
Q_UNUSED(event)
if(m_pTmpNode)
{
delete []m_pTmpNode;
m_pTmpNode = nullptr;
}
}
void RenderWgt::initialize()
{
setMinimumSize(100, 100);
QPixmap pixmap;
pixmap.load(":/res/icon/mou.png");
pixmap.setDevicePixelRatio(1.8);
cursor = QCursor(pixmap, 2, 2);
setCursor(cursor);
m_pViewCube = new ViewCube(parentWidget());
// m_pViewCube->show();
m_pCameraTool = new CameraTool(this);
m_pTip = new TipWgt(this);
m_pTip->raise();
m_pTip->move(10, 30);
m_pTip->hide();
//创建显示进度的任务栏按钮
connect(m_pCameraTool,&CameraTool::dataChange,[=](float speed, QVector3D pos){
g_PropertyManager->camera()->setMoveSpeed(speed);
g_PropertyManager->camera()->setCameraPos(pos);
});
connect(m_pCameraTool, &CameraTool::cameraRes, [=](){
g_PropertyManager->camera()->res();
m_pCameraTool->setData(g_PropertyManager->camera()->getMoveSpeed(), g_PropertyManager->camera()->getCameraPos());
m_pViewCube->setModelMat(g_PropertyManager->camera()->getDir(), g_PropertyManager->camera()->getUp());
});
// timer.setInterval(1);
connect(&timer,&QTimer::timeout,this,static_cast<void (RenderWgt::*)()>(&RenderWgt::update));
connect(&timer,&QTimer::timeout,this,[=](){
static QTime time(QTime::currentTime());//
double key = time.elapsed()/1000.0;
//this->replot();
static double lastFpsKey = 0;
static int frameCount;
++frameCount;
if(key - lastFpsKey>1){
m_pCameraTool->setFPS(QString("%1 FPS").arg(frameCount/(key-lastFpsKey), 0, 'f', 0));
lastFpsKey = key;
frameCount = 0;
}
g_PropertyManager->setFps(frameCount/(key-lastFpsKey));
});
timer.start();
m_pViewCube->setModelMat(g_PropertyManager->camera()->getDir(), g_PropertyManager->camera()->getUp());
// QSurfaceFormat newGLFormat = this->format(); //开启抗锯齿(开启后二维转三维坐标问题未解决)
// newGLFormat.setSamples(4);
// this->setFormat(newGLFormat);
}
void RenderWgt::initializeShader()
{
bool success;
m_ShaderProgram.addShaderFromSourceFile(QOpenGLShader::Vertex,":/res/shader/shapes.vert");
m_ShaderProgram.addShaderFromSourceFile(QOpenGLShader::Fragment,":/res/shader/shapes.frag");
success=m_ShaderProgram.link();
if(!success) qDebug()<<"ERR:"<<m_ShaderProgram.log();
m_DepthMapShaderProgram.addShaderFromSourceFile(QOpenGLShader::Vertex,":/res/shader/depthMap.vert");
m_DepthMapShaderProgram.addShaderFromSourceFile(QOpenGLShader::Fragment,":/res/shader/depthMap.frag");
success=m_DepthMapShaderProgram.link();
if(!success) qDebug()<<"ERR:"<<m_DepthMapShaderProgram.log();
}
void RenderWgt::createFloor()
{
if(g_PropertyManager->floor())
{
return;
}
QFile file(qApp->applicationDirPath() + "/floor.obj");
QFile::copy(":/res/model/floor/floor.obj", qApp->applicationDirPath() + "/floor.obj");
QFile::copy(":/res/model/floor/floor.png", qApp->applicationDirPath() + "/floor.png");
QFile::copy(":/res/model/floor/floor.mtl", qApp->applicationDirPath() + "/floor.mtl");
Node* floor = g_PropertyManager->loadModel(file.fileName(), false);
floor->setUpTextureId();
floor->setupGlFunc(QOpenGLContext::currentContext()->versionFunctions<GLFUNC>());
floor->setHideMesh(true);
floor->setScale(QVector3D(1000, 0.01f, 1000));
g_PropertyManager->setFloor(floor);
g_PropertyManager->propertysWgt()->removeAll();
}
void RenderWgt::createDepthTexture()
{
// configure depth map FBO
// -----------------------
glGenFramebuffers(1, &m_depthMapFBO);
// create depth texture
glGenTextures(1, &m_depthMap);
glBindTexture(GL_TEXTURE_2D, m_depthMap);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, m_SHADOW_WIDTH, m_SHADOW_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
float borderColor[] = { 1.0f, 1.0f, 1.0f, 1.0f };
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
// attach depth texture as FBO's depth buffer
glBindFramebuffer(GL_FRAMEBUFFER, m_depthMapFBO);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depthMap, 0);
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
qDebug() << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!" << endl;
glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebufferObject() );
}
void RenderWgt::loadWorld()
{
if(!g_PropertyManager->m_isLoadWorld)
{
return;
}
foreach(auto node, g_PropertyManager->m_tmpNodes)
{
node->setupGlFunc(QOpenGLContext::currentContext()->versionFunctions<GLFUNC>());
g_PropertyManager->addNode(node);
g_PropertyManager->m_tmpNodes.removeOne(node);
int num = g_PropertyManager->nodes().size() * 100/(g_PropertyManager->m_tmpNodes.size() + g_PropertyManager->nodes().size());
g_PropertyManager->loadWgt()->onSetTip(QString(("即将加载完成 %1 %")).arg(num));
emit g_PropertyManager->setTaskbarProgressValue(60 + num*0.4);
if(g_PropertyManager->m_tmpNodes.size() == 0)
{
g_PropertyManager->loadWgt()->onSetTip(("加载完成!"));
g_PropertyManager->m_isLoadWorld = false;
g_PropertyManager->m_tmpNodes.clear();
g_PropertyManager->loadWgt()->hide();
g_PropertyManager->setIsNeedSave(false);
emit g_PropertyManager->setEnabledSignal(true);
emit g_PropertyManager->setTaskbarProgressValue(0);
QApplication::alert(this);
if(m_shadowUpDate == 2)
{
m_isUpDateShadow = true;
}
}
break;
}
}
void RenderWgt::loadModel()
{
if(!m_isLoadModel)
{
return;
}
m_isLoadModel = false;
if(m_pLoadModel)
{
m_pLoadModel->setupGlFunc(QOpenGLContext::currentContext()->versionFunctions<GLFUNC>());
// g_PropertyManager->addNode(m_pLoadModel);
g_PropertyManager->undoStack()->push(new UndoCommandAddNode(m_pLoadModel, "add node::" + m_pLoadModel->name()));
g_PropertyManager->selectNode(m_pLoadModel);
m_pLoadModel = nullptr;
}
if(m_pTmpNode)
{
m_pTmpNode->setUpTextureId();
m_pTmpNode->setupGlFunc(QOpenGLContext::currentContext()->versionFunctions<GLFUNC>());
}
g_PropertyManager->setEnabledSignal(true);
m_pTip->hide();
if(m_shadowUpDate == 2)
{
m_isUpDateShadow = true;
}
}
void RenderWgt::renderDepthMap()
{
// m_isDepthMap = true;
if(m_isDepthMap)
{
if(m_isUpDateShadow)
{
if(m_shadowUpDate != 1)
{
m_isUpDateShadow = false;
}
m_DepthMapShaderProgram.bind();
// 1. render depth of scene to texture (from light's perspective)
// --------------------------------------------------------------
QMatrix4x4 lightProjection, lightView;
QMatrix4x4 lightSpaceMatrix;
float near_plane = 10.0f, far_plane = 500.0f;
lightProjection.ortho(-1000.0f, 1000.0f, -1000.0f, 1000.0f, near_plane, far_plane);
lightView.lookAt(-m_tmpLightDir*100 + g_PropertyManager->camera()->getCameraPos(),
g_PropertyManager->camera()->getCameraPos(), QVector3D(0.0, 1.0, 0.0));
lightSpaceMatrix = lightProjection * lightView;
glViewport(0, 0, m_SHADOW_WIDTH, m_SHADOW_HEIGHT);
glBindFramebuffer(GL_FRAMEBUFFER, m_depthMapFBO);
glClear(GL_DEPTH_BUFFER_BIT);
m_DepthMapShaderProgram.setUniformValue("lightSpaceMatrix", lightSpaceMatrix);
// glEnable(GL_CULL_FACE);
// glCullFace(GL_FRONT);
foreach(auto node, g_PropertyManager->nodes())
{
node->Draw(m_DepthMapShaderProgram, true);
}
// g_PropertyManager->floor()->Draw(m_DepthMapShaderProgram, true);
// glCullFace(GL_BACK); // 不要忘记设回原先的culling face
// glDisable(GL_CULL_FACE);
glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebufferObject());
m_DepthMapShaderProgram.release();
m_ShaderProgram.bind();
m_ShaderProgram.setUniformValue("lightSpaceMatrix", lightSpaceMatrix);
glViewport(0, 0, width(), height());
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, m_depthMap);
m_ShaderProgram.setUniformValue("depthMap",1);
m_ShaderProgram.setUniformValue("isDepthMap",true);
}
}
else
{
// glClear(GL_DEPTH_BUFFER_BIT);
m_ShaderProgram.bind();
m_ShaderProgram.setUniformValue("isDepthMap",false);
}
}
void RenderWgt::renderNode()
{
m_ShaderProgram.bind();
m_ShaderProgram.setUniformValue("projection", m_projection);
m_ShaderProgram.setUniformValue("view", g_PropertyManager->camera()->getView());
m_ShaderProgram.setUniformValue("viewPos",g_PropertyManager->camera()->getCameraPos());
m_ShaderProgram.setUniformValue("light.direction", m_tmpLightDir);
g_PropertyManager->floor()->Draw(m_ShaderProgram);
foreach(auto node, g_PropertyManager->nodes())
{
node->Draw(m_ShaderProgram);
}
if(m_pTmpNode)
{
glDisable(GL_DEPTH_TEST);
m_pTmpNode->Draw(m_ShaderProgram);
glEnable(GL_DEPTH_TEST);
}
if(g_PropertyManager->manipulator())
{
g_PropertyManager->manipulator()->Draw(m_ShaderProgram);
}
m_ShaderProgram.release();
}
QVector4D RenderWgt::worldPosFromViewPort(int posX, int posY)
{
makeCurrent();
float winZ;
glReadPixels(
posX,
this->height()-posY
,1,1
,GL_DEPTH_COMPONENT,GL_FLOAT
,&winZ);
doneCurrent();
float x=(2.0f*posX)/this->width()-1.0f; //转化为标准设备坐标(-1,1)
float y=1.0f-(2.0f*posY)/this->height();//转化为标准设备坐标(-1,1)
float z=winZ*2.0f-1.0f;//转化为标准设备坐标(-1,1)
float w = (2.0f * CAM_NEAR * CAM_FAR) / (CAM_FAR + CAM_NEAR - z * (CAM_FAR - CAM_NEAR));//计算齐次坐标
//float w= _near*_far/(_near*winZ-_far*winZ+_far);
QVector4D wolrdPostion(x,y,z,1);
wolrdPostion=w*wolrdPostion;//裁剪空间的坐标
return g_PropertyManager->camera()->getView().inverted()*m_projection.inverted()*wolrdPostion; //获得世界空间的坐标
}
void RenderWgt::setBackgroundColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a)
{
m_backgroundColor = QVector4D(r, g, b, a);
}
void RenderWgt::addModelByFile()
{
m_modelPath = QFileDialog::getOpenFileName(this, ("导入模型"),
g_Config->Get("path", "model").toString(),
tr("Model Files (%1)").arg(MODEL_FILE_TYPE));
if(m_modelPath.isEmpty())
{
return;
}
g_PropertyManager->setEnabledSignal(false);
m_pTip->setText(("模型加载中..."));
m_pTip->show();
QFutureWatcher<void> *pWatcher = new QFutureWatcher<void>;
QFuture<void> future = QtConcurrent::run([=]()
{
Node *node = g_PropertyManager->loadModel(m_modelPath);
while(m_pLoadModel != nullptr);
m_pLoadModel = node;
});
connect(pWatcher, &QFutureWatcher<void>::finished,this,[=](){
m_pLoadModel->setUpTextureId();
m_isLoadModel = true;
});
pWatcher->setFuture(future);
QString dir = m_modelPath;
dir.chop(dir.split("/").last().count());
g_Config->Set("path", "model", dir);
}
Node
所有图形的基类。
node.h
#ifndef NODE_H
#define NODE_H
#include <QVector3D>
#include <QMatrix4x4>
#include <QOpenGLShaderProgram>
#include <QOpenGLFunctions_3_3_Compatibility>
//#include "../Components/componentbase.h"
#define GLFUNC QOpenGLFunctions_3_3_Compatibility
class PropertyManager;
class ComponentBase;
using namespace std;
struct Vertex {
QVector3D Position;
QVector3D Normal;
QVector2D TexCoords;
};
struct Texture {
unsigned int id;
string type;
string path;
};
struct AABB
{
QVector3D minPos;
QVector3D maxPos;
};
struct Material {
float shininess;
QVector3D ambient;
QVector3D diffuse;
QVector3D specular;
};
struct MeshData
{
vector<Vertex> m_vertices;
vector<unsigned int> m_indices;
unsigned int VAO, VBO, EBO;
bool m_isSetup = false;
};
enum NODE_TYPE
{
NODE_TYPE_NONE = -1,
NODE_TYPE_MODEL = 0,
NODE_TYPE_MESH = 1,
};
class Node
{
public:
Node(Node *parent = nullptr);
virtual ~Node();
QMatrix4x4 modelMat();
void setAABB(const AABB &aabb){m_aabb = aabb;}
AABB aabb(){return m_aabb;}
void setParent(Node *parent){m_pParent = parent;}
Node *parent(){return m_pParent;}
QString path(){return m_path;}
void setPath(const QString &path){m_path = path;}
void setIdxInModel(int indx){m_nIdxInModel = indx;}
int IdxInModel(){return m_nIdxInModel;}
NODE_TYPE type(){return m_nodeType;}
MeshData *meshData(){return m_pMeshData;}
vector<Texture> textures(){return m_textures;}
void setTextures(vector<Texture> textures){m_textures = textures;}
QVariantMap saveData();
void setData(QVariantMap data);
void setHideAABB(bool isHide);
bool isHideAABB(){ return m_isHideAABB; }
bool isSelect(QVector4D pos);
Node *selectNode(QVector4D pos);
QVector3D centrePos(){return m_centrePos;}
QVector3D translate(){return m_tra;}
QVector3D rotate(){return m_rot;}
QVector3D scale(){return m_scale;}
QVector3D relativeScale();
void setTranslate(const QVector3D &tra);
void translate(const QVector3D &tra);
void setRotate(const QVector3D& rot);
void rotate(const QVector3D& rot);
void rotateRectify();
void setScale(const QVector3D& sca);
void scale(const QVector3D& sca);
void scaleMovePos(const QVector3D &sca, const QVector3D &pos);
void setHide(bool is){m_isHide = is;}
bool isHide(){return m_isHide;}
void setHideMesh(bool is);
void setHidelOutLine(bool is);
void setMaterial(const Material &material);
Material material(){return m_material;}
void setName(const QString &name){m_name = name;}
QString name(){return m_name;}
void addChild(Node *node);
QList<Node *> childs(){return m_childs;}
void delChild(Node *child);
void bindComponent(ComponentBase *com);
virtual void Draw(QOpenGLShaderProgram &shader, bool isDepthMap = false);
virtual void setupGlFunc(GLFUNC *glfuns);
virtual void setUpTextureId();
bool m_isAddAABBIdx = false;
protected:
virtual void upDataAABB();
protected:
GLFUNC *m_glFuns;
// mesh data
MeshData *m_pMeshData;
vector<Texture> m_textures;
QString m_name;
QString m_path;
int m_nIdxInModel = -1;
QMatrix4x4 m_modelMat;
QVector3D m_tra = QVector3D(0, 0, 0);
QVector3D m_rot = QVector3D(0, 0, 0); //分别为绕x y z轴旋转的角度;
QVector3D m_scale = QVector3D(1, 1, 1);
Node *m_pParent = nullptr;
QList<Node *> m_childs;
AABB m_aabb;
bool m_isHideAABB = true;
QVector3D m_centrePos;
bool m_isHideMesh = true;
bool m_isHideOutLine = true;
bool m_isHide = false;
bool m_isUseColor = false;
NODE_TYPE m_nodeType = NODE_TYPE::NODE_TYPE_NONE;
QVector3D m_color = QVector3D(1, 1, 1);
Material m_material{32.0f, QVector3D(0.4f, 0.4f, 0.4f), QVector3D(0.9f, 0.9f, 0.9f),QVector3D(0.3f, 0.3f, 0.3f)};
ComponentBase *m_pComponent = nullptr;
//...
};
#endif // NODE_H
node.cpp
#include "node.h"
#include "./../propertymanager.h"
Node::Node(Node* parent)
:m_pParent(parent)
{
}
Node::~Node()
{
foreach(auto child, m_childs)
{
delete []child;
}
if(m_pComponent)
{
delete m_pComponent;
m_pComponent = nullptr;
}
}
QMatrix4x4 Node::modelMat()
{
QMatrix4x4 modelMat = QMatrix4x4();
if(parent())
{
QVector3D tra, sca;
tra = m_tra - parent()->translate();
sca = m_scale;///parent()->scale();
modelMat.translate(tra);
modelMat.rotate(m_rot.y(), 0, 1, 0);
modelMat.rotate(m_rot.z(), 0, 0, 1);
modelMat.rotate(m_rot.x(), 1, 0, 0);
modelMat.scale(sca);
QMatrix4x4 pMat = parent()->modelMat();
pMat.scale(QVector3D(1, 1, 1)/parent()->scale());
modelMat = pMat * modelMat;
}
else
{
modelMat.translate(m_tra);
modelMat.rotate(m_rot.y(), 0, 1, 0);
modelMat.rotate(m_rot.z(), 0, 0, 1);
modelMat.rotate(m_rot.x(), 1, 0, 0);
modelMat.scale(m_scale);
}
return modelMat;
}
QVariantMap Node::saveData()
{
QVariantMap data;
data.insert("name", m_name);
data.insert("type", m_nodeType);
//获取程序所在的路径
QDir dir=QDir::current();
//将绝对路径转换为相对路径
QString relPath = dir.relativeFilePath(m_path);
data.insert("path", relPath);
data.insert("idxInModel", m_nIdxInModel);
data.insert("isHide", m_isHide);
QString tra = QString::number(m_tra.x()) + "," + QString::number(m_tra.y()) + "," + QString::number(m_tra.z());
QString rot = QString::number(m_rot.x()) + "," + QString::number(m_rot.y()) + "," + QString::number(m_rot.z());
QString sca = QString::number(m_scale.x()) + "," + QString::number(m_scale.y()) + "," + QString::number(m_scale.z());
data.insert("tra", tra);
data.insert("rot", rot);
data.insert("sca", sca);
QString mat_am = QString::number(m_material.ambient.x()) + "," + QString::number(m_material.ambient.y()) + "," + QString::number(m_material.ambient.z());
QString mat_di = QString::number(m_material.diffuse.x()) + "," + QString::number(m_material.diffuse.y()) + "," + QString::number(m_material.diffuse.z());
QString mat_sp = QString::number(m_material.specular.x()) + "," + QString::number(m_material.specular.y()) + "," + QString::number(m_material.specular.z());
data.insert("mat_sh", m_material.shininess);
data.insert("mat_am", mat_am);
data.insert("mat_di", mat_di);
data.insert("mat_sp", mat_sp);
data.insert("isUseClolr", m_isUseColor);
QString color = QString::number(m_color.x()) + "," + QString::number(m_color.y()) + "," + QString::number(m_color.z());
data.insert("color", color);
QVariantList childs;
foreach(auto child, m_childs)
{
childs.append(child->saveData());
}
data.insert("childs", childs);
return data;
}
void Node::setData(QVariantMap data)
{
m_name = data["name"].toString();
m_nodeType = (NODE_TYPE)data["type"].toInt();
m_path = data["path"].toString();
m_nIdxInModel = data["idxInModel"].toInt();
m_isHide = data["isHide"].toBool();
QStringList tra = data["tra"].toString().split(",");
m_tra = QVector3D(tra[0].toDouble(), tra[1].toDouble(), tra[2].toDouble());
QStringList rot = data["rot"].toString().split(",");
m_rot = QVector3D(rot[0].toDouble(), rot[1].toDouble(), rot[2].toDouble());
QStringList sca = data["sca"].toString().split(",");
m_scale = QVector3D(sca[0].toDouble(), sca[1].toDouble(), sca[2].toDouble());
m_material.shininess = data["mat_sh"].toFloat();
QStringList mat_am = data["mat_am"].toString().split(",");
m_material.ambient = QVector3D(mat_am[0].toDouble(), mat_am[1].toDouble(), mat_am[2].toDouble());
QStringList mat_di = data["mat_di"].toString().split(",");
m_material.diffuse = QVector3D(mat_di[0].toDouble(), mat_di[1].toDouble(), mat_di[2].toDouble());
QStringList mat_sp = data["mat_sp"].toString().split(",");
m_material.specular = QVector3D(mat_sp[0].toDouble(), mat_sp[1].toDouble(), mat_sp[2].toDouble());
m_isUseColor = data["isUseCloor"].toBool();
QStringList color = data["color"].toString().split(",");
m_color = QVector3D(color[0].toDouble(), color[1].toDouble(), color[2].toDouble());
}
void Node::setHideAABB(bool isHide)
{
m_isHideAABB = isHide;
foreach (auto node, m_childs)
{
node->setHideAABB(m_isHideAABB);
}
}
bool Node::isSelect(QVector4D pos)
{
if(m_isHide)
{
return false;
}
QVector3D minPos = modelMat() * m_aabb.minPos;
QVector3D maxPos = modelMat() * m_aabb.maxPos;
// if(m_rot != QVector3D())
{
QVector<QVector3D> ps{modelMat() * QVector3D(m_aabb.minPos.x(), m_aabb.minPos.y(), m_aabb.maxPos.z()),
modelMat() * QVector3D(m_aabb.minPos.x(), m_aabb.maxPos.y(), m_aabb.maxPos.z()),
modelMat() * QVector3D(m_aabb.maxPos.x(), m_aabb.minPos.y(), m_aabb.maxPos.z()),
modelMat() * QVector3D(m_aabb.maxPos.x(), m_aabb.minPos.y(), m_aabb.minPos.z()),
modelMat() * QVector3D(m_aabb.minPos.x(), m_aabb.minPos.y(), m_aabb.maxPos.z()),
modelMat() * QVector3D(m_aabb.minPos.x(), m_aabb.maxPos.y(), m_aabb.minPos.z())};
foreach(auto pos, ps)
{
if(pos.x() < minPos.x())
{
minPos.setX(pos.x());
}
if(pos.y() < minPos.y())
{
minPos.setY(pos.y());
}
if(pos.z() < minPos.z())
{
minPos.setZ((pos.z()));
}
if(pos.x() > maxPos.x())
{
maxPos.setX(pos.x());
}
if(pos.y() > maxPos.y())
{
maxPos.setY(pos.y());
}
if(pos.z() > maxPos.z())
{
maxPos.setZ((pos.z()));
}
}
}
if(pos.x() >= minPos.x()-0.01f && pos.y() >= minPos.y()-0.01f && pos.z() >= minPos.z()-0.01f
&& pos.x() <= maxPos.x()+0.01f && pos.y() <= maxPos.y()+0.01f && pos.z() <= maxPos.z()+0.01f)
{
g_PropertyManager->addSelectTmpNode(QVector3D(maxPos - minPos).length(), this);
return true;
}
return false;
}
Node *Node::selectNode(QVector4D pos)
{
if(m_isHide)
{
return nullptr;
}
Node *retNode = nullptr;
if(m_nodeType == NODE_TYPE::NODE_TYPE_MODEL)
{
foreach(auto node, m_childs)
{
retNode = node->selectNode(pos);
if(retNode != nullptr)
{
//return retNode;
}
}
}
if(m_nodeType == NODE_TYPE::NODE_TYPE_MESH)
{
if(isSelect(pos))
{
//return this;
}
foreach(auto node, m_childs)
{
retNode = node->selectNode(pos);
if(retNode != nullptr)
{
//return retNode;
}
}
}
return nullptr;
}
QVector3D Node::relativeScale()
{
if(parent())
{
return m_scale/parent()->relativeScale();
}
else
{
return m_scale;
}
}
void Node::setTranslate(const QVector3D &tra)
{
if(isnan(tra.x()) || isnan(tra.y()) || isnan(tra.z()))
{
return;
}
foreach(auto node, m_childs)
{
node->translate(tra - m_tra);
}
m_tra = tra;
}
void Node::translate(const QVector3D &tra)
{
if(isnan(tra.x()) || isnan(tra.y()) || isnan(tra.z()))
{
return;
}
foreach(auto node, m_childs)
{
node->translate(tra);
}
m_tra += tra;
}
void Node::setRotate(const QVector3D &rot)
{
if(isnan(rot.x()) || isnan(rot.y()) || isnan(rot.z()))
{
return;
}
// foreach(auto node, m_childs)
// {
// node->rotate(rot - m_rot);
// }
m_rot = rot;
rotateRectify();
}
void Node::rotate(const QVector3D &rot)
{
if(isnan(rot.x()) || isnan(rot.y()) || isnan(rot.z()))
{
return;
}
m_rot += rot;
// foreach(auto child, m_childs)
// {
// child->rotate(rot);
// }
rotateRectify();
}
void Node::rotateRectify()
{
if(m_rot.x() < 0) m_rot.setX(m_rot.x() + 360);
if(m_rot.x() > 360) m_rot.setX(m_rot.x() - 360);
if(m_rot.y() < 0) m_rot.setY(m_rot.y() + 360);
if(m_rot.y() > 360) m_rot.setY(m_rot.y() - 360);
if(m_rot.z() < 0) m_rot.setZ(m_rot.z() + 360);
if(m_rot.z() > 360) m_rot.setZ(m_rot.z() - 360);
}
void Node::setScale(const QVector3D &sca)
{
if(isnan(sca.x()) || isnan(sca.y()) || isnan(sca.z()))
{
return;
}
QVector3D tmpSca = QVector3D(1, 1, 1);
if(m_scale.x() != sca.x())
{
tmpSca.setX(sca.x()/m_scale.x());
}
if(m_scale.y() != sca.y())
{
tmpSca.setY(sca.y()/m_scale.y());
}
if(m_scale.z() != sca.z())
{
tmpSca.setZ(sca.z()/m_scale.z());
}
m_scale = sca;
foreach(auto node, m_childs)
{
QMatrix4x4 mat;
// QVector3D rot = node->rotate();
// mat.rotate(rot.y(), 0, 1, 0);
// mat.rotate(rot.z(), 0, 0, 1);
// mat.rotate(rot.x(), 1, 0, 0);
node->scaleMovePos(mat*tmpSca, m_tra);
}
}
void Node::scale(const QVector3D &sca)
{
if(isnan(sca.x()) || isnan(sca.y()) || isnan(sca.z()))
{
return;
}
m_scale *= sca;
foreach(auto node, m_childs)
{
QMatrix4x4 mat;
// QVector3D rot = node->rotate();
// mat.rotate(rot.y(), 0, 1, 0);
// mat.rotate(rot.z(), 0, 0, 1);
// mat.rotate(rot.x(), 1, 0, 0);
node->scaleMovePos(mat*sca, m_tra);
}
}
void Node::scaleMovePos(const QVector3D &sca, const QVector3D &pos)
{
if(isnan(sca.x()) || isnan(sca.y()) || isnan(sca.z()))
{
return;
}
m_scale *= sca;
m_tra = (m_tra - pos)*sca + pos;
foreach(auto node, m_childs)
{
node->scaleMovePos(sca, m_tra);
}
}
void Node::setHideMesh(bool is)
{
m_isHideMesh = is;
foreach (auto node, m_childs)
{
node->setHideMesh(m_isHideMesh);
}
}
void Node::setHidelOutLine(bool is)
{
m_isHideOutLine = is;
foreach(auto node, m_childs)
{
node->setHidelOutLine(m_isHideOutLine);
}
}
void Node::setMaterial(const Material &material)
{
m_material = material;
if(m_nodeType == NODE_TYPE::NODE_TYPE_MODEL)
{
// foreach(auto child, m_childs)
// {
// child->setMaterial(m_material);
// }
}
}
void Node::addChild(Node *node)
{
if(node != nullptr)
{
node->setParent(this);
m_childs.push_back(node);
}
}
void Node::delChild(Node *child)
{
m_childs.removeOne(child);
}
void Node::bindComponent(ComponentBase *com)
{
if(m_pComponent)
{
delete []m_pComponent;
}
m_pComponent = com;
if(m_pComponent)
{
m_pComponent->bindNode(this);
}
}
void Node::upDataAABB()
{
// m_aabb.minPos = QVector3D(m_modelMat * m_vertices[0].pos);
// m_aabb.maxPos = QVector3D(m_modelMat * m_vertices[0].pos);
// for(int i = 0; i < m_vertices.size(); i++)
// {
// QVector3D tmp = m_modelMat * m_vertices[i].pos;
// if(tmp.x() > m_aabb.maxPos.x())
// {
// m_aabb.maxPos.setX(tmp.x());
// }
// if(tmp.y() > m_aabb.maxPos.y())
// {
// m_aabb.maxPos.setY(tmp.y());
// }
// if(tmp.z() > m_aabb.maxPos.z())
// {
// m_aabb.maxPos.setZ(tmp.z());
// }
// if(tmp.x() < m_aabb.minPos.x())
// {
// m_aabb.minPos.setX(tmp.x());
// }
// if(tmp.y() < m_aabb.minPos.y())
// {
// m_aabb.minPos.setY(tmp.y());
// }
// if(tmp.z() < m_aabb.minPos.z())
// {
// m_aabb.minPos.setZ(tmp.z());
// }
// //vertices.push_back(QVector3D(m_vertices[i], m_vertices[i+1], m_vertices[i+2]));
// }
// m_aabb.minPos.setX(m_aabb.minPos.x() - 0.01f);
// m_aabb.minPos.setY(m_aabb.minPos.y() - 0.01f);
// m_aabb.minPos.setZ(m_aabb.minPos.z() - 0.01f);
// m_aabb.maxPos.setX(m_aabb.maxPos.x() + 0.01f);
// m_aabb.maxPos.setY(m_aabb.maxPos.y() + 0.01f);
// m_aabb.maxPos.setZ(m_aabb.maxPos.z() + 0.01f);
// m_centrePos = (m_aabb.minPos +m_aabb.maxPos)/2;
// m_AABBvertices.clear();
// m_AABBvertices.push_back(QVector3D(m_aabb.minPos.x(), m_aabb.minPos.y(), m_aabb.minPos.z()));
// m_AABBvertices.push_back(QVector3D(m_aabb.maxPos.x(), m_aabb.minPos.y(), m_aabb.minPos.z()));
// m_AABBvertices.push_back(QVector3D(m_aabb.minPos.x(), m_aabb.maxPos.y(), m_aabb.minPos.z()));
// m_AABBvertices.push_back(QVector3D(m_aabb.minPos.x(), m_aabb.minPos.y(), m_aabb.maxPos.z()));
// m_AABBvertices.push_back(QVector3D(m_aabb.maxPos.x(), m_aabb.maxPos.y(), m_aabb.minPos.z()));
// m_AABBvertices.push_back(QVector3D(m_aabb.maxPos.x(), m_aabb.maxPos.y(), m_aabb.maxPos.z()));
// m_AABBvertices.push_back(QVector3D(m_aabb.maxPos.x(), m_aabb.minPos.y(), m_aabb.maxPos.z()));
// m_AABBvertices.push_back(QVector3D(m_aabb.minPos.x(), m_aabb.maxPos.y(), m_aabb.maxPos.z()));
}
void Node::Draw(QOpenGLShaderProgram &shader, bool isDepthMap)
{
Q_UNUSED(shader)
Q_UNUSED(isDepthMap)
}
void Node::setupGlFunc(GLFUNC *glfuns)
{
Q_UNUSED(glfuns)
}
void Node::setUpTextureId()
{
}
结语
有功能点击没效果, 不要怀疑, 就是还没有实现;欢迎提问。
国际站点:https://github.com/yibobunengyuntian
QQ:2947467985