Все доброго времени суток! Так вот планомерно, систематизированно и не сильно перенапрягаясь мы пришли к тому, что для 3D-объекта вида кубоид на данный момент реализована полная поддержка необходимого функционала. Поэтому сегодня по аналогичной схеме добавим остальные объекты. Чуть более подробно рассмотрим на каком-то одном из них, пусть на сфере, например, без разницы.
Собственно, уже четко определено, какие именно методы должен переопределять каждый из создаваемых 3D-объектов, так что sphere.h имеет такой вид:
#ifndef SPHERE_H #define SPHERE_H #include <QObject> #include "paintobject.h" class Sphere : public PaintObject { Q_OBJECT public: Sphere(Qt3DCore::QEntity *parentEntity, quint32 objectId, const QVector3D &coordinate = QVector3D(0, 0, 0)); void onMouseMoved(const QVector3D &coordinate); void update(const QVector<qreal> ¶meters); QVector<qreal> getParameters(); }; #endif // SPHERE_H
И реализация, sphere.cpp:
Sphere::Sphere(Qt3DCore::QEntity *parentEntity, quint32 objectId, const QVector3D &coordinate) : PaintObject(parentEntity, objectId) { type = PaintObject::Type::Sphere; Qt3DExtras::QSphereMesh *mesh = new Qt3DExtras::QSphereMesh(); Qt3DCore::QTransform *transform = new Qt3DCore::QTransform(); mesh->setRadius(0); mesh->setSlices(50); transform->setTranslation(QVector3D(coordinate.x(), coordinate.y(), constants::basePlaneZExtent / 2)); initialCoordinate = coordinate; entity->addComponent(mesh); entity->addComponent(transform); addMaterial(); } void Sphere::onMouseMoved(const QVector3D &coordinate) { Qt3DExtras::QSphereMesh *currentMesh = entity->componentsOfType<Qt3DExtras::QSphereMesh>().at(0); QVector3D mouseMoveVector = QVector3D(qAbs(coordinate.x() - initialCoordinate.x()), qAbs(coordinate.y() - initialCoordinate.y()), 0); currentMesh->setRadius(mouseMoveVector.length()); } QVector<qreal> Sphere::getParameters() { QVector<qreal> parameters; for (int i = 0; i < parametersVectorSize; i++) { parameters.append(0); } Qt3DExtras::QSphereMesh *currentMesh = entity->componentsOfType<Qt3DExtras::QSphereMesh>().at(0); parameters[0] = currentMesh->radius(); return parameters; } void Sphere::update(const QVector<qreal> ¶meters) { if (parameters.size() >= parametersVectorSize) { Qt3DExtras::QSphereMesh *currentMesh = entity->componentsOfType<Qt3DExtras::QSphereMesh>().at(0); currentMesh->setRadius(parameters.at(0)); } }
Схема один в один, как и для кубоида, ну для того и создавалась четкая архитектура приложения. В PaintEntity
добавляем типы инструментов, причем закинем сразу не только для сферы, но и для остальных объектов:
enum class ToolType { Select = 0, Delete, Cuboid, Sphere, Cone, Cylinder, Torus, ExtrudedText }; Q_ENUM(ToolType)
Следом же расширяем ToolPanel,
чтобы добавить новые инструменты в интерфейс:
Rectangle { id: rootRectangle color: "transparent" height: buttonsGrid.height property int selectedTool: PaintEntity.ToolType.Cuboid property var buttonsModel: [ {name: qsTr("select"), type: PaintEntity.ToolType.Select}, {name: qsTr("delete"), type: PaintEntity.ToolType.Delete}, {name: qsTr("cuboid"), type: PaintEntity.ToolType.Cuboid}, {name: qsTr("sphere"), type: PaintEntity.ToolType.Sphere}, {name: qsTr("cone"), type: PaintEntity.ToolType.Cone}, {name: qsTr("cylinder"), type: PaintEntity.ToolType.Cylinder}, {name: qsTr("torus"), type: PaintEntity.ToolType.Torus}, {name: qsTr("text"), type: PaintEntity.ToolType.ExtrudedText} ] // ...............
Дизайн нас все еще не интересует, так что результат устраивает полностью 👍 Остается внедрить логику отрисовки сферы везде, где это требуется. Во-первых, при создании объекта:
void PaintEntity::onBasePlaneMousePressed(const QVector3D &coordinate) { switch (activeTool) { case PaintEntity::ToolType::Cuboid: paintObjects.append(QSharedPointer<PaintObject>(new Cuboid(this, paintObjects.size(), coordinate))); break; case PaintEntity::ToolType::Sphere: paintObjects.append(QSharedPointer<PaintObject>(new Sphere(this, paintObjects.size(), coordinate))); break; default: // This branch should never be executed break; } int currentIndex = paintObjects.size() - 1; paintObjects.at(currentIndex)->setColor(activeColor); QObject::connect(paintObjects.at(currentIndex).data(), &PaintObject::picked, this, &PaintEntity::paintObjectPicked); QObject::connect(paintObjects.at(currentIndexcurrentIndex).data(), &PaintObject::readyForDeletion, this, &PaintEntity::removePaintObject); }
И, в принципе, сейчас уже сфера будет отрисовываться как положено. Еще пара дополнений требуется только в интерфейсной части main.qml:
PaintEntity { id: paintEntity function hideObjectControls() { for (var i = 0; i < objectsPanels.visibleChildren.length; i++) { objectsPanels.visibleChildren[i].visible = false; } transformPanel.visible = false; commonObjectPanel.visible = false; } onActivePaintObjectChanged: { hideObjectControls(); if (activePaintObject !== null) { colorPanel.setCurrentItem(activePaintObject.color); transformPanel.initialPosition = activePaintObject.position; transformPanel.reset(); transformPanel.visible = true; switch(activePaintObject.type) { case PaintObject.Type.Cuboid: commonObjectPanel.controlsModel = [ {text: "X extent", sliderMin: 0.1, sliderMax: baseCuboid.xExtent, sliderCurrent: activePaintObject.parameters[0]}, {text: "Y extent", sliderMin: 0.1, sliderMax: baseCuboid.yExtent, sliderCurrent: activePaintObject.parameters[1]}, {text: "Z extent", sliderMin: 0.1, sliderMax: 10, sliderCurrent: activePaintObject.parameters[2]} ]; break; case PaintObject.Type.Sphere: commonObjectPanel.controlsModel = [ {text: "Radius", sliderMin: 0.1, sliderMax: 10, sliderCurrent: activePaintObject.parameters[0]} ]; break; default: break; } commonObjectPanel.visible = true; } } }
Ровно как и планировали, поведение панели свойств объекта полностью определяется в одном месте и одним свойством - commonObjectPanel.controlsModel
. На этом процедура добавления нового 3D-объекта заканчивается. Только для редактирования текста я добавил еще одну панель - ExtrudedTextPanel
, исключительно в целях редактирования непосредственно текста. Полученный результат:
И далее, как обещал, полный код для всех текущих объектов, последовательно:
- конус
- кубоид
- цилиндр
- объемный текст
- сфера
- тор
Список уникальных свойств, доступных для редактирования для каждого из них:
3D объект | Параметры |
---|---|
Конус | Длина, радиус основания, радиус верхнего основания (для усеченного конуса) |
Кубоид | Длина, ширина, высота |
Цилиндр | Длина, радиус |
Текст | Размер, текст |
Сфера | Радиус |
Тор | Радиус образующей окружности, радиус |
Текущая структура проекта, на всякий:
И да, я упаковал все панели в ScrollView
, на случай если пространства окна им не хватит, что, в общем-то и произошло )
Все, теперь добавленный код для объектов и ссылка на полный проект:
#include <QDebug> #include "paintentity.h" #include "objects/cuboid.h" #include "objects/cone.h" #include "objects/sphere.h" #include "objects/cylinder.h" #include "objects/torus.h" #include "objects/extrudedtext.h" PaintEntity::PaintEntity(QNode *parent) : Qt3DCore::QEntity(parent), activeTool(ToolType::Cuboid), activePaintObject(nullptr), activeColor("#b22222") { } void PaintEntity::paintObjectPicked(quint32 pickedId) { if (activeTool == PaintEntity::ToolType::Select) { paintObjects.at(pickedId)->startSelectAnimation(); activePaintObject = paintObjects.at(pickedId).data(); emit activePaintObjectChanged(); } else { if (activeTool == PaintEntity::ToolType::Delete) { paintObjects.at(pickedId)->startDeleteAnimation(); } } } void PaintEntity::removePaintObject(quint32 objectId) { if (activePaintObject != nullptr) { if (objectId == activePaintObject->getId()) { activePaintObject = nullptr; emit activePaintObjectChanged(); } } paintObjects.remove(objectId); updatePaintObjectIds(objectId); } void PaintEntity::updatePaintObjectIds(int deletedIndex) { for (int i = deletedIndex; i < paintObjects.size(); i++) { paintObjects.at(i)->setId(i); } } void PaintEntity::onBasePlaneMousePressed(const QVector3D &coordinate) { switch (activeTool) { case PaintEntity::ToolType::Cuboid: paintObjects.append(QSharedPointer<PaintObject>(new Cuboid(this, paintObjects.size(), coordinate))); break; case PaintEntity::ToolType::Sphere: paintObjects.append(QSharedPointer<PaintObject>(new Sphere(this, paintObjects.size(), coordinate))); break; case PaintEntity::ToolType::Cone: paintObjects.append(QSharedPointer<PaintObject>(new Cone(this, paintObjects.size(), coordinate))); break; case PaintEntity::ToolType::Cylinder: paintObjects.append(QSharedPointer<PaintObject>(new Cylinder(this, paintObjects.size(), coordinate))); break; case PaintEntity::ToolType::Torus: paintObjects.append(QSharedPointer<PaintObject>(new Torus(this, paintObjects.size(), coordinate))); break; case PaintEntity::ToolType::ExtrudedText: paintObjects.append(QSharedPointer<PaintObject>(new ExtrudedText(this, paintObjects.size(), coordinate))); break; default: // This branch should never be executed break; } int currentIndex = paintObjects.size() - 1; paintObjects.at(currentIndex)->setColor(activeColor); QObject::connect(paintObjects.at(currentIndex).data(), &PaintObject::picked, this, &PaintEntity::paintObjectPicked); QObject::connect(paintObjects.at(currentIndex).data(), &PaintObject::readyForDeletion, this, &PaintEntity::removePaintObject); } void PaintEntity::onBasePlaneMouseMoved(const QVector3D &coordinate) { paintObjects.at(paintObjects.size() - 1)->onMouseMoved(coordinate); } void PaintEntity::setActiveColor(const QString &color) { activeColor = color; if (activeTool == PaintEntity::ToolType::Select) { if (activePaintObject != nullptr) { activePaintObject->setColor(activeColor); } } } PaintEntity::ToolType PaintEntity::getActiveTool() { return activeTool; } void PaintEntity::setActiveTool(ToolType tool) { activeTool = tool; bool pickerState = false; if ((activeTool == PaintEntity::ToolType::Select) || (activeTool == PaintEntity::ToolType::Delete)) { pickerState = true; } for (int i = 0; i < paintObjects.size(); i++) { paintObjects.at(i)->setPickerEnabled(pickerState); } } PaintObject* PaintEntity::getPaintObject() { return activePaintObject; }
import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQml.Models 2.15 import QtQuick.Layouts 1.15 import QtQuick.Shapes 1.15 Rectangle { id: rootRectangle color: "#606065" height: controlsColumn.height property string textInput: qsTr("Text") property string initialText: qsTr("Text") Column { id: controlsColumn spacing: 2 anchors.horizontalCenter: parent.horizontalCenter TextInput { color: "white" font.pointSize: 16 onVisibleChanged: { if (visible === true) { text = initialText; } } onTextEdited: { if (text === "") { text = "-"; } textInput = text; } } } }
import QtQuick 2.15 import QtQuick.Window 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 import Qt3D.Core 2.15 import QtQuick3D 1.15 import QtQuick.Scene3D 2.15 import Qt3D.Render 2.15 import Qt3D.Input 2.15 import Qt3D.Extras 2.15 import QtQuick3D.Materials 1.15 import "../qml/objects" import microtechnics.paintEntity 1.0 import microtechnics.paintObject 1.0 ApplicationWindow { id: window width: Screen.width * 3 / 4 height: Screen.height * 3 / 4 visible: true title: qsTr("mtPaint3D") color: "#505050" onClosing: { paintEntity.destroy(); } GridLayout { id: mainLayout rows: 12 columns: 6 flow: GridLayout.TopToBottom anchors.fill: parent component GridRectangle : Rectangle { Layout.fillHeight: true Layout.fillWidth: true Layout.preferredWidth: Layout.columnSpan Layout.preferredHeight: Layout.rowSpan color: "#808080" border.color: Qt.darker(color) border.width: 1 } GridRectangle { id: objectBlock Layout.row: 0 Layout.column: 0 Layout.rowSpan: 12 Layout.columnSpan: 1 ScrollView { clip: true anchors.fill: parent contentHeight: toolPanel.height + colorPanel.height + colorPanel.anchors.topMargin + transformPanel.height + transformPanel.anchors.topMargin + objectsPanels.childrenRect.height + extrudedTextPanel.anchors.topMargin ToolPanel { id: toolPanel anchors.left: parent.left anchors.right: parent.right anchors.top: parent.top onSelectedToolChanged: { if ((toolPanel.selectedTool === PaintEntity.ToolType.Select) || (toolPanel.selectedTool === PaintEntity.ToolType.Delete)) { baseCuboidPicker.paintEnabled = false; } else { baseCuboidPicker.paintEnabled = true; } paintEntity.activeTool = toolPanel.selectedTool; } } ColorPanel { id: colorPanel anchors.left: parent.left anchors.right: parent.right anchors.top: toolPanel.bottom anchors.topMargin: 10 visible: true onSelectedColorChanged: { paintEntity.setActiveColor(selectedColor); } } TransformPanel { id: transformPanel anchors.left: parent.left anchors.right: parent.right anchors.top: colorPanel.bottom anchors.topMargin: 10 visible: false positionLimits: Qt.vector3d(baseCuboid.xExtent, baseCuboid.yExtent, 20) onAngleChanged: { if (paintEntity.activePaintObject !== null) { paintEntity.activePaintObject.rotate(angle); } } onPositionChanged: { if (paintEntity.activePaintObject !== null) { paintEntity.activePaintObject.move(position); } } } Item { id: objectsPanels anchors.left: parent.left anchors.right: parent.right anchors.top: transformPanel.bottom CommonObjectPanel { id: commonObjectPanel anchors.left: parent.left anchors.right: parent.right visible: false onParametersChanged: { if (paintEntity.activePaintObject !== null) { paintEntity.activePaintObject.update(parameters); } } } ExtrudedTextPanel { id: extrudedTextPanel anchors.left: parent.left anchors.right: parent.right anchors.top: commonObjectPanel.bottom anchors.topMargin: 20 visible: false onTextInputChanged: { if (paintEntity.activePaintObject !== null) { paintEntity.activePaintObject.updateText(textInput); } } } } } } GridRectangle { id: viewBlock Layout.row: 0 Layout.column: 1 Layout.rowSpan: 1 Layout.columnSpan: 5 Row { id: viewButtonsRow spacing: 2 anchors.horizontalCenter: parent.horizontalCenter anchors.verticalCenter: parent.verticalCenter Button { id: topViewButton text: qsTr("Top View") onClicked: ParallelAnimation { PropertyAnimation { target: camera; property: "position"; to: Qt.vector3d(0.0, 0.0, 35.0); duration: 675; } PropertyAnimation { target: camera; property: "upVector"; to: Qt.vector3d(0.0, 1.0, 0.0); duration: 675; } } } Button { id: frontViewButton text: qsTr("Front View") onClicked: ParallelAnimation { PropertyAnimation { target: camera; property: "position"; to: Qt.vector3d(0.0, -25.0, 25.0); duration: 675; } PropertyAnimation { target: camera; property: "upVector"; to: Qt.vector3d(0.0, 0.0, 1.0); duration: 675; } } } } } GridRectangle { id: paintBlock Layout.row: 1 Layout.column: 1 Layout.rowSpan: 11 Layout.columnSpan: 5 Scene3D { id: scene3D anchors.fill: parent focus: true aspects: ["input", "logic"] Entity { id: rootEntity Entity { id: lightEntity components: [ PointLight { color: "#ffffa7" intensity: 0.5 enabled: true }, Transform { translation: Qt.vector3d(10, 0, 10) } ] } Camera { id: camera projectionType: CameraLens.PerspectiveProjection fieldOfView: 45 nearPlane : 0.1 farPlane : 100 aspectRatio: 1 position: Qt.vector3d(0.0, -25.0, 25.0) upVector: Qt.vector3d(0.0, 0.0, 1.0) viewCenter: Qt.vector3d(0.0, 0.0, 0.0) } PaintCameraController { camera: camera lookSpeed: 35 } RenderSettings { id: renderSettings activeFrameGraph: ForwardRenderer { camera: camera clearColor: "transparent" } pickingSettings.pickMethod: PickingSettings.TrianglePicking } InputSettings { id: inputSettings } Entity { id: baseCuboidEntity CuboidMesh { id: baseCuboid xExtent: 35 yExtent: 25 zExtent: basePlaneZExtent } Transform { id: baseCuboidTransform } DiffuseSpecularMaterial { id: baseCuboidMaterial ambient: "#ffffff" shininess: 100 } ObjectPicker { id: baseCuboidPicker hoverEnabled: true dragEnabled: true enabled: true property bool isAddingPaintObject: false property bool paintEnabled: true onPressed: { if (paintEnabled === true) { if (pick.buttons === Qt.LeftButton) { isAddingPaintObject = true; paintEntity.onBasePlaneMousePressed(pick.worldIntersection); } } } onMoved: { var hoverCoordinate = Qt.vector3d(pick.worldIntersection.x, pick.worldIntersection.y, basePlaneHoverTransform.translation.z); basePlaneHoverTransform.translation = hoverCoordinate; if (paintEnabled === true) { if (isAddingPaintObject === true) { paintEntity.onBasePlaneMouseMoved(pick.worldIntersection); } } } onReleased: { isAddingPaintObject = false; } } components: [ baseCuboid, baseCuboidMaterial, baseCuboidTransform, baseCuboidPicker ] } Entity { id: basePlaneHoverEntity enabled: true property var zCoordinate: 0.01 PlaneMesh { id: basePlaneHoverMesh width: 0.3 height: 0.3 } Transform { id: basePlaneHoverTransform translation: Qt.vector3d(0, 0, baseCuboid.zExtent + basePlaneHoverEntity.zCoordinate) rotationX: 90 } GoochMaterial { id: basePlaneHoverMaterial alpha: 1 cool: "#0000b0" } components: [ basePlaneHoverMesh, basePlaneHoverMaterial, basePlaneHoverTransform ] } PaintEntity { id: paintEntity function hideObjectControls() { for (var i = 0; i < objectsPanels.visibleChildren.length; i++) { objectsPanels.visibleChildren[i].visible = false; } transformPanel.visible = false; extrudedTextPanel.visible = false; commonObjectPanel.visible = false; } onActivePaintObjectChanged: { hideObjectControls(); if (activePaintObject !== null) { colorPanel.setCurrentItem(activePaintObject.color); transformPanel.initialPosition = activePaintObject.position; transformPanel.reset(); transformPanel.visible = true; switch(activePaintObject.type) { case PaintObject.Type.Cuboid: commonObjectPanel.controlsModel = [ {text: qsTr("X extent"), sliderMin: 0.1, sliderMax: baseCuboid.xExtent, sliderCurrent: activePaintObject.parameters[0]}, {text: qsTr("Y extent"), sliderMin: 0.1, sliderMax: baseCuboid.yExtent, sliderCurrent: activePaintObject.parameters[1]}, {text: qsTr("Z extent"), sliderMin: 0.1, sliderMax: 10, sliderCurrent: activePaintObject.parameters[2]} ]; break; case PaintObject.Type.Cone: commonObjectPanel.controlsModel = [ {text: qsTr("Length"), sliderMin: 0.1, sliderMax: 10, sliderCurrent: activePaintObject.parameters[0]}, {text: qsTr("Bottom radius"), sliderMin: 0.1, sliderMax: 10, sliderCurrent: activePaintObject.parameters[1]}, {text: qsTr("Top radius"), sliderMin: 0.1, sliderMax: 8, sliderCurrent: activePaintObject.parameters[2]} ]; break; case PaintObject.Type.Sphere: commonObjectPanel.controlsModel = [ {text: qsTr("Radius"), sliderMin: 0.1, sliderMax: 10, sliderCurrent: activePaintObject.parameters[0]} ]; break; case PaintObject.Type.Cylinder: commonObjectPanel.controlsModel = [ {text: qsTr("Length"), sliderMin: 0.1, sliderMax: 10, sliderCurrent: activePaintObject.parameters[0]}, {text: qsTr("Radius"), sliderMin: 0.1, sliderMax: 10, sliderCurrent: activePaintObject.parameters[1]} ]; break; case PaintObject.Type.Torus: commonObjectPanel.controlsModel = [ {text: qsTr("Minor radius"), sliderMin: 0.1, sliderMax: 1, sliderCurrent: activePaintObject.parameters[0]}, {text: qsTr("Radius"), sliderMin: 0.1, sliderMax: 10, sliderCurrent: activePaintObject.parameters[1]} ]; break; case PaintObject.Type.ExtrudedText: commonObjectPanel.controlsModel = [ {text: qsTr("Scale"), sliderMin: 0.1, sliderMax: 5, sliderCurrent: activePaintObject.parameters[0]} ]; extrudedTextPanel.initialText = activePaintObject.text; extrudedTextPanel.visible = true; break; default: break; } commonObjectPanel.visible = true; } } } } } } } }
#include "cone.h" constexpr int parametersVectorSize = 3; constexpr qreal defaultLength = 5; constexpr qreal defaultRadiusRatio = 0.1; Cone::Cone(Qt3DCore::QEntity *parentEntity, quint32 objectId, const QVector3D &coordinate) : PaintObject(parentEntity, objectId) { type = PaintObject::Type::Cone; Qt3DExtras::QConeMesh *mesh = new Qt3DExtras::QConeMesh(); Qt3DCore::QTransform *transform = new Qt3DCore::QTransform(); mesh->setHasBottomEndcap(true); mesh->setHasTopEndcap(true); mesh->setLength(defaultLength); mesh->setBottomRadius(0); mesh->setTopRadius(mesh->bottomRadius() * defaultRadiusRatio); mesh->setSlices(50); transform->setTranslation(QVector3D(coordinate.x(), coordinate.y(), constants::basePlaneZExtent / 2 + defaultLength / 2)); transform->setRotationX(90); initialCoordinate = coordinate; entity->addComponent(mesh); entity->addComponent(transform); addMaterial(); } void Cone::onMouseMoved(const QVector3D &coordinate) { Qt3DExtras::QConeMesh *currentMesh = entity->componentsOfType<Qt3DExtras::QConeMesh>().at(0); QVector3D mouseMoveVector = QVector3D(qAbs(coordinate.x() - initialCoordinate.x()), qAbs(coordinate.y() - initialCoordinate.y()), 0); currentMesh->setBottomRadius(mouseMoveVector.length()); currentMesh->setTopRadius(currentMesh->bottomRadius() * defaultRadiusRatio); } QVector<qreal> Cone::getParameters() { QVector<qreal> parameters; for (int i = 0; i < parametersVectorSize; i++) { parameters.append(0); } Qt3DExtras::QConeMesh *currentMesh = entity->componentsOfType<Qt3DExtras::QConeMesh>().at(0); parameters[0] = currentMesh->length(); parameters[1] = currentMesh->bottomRadius(); parameters[2] = currentMesh->topRadius(); return parameters; } void Cone::update(const QVector<qreal> ¶meters) { if (parameters.size() >= parametersVectorSize) { Qt3DExtras::QConeMesh *currentMesh = entity->componentsOfType<Qt3DExtras::QConeMesh>().at(0); qreal deltaLength = parameters.at(0) - currentMesh->length(); currentMesh->setLength(parameters.at(0)); currentMesh->setBottomRadius(parameters.at(1)); currentMesh->setTopRadius(parameters.at(2)); Qt3DCore::QTransform *currentTransform = entity->componentsOfType<Qt3DCore::QTransform>().at(0); currentTransform->setTranslation(currentTransform->translation() + currentTransform->rotation().rotatedVector(QVector3D(0, deltaLength / 2, 0))); } }
#include "cylinder.h" constexpr int parametersVectorSize = 3; constexpr qreal defaultLength = 5; Cylinder::Cylinder(Qt3DCore::QEntity *parentEntity, quint32 objectId, const QVector3D &coordinate) : PaintObject(parentEntity, objectId) { type = PaintObject::Type::Cylinder; Qt3DExtras::QCylinderMesh *mesh = new Qt3DExtras::QCylinderMesh(); Qt3DCore::QTransform *transform = new Qt3DCore::QTransform(); mesh->setLength(defaultLength); mesh->setRadius(0); mesh->setSlices(50); transform->setTranslation(QVector3D(coordinate.x(), coordinate.y(), constants::basePlaneZExtent / 2 + defaultLength / 2)); transform->setRotationX(90); initialCoordinate = coordinate; entity->addComponent(mesh); entity->addComponent(transform); addMaterial(); } void Cylinder::onMouseMoved(const QVector3D &coordinate) { Qt3DExtras::QCylinderMesh *currentMesh = entity->componentsOfType<Qt3DExtras::QCylinderMesh>().at(0); QVector3D mouseMoveVector = QVector3D(qAbs(coordinate.x() - initialCoordinate.x()), qAbs(coordinate.y() - initialCoordinate.y()), 0); currentMesh->setRadius(mouseMoveVector.length()); } QVector<qreal> Cylinder::getParameters() { QVector<qreal> parameters; for (int i = 0; i < parametersVectorSize; i++) { parameters.append(0); } Qt3DExtras::QCylinderMesh *currentMesh = entity->componentsOfType<Qt3DExtras::QCylinderMesh>().at(0); parameters[0] = currentMesh->length(); parameters[1] = currentMesh->radius(); return parameters; } void Cylinder::update(const QVector<qreal> ¶meters) { if (parameters.size() >= parametersVectorSize) { Qt3DExtras::QCylinderMesh *currentMesh = entity->componentsOfType<Qt3DExtras::QCylinderMesh>().at(0); qreal deltaLength = parameters.at(0) - currentMesh->length(); currentMesh->setLength(parameters.at(0)); currentMesh->setRadius(parameters.at(1)); Qt3DCore::QTransform *currentTransform = entity->componentsOfType<Qt3DCore::QTransform>().at(0); currentTransform->setTranslation(currentTransform->translation() + currentTransform->rotation().rotatedVector(QVector3D(0, deltaLength / 2, 0))); } }
#include "extrudedtext.h" constexpr int parametersVectorSize = 1; constexpr qreal defaultDepth = 0.25; constexpr qreal mouseScaleRatio = 2.5; ExtrudedText::ExtrudedText(Qt3DCore::QEntity *parentEntity, quint32 objectId, const QVector3D &coordinate) : PaintObject(parentEntity, objectId) { type = PaintObject::Type::ExtrudedText; Qt3DExtras::QExtrudedTextMesh *mesh = new Qt3DExtras::QExtrudedTextMesh(); Qt3DCore::QTransform *transform = new Qt3DCore::QTransform(); mesh->setDepth(defaultDepth); mesh->setText("Text"); transform->setTranslation(QVector3D(coordinate.x(), coordinate.y(), constants::basePlaneZExtent / 2)); transform->setScale(0); transform->setRotationX(45); initialCoordinate = coordinate; entity->addComponent(mesh); entity->addComponent(transform); addMaterial(); } void ExtrudedText::onMouseMoved(const QVector3D &coordinate) { Qt3DCore::QTransform *currentTransform = entity->componentsOfType<Qt3DCore::QTransform>().at(0); QVector3D mouseMoveVector = QVector3D(qAbs(coordinate.x() - initialCoordinate.x()), 0, 0); currentTransform->setScale(mouseMoveVector.length() / mouseScaleRatio); } QVector<qreal> ExtrudedText::getParameters() { QVector<qreal> parameters; for (int i = 0; i < parametersVectorSize; i++) { parameters.append(0); } Qt3DCore::QTransform *currentTransform = entity->componentsOfType<Qt3DCore::QTransform>().at(0); parameters[0] = currentTransform->scale(); return parameters; } void ExtrudedText::update(const QVector<qreal> ¶meters) { if (parameters.size() >= parametersVectorSize) { Qt3DCore::QTransform *currentTransform = entity->componentsOfType<Qt3DCore::QTransform>().at(0); currentTransform->setScale(parameters.at(0)); } } QString ExtrudedText::getText() { Qt3DExtras::QExtrudedTextMesh *currentMesh = entity->componentsOfType<Qt3DExtras::QExtrudedTextMesh>().at(0); return currentMesh->text(); } void ExtrudedText::updateText(QString text) { Qt3DExtras::QExtrudedTextMesh *currentMesh = entity->componentsOfType<Qt3DExtras::QExtrudedTextMesh>().at(0); if (text.isEmpty() == true) { text = "-"; } currentMesh->setText(text); }
#include "torus.h" constexpr int parametersVectorSize = 3; constexpr qreal defaultMinorRadius = 0.5; Torus::Torus(Qt3DCore::QEntity *parentEntity, quint32 objectId, const QVector3D &coordinate) : PaintObject(parentEntity, objectId) { type = PaintObject::Type::Torus; Qt3DExtras::QTorusMesh *mesh = new Qt3DExtras::QTorusMesh(); Qt3DCore::QTransform *transform = new Qt3DCore::QTransform(); mesh->setMinorRadius(defaultMinorRadius); mesh->setRadius(0); mesh->setRings(50); transform->setTranslation(QVector3D(coordinate.x(), coordinate.y(), constants::basePlaneZExtent / 2 + defaultMinorRadius)); initialCoordinate = coordinate; entity->addComponent(mesh); entity->addComponent(transform); addMaterial(); } void Torus::onMouseMoved(const QVector3D &coordinate) { Qt3DExtras::QTorusMesh *currentMesh = entity->componentsOfType<Qt3DExtras::QTorusMesh>().at(0); QVector3D mouseMoveVector = QVector3D(qAbs(coordinate.x() - initialCoordinate.x()), qAbs(coordinate.y() - initialCoordinate.y()), 0); currentMesh->setRadius(mouseMoveVector.length()); } QVector<qreal> Torus::getParameters() { QVector<qreal> parameters; for (int i = 0; i < parametersVectorSize; i++) { parameters.append(0); } Qt3DExtras::QTorusMesh *currentMesh = entity->componentsOfType<Qt3DExtras::QTorusMesh>().at(0); parameters[0] = currentMesh->minorRadius(); parameters[1] = currentMesh->radius(); return parameters; } void Torus::update(const QVector<qreal> ¶meters) { if (parameters.size() >= parametersVectorSize) { Qt3DExtras::QTorusMesh *currentMesh = entity->componentsOfType<Qt3DExtras::QTorusMesh>().at(0); qreal deltaLength = 0;//parameters.at(0) - currentMesh->length(); currentMesh->setMinorRadius(parameters.at(0)); currentMesh->setRadius(parameters.at(1)); Qt3DCore::QTransform *currentTransform = entity->componentsOfType<Qt3DCore::QTransform>().at(0); currentTransform->setTranslation(currentTransform->translation() + currentTransform->rotation().rotatedVector(QVector3D(0, deltaLength / 2, 0))); } }
Исходный код и проект: mtPaint3D_day_7