Qt3D のドキュメントは増えていますが、特に Qml/QtQuick なしで作業を行う方法についてはまだ情報が不足しています。ワイヤーフレーム モードでメッシュをレンダリングする方法について Web で徹底的に検索した結果、役立つヒントや例がたくさん見つかりました。それらすべてをまとめて、記事を書いた人や同様の例を検索した人全員への貢献として、ここでサンプル ビューアーを紹介したいと思います。
最も役立つリンクは次のとおりです。
Qt3DWindow でのイベント フィルターの使用に関する Stackoverflow の質問と回答:Qt 3D ウィンドウ上のマウス コントロール
メッシュはマウスで回転したりズームしたりできます。
ビューアのスクリーンショット
これを改善する方法についてのコメントは歓迎します。特に、前面と背面を異なる色でレンダリングしたり、頂点ごとに色をレンダリングしたりできるシェーダー プログラムの書き方に興味があります。
コードは次のとおりです。
// ######### Opening the viewer #########
void MainWindow::import3dMeshInMeshViewer(QString name)
{
if (!m_viewer3D)
{
m_viewer3D = new Viewer3D(this);
}
m_viewer3D->sceneModifier()->addTriangleMeshCustomMaterial(name, m_meshVector);
m_viewer3D->show();
}
// ######### Viewer class h #########
class Viewer3D : public QDialog
{
Q_OBJECT
public:
Viewer3D(QWidget *parent = 0);
SceneModifier* sceneModifier() {return m_sceneModifier;}
protected:
bool eventFilter(QObject *obj, QEvent *ev);
void mouseMoveEvent(QMouseEvent *ev);
void mousePressEvent(QMouseEvent *ev);
void mouseReleaseEvent(QMouseEvent *ev);
void wheelEvent(QWheelEvent *we);
private:
QPointer<Qt3DCore::QEntity> m_rootEntity;
QPointer<SceneModifier> m_sceneModifier;
Qt3DExtras::Qt3DWindow *m_view;
QPoint m_moveStartPoint;
QMatrix4x4 m_cameraMatrix;
};
// ######### Viewer class cpp #########
Viewer3D::Viewer3D(QWidget *parent) :
QDialog(parent)
{
setAttribute(Qt::WA_DeleteOnClose);
m_moveStartPoint.setX(-1);
m_view = new Qt3DExtras::Qt3DWindow();
m_view->installEventFilter(this);
m_view->defaultFrameGraph()->setClearColor(QColor(QRgb(0x4d4d4f)));
QWidget *container = QWidget::createWindowContainer(m_view);
QSize screenSize = m_view->screen()->size();
container->setMinimumSize(QSize(200, 100));
container->setMaximumSize(screenSize);
QHBoxLayout *hLayout = new QHBoxLayout(this);
QVBoxLayout *vLayout = new QVBoxLayout();
hLayout->addWidget(container, 1);
setWindowTitle(QStringLiteral("Mesh Viewer"));
// Root entity
m_rootEntity = new Qt3DCore::QEntity();
// Scene modifier
m_sceneModifier = new SceneModifier(m_rootEntity);
// Window geometry
resize(parent->geometry().width() * 0.8, parent->geometry().height() * 0.8);
move(parent->geometry().center() - QPoint(width() / 2, height() / 2));
// Camera
Qt3DRender::QCamera *cameraEntity = m_view->camera();
//cameraEntity->lens()->setPerspectiveProjection(22.5f, m_view->width()/m_view->height(), 0.01f, 1000.0f);
cameraEntity->setPosition(QVector3D(0, 0, 500.0f));
cameraEntity->setUpVector(QVector3D(0, 1, 0));
cameraEntity->setViewCenter(QVector3D(0, 0, 0));
cameraEntity->transform()->setScale(1.f);
// Set root object of the scene
m_view->setRootEntity(m_rootEntity);
}
bool Viewer3D::eventFilter(QObject *obj, QEvent *ev)
{
if (ev->type() == QEvent::Wheel)
{
wheelEvent(dynamic_cast<QWheelEvent*>(ev));
return true;
}
else if (ev->type() == QEvent::MouseButtonPress)
{
mousePressEvent(dynamic_cast<QMouseEvent*>(ev));
return true;
}
else if (ev->type() == QEvent::MouseMove)
{
mouseMoveEvent(dynamic_cast<QMouseEvent*>(ev));
return true;
}
else if (ev->type() == QEvent::MouseButtonRelease)
{
mouseReleaseEvent(dynamic_cast<QMouseEvent*>(ev));
return true;
}
return QObject::eventFilter(obj, ev);
}
void Viewer3D::wheelEvent(QWheelEvent *we)
{
Qt3DCore::QTransform* transform = m_view->camera()->transform();
float scale = transform->scale();
QPoint delta = we->angleDelta();
float zoom_distance = scale * static_cast<float>(delta.y()) / 500.f;
scale -= zoom_distance;
scale = std::min(10.0000f, scale);
scale = std::max(0.001f, scale);
transform->setScale(scale);
}
void Viewer3D::mousePressEvent(QMouseEvent *ev)
{
if (ev->button() == Qt::LeftButton)
{
m_moveStartPoint = ev->pos();
m_cameraMatrix = m_view->camera()->transform()->matrix();
}
}
void Viewer3D::mouseMoveEvent(QMouseEvent *ev)
{
if (m_moveStartPoint.x() > -1)
{
QPoint delta = ev->pos() - m_moveStartPoint;
float angle = static_cast<float>(QPoint::dotProduct(delta, delta)) / 100.f;
QVector3D axis = QVector3D(delta.y(), delta.x(), 0);
QMatrix4x4 rotationMatrix = Qt3DCore::QTransform::rotateAround(-m_view->camera()->position(), angle, axis);
QMatrix4x4 matrix = rotationMatrix * m_cameraMatrix;
m_view->camera()->transform()->setMatrix(matrix);
}
}
void Viewer3D::mouseReleaseEvent(QMouseEvent *ev)
{
if (m_moveStartPoint.x() > -1)
{
m_moveStartPoint.setX(-1);
m_cameraMatrix = m_view->camera()->transform()->matrix();
}
}
// ######### Scene modifier class h #########
class SceneModifier : public QObject
{
Q_OBJECT
public:
SceneModifier(Qt3DCore::QEntity* rootEntity);
void addTriangleMeshCustomMaterial(QString name, const std::vector<Import3d::Triangle>& meshVector);
private:
Qt3DCore::QEntity* m_rootEntity;
};
// ######### Scene modifier class cpp #########
#include "SceneModifier.h"
#include "TriangleMeshRenderer.h"
#include "MaterialWireFrame.h"
SceneModifier::SceneModifier(Qt3DCore::QEntity* rootEntity) :
m_rootEntity(rootEntity),
QObject(rootEntity)
{
}
void SceneModifier::addTriangleMeshCustomMaterial(QString name, const std::vector<Import3d::Triangle>& meshVector)
{
if (!m_rootEntity)
{
return;
}
// Mesh entity
Qt3DCore::QEntity *triangleMeshEntity = new Qt3DCore::QEntity(m_rootEntity);
triangleMeshEntity->setObjectName(QStringLiteral("customMeshEntity"));
TriangleMeshRenderer *triangleMeshRenderer = new TriangleMeshRenderer(meshVector);
MaterialWireFrame* materialWireFrame = new MaterialWireFrame();
Qt3DCore::QTransform *transform = new Qt3DCore::QTransform;
transform->setScale(1.f);
triangleMeshEntity->addComponent(triangleMeshRenderer);
triangleMeshEntity->addComponent(transform);
triangleMeshEntity->addComponent(materialWireFrame);
//emit meshAdded(name, triangleMeshEntity);
}
// ######### Point and Triangle structs #########
struct Point
{
QVector3D p; //point x, y, z
QVector3D c; //color red, green, blue
Point() {}
Point(float xp, float yp, float zp)
{
p = QVector3D(xp, yp, zp);
c = QVector3D(0, 0, 0);
}
Point(QVector3D pos, unsigned char r, unsigned char g, unsigned char b)
{
p = pos;
c = QVector3D(static_cast<float>(r) / 255.f,
static_cast<float>(g) / 255.f,
static_cast<float>(b) / 255.f);
}
};
struct Triangle
{
Point vertices[3];
Triangle()
{
}
Triangle(Point p1, Point p2, Point p3)
{
vertices[0] = p1;
vertices[1] = p2;
vertices[2] = p3;
}
};
// ######### TriangleMeshRenderer class h #########
class TriangleMeshRenderer : public Qt3DRender::QGeometryRenderer
{
Q_OBJECT
public: