mirror of
https://github.com/alicevision/Meshroom.git
synced 2025-04-29 10:17:27 +02:00
[ui] add 3D viewer components
This commit is contained in:
parent
cdcc8df33e
commit
ae28a5477e
5 changed files with 446 additions and 0 deletions
58
meshroom/ui/qml/Viewer/Grid3D.qml
Normal file
58
meshroom/ui/qml/Viewer/Grid3D.qml
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
import QtQuick 2.7
|
||||||
|
import Qt3D.Core 2.0
|
||||||
|
import Qt3D.Render 2.0
|
||||||
|
import Qt3D.Extras 2.0
|
||||||
|
|
||||||
|
// Grid
|
||||||
|
Entity {
|
||||||
|
id: gridEntity
|
||||||
|
components: [
|
||||||
|
GeometryRenderer {
|
||||||
|
primitiveType: GeometryRenderer.Lines
|
||||||
|
geometry: Geometry {
|
||||||
|
Attribute {
|
||||||
|
id: gridPosition
|
||||||
|
attributeType: Attribute.VertexAttribute
|
||||||
|
vertexBaseType: Attribute.Float
|
||||||
|
vertexSize: 3
|
||||||
|
count: 0
|
||||||
|
name: defaultPositionAttributeName
|
||||||
|
buffer: Buffer {
|
||||||
|
type: Buffer.VertexBuffer
|
||||||
|
data: {
|
||||||
|
function buildGrid(first, last, offset, attribute) {
|
||||||
|
var vertexCount = (((last-first)/offset)+1)*4;
|
||||||
|
var f32 = new Float32Array(vertexCount*3);
|
||||||
|
for(var id = 0, i = first; i <= last; i += offset, id++)
|
||||||
|
{
|
||||||
|
f32[12*id] = i;
|
||||||
|
f32[12*id+1] = 0.0;
|
||||||
|
f32[12*id+2] = first;
|
||||||
|
|
||||||
|
f32[12*id+3] = i;
|
||||||
|
f32[12*id+4] = 0.0;
|
||||||
|
f32[12*id+5] = last;
|
||||||
|
|
||||||
|
f32[12*id+6] = first;
|
||||||
|
f32[12*id+7] = 0.0;
|
||||||
|
f32[12*id+8] = i;
|
||||||
|
|
||||||
|
f32[12*id+9] = last;
|
||||||
|
f32[12*id+10] = 0.0;
|
||||||
|
f32[12*id+11] = i;
|
||||||
|
}
|
||||||
|
attribute.count = vertexCount;
|
||||||
|
return f32;
|
||||||
|
}
|
||||||
|
return buildGrid(-12, 12, 1, gridPosition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
boundingVolumePositionAttribute: gridPosition
|
||||||
|
}
|
||||||
|
},
|
||||||
|
PhongMaterial {
|
||||||
|
ambient: Qt.rgba(0.4, 0.4, 0.4, 1)
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
56
meshroom/ui/qml/Viewer/Locator3D.qml
Normal file
56
meshroom/ui/qml/Viewer/Locator3D.qml
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
import QtQuick 2.7
|
||||||
|
import Qt3D.Core 2.0
|
||||||
|
import Qt3D.Render 2.0
|
||||||
|
import Qt3D.Extras 2.0
|
||||||
|
|
||||||
|
// Locator
|
||||||
|
Entity {
|
||||||
|
id: locatorEntity
|
||||||
|
components: [
|
||||||
|
GeometryRenderer {
|
||||||
|
primitiveType: GeometryRenderer.Lines
|
||||||
|
geometry: Geometry {
|
||||||
|
Attribute {
|
||||||
|
id: locatorPosition
|
||||||
|
attributeType: Attribute.VertexAttribute
|
||||||
|
vertexBaseType: Attribute.Float
|
||||||
|
vertexSize: 3
|
||||||
|
count: 6
|
||||||
|
name: defaultPositionAttributeName
|
||||||
|
buffer: Buffer {
|
||||||
|
type: Buffer.VertexBuffer
|
||||||
|
data: Float32Array([
|
||||||
|
0.0, 0.001, 0.0,
|
||||||
|
1.0, 0.001, 0.0,
|
||||||
|
0.0, 0.001, 0.0,
|
||||||
|
0.0, 1.001, 0.0,
|
||||||
|
0.0, 0.001, 0.0,
|
||||||
|
0.0, 0.001, 1.0
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Attribute {
|
||||||
|
attributeType: Attribute.VertexAttribute
|
||||||
|
vertexBaseType: Attribute.Float
|
||||||
|
vertexSize: 3
|
||||||
|
count: 6
|
||||||
|
name: defaultColorAttributeName
|
||||||
|
buffer: Buffer {
|
||||||
|
type: Buffer.VertexBuffer
|
||||||
|
data: Float32Array([
|
||||||
|
1.0, 0.0, 0.0,
|
||||||
|
1.0, 0.0, 0.0,
|
||||||
|
0.0, 1.0, 0.0,
|
||||||
|
0.0, 1.0, 0.0,
|
||||||
|
0.0, 0.0, 1.0,
|
||||||
|
0.0, 0.0, 1.0
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
boundingVolumePositionAttribute: locatorPosition
|
||||||
|
}
|
||||||
|
},
|
||||||
|
PerVertexColorMaterial {},
|
||||||
|
Transform { id: locatorTransform }
|
||||||
|
]
|
||||||
|
}
|
128
meshroom/ui/qml/Viewer/MayaCameraController.qml
Normal file
128
meshroom/ui/qml/Viewer/MayaCameraController.qml
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
import QtQuick 2.7
|
||||||
|
import Qt3D.Core 2.1
|
||||||
|
import Qt3D.Render 2.1
|
||||||
|
import Qt3D.Input 2.1
|
||||||
|
//import Qt3D.Extras 2.0
|
||||||
|
import Qt3D.Logic 2.0
|
||||||
|
import QtQml 2.2
|
||||||
|
|
||||||
|
Entity {
|
||||||
|
|
||||||
|
id: root
|
||||||
|
property Camera camera
|
||||||
|
property real translateSpeed: 100.0
|
||||||
|
property real tiltSpeed: 500.0
|
||||||
|
property real panSpeed: 500.0
|
||||||
|
property bool moving: false
|
||||||
|
|
||||||
|
signal mousePressed(var mouse)
|
||||||
|
signal mouseReleased(var mouse)
|
||||||
|
signal mouseWheeled(var wheel)
|
||||||
|
|
||||||
|
KeyboardDevice { id: keyboardSourceDevice }
|
||||||
|
MouseDevice { id: mouseSourceDevice; sensitivity: 0.1 }
|
||||||
|
|
||||||
|
MouseHandler {
|
||||||
|
|
||||||
|
sourceDevice: mouseSourceDevice
|
||||||
|
onPressed: mousePressed(mouse)
|
||||||
|
onReleased: mouseReleased(mouse)
|
||||||
|
onWheel: {
|
||||||
|
var d = (root.camera.viewCenter.minus(root.camera.position)).length() * 0.05;
|
||||||
|
var tz = (wheel.angleDelta.y / 120) * d;
|
||||||
|
root.camera.translate(Qt.vector3d(0, 0, tz), Camera.DontTranslateViewCenter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LogicalDevice {
|
||||||
|
id: cameraControlDevice
|
||||||
|
actions: [
|
||||||
|
Action {
|
||||||
|
id: actionLMB
|
||||||
|
inputs: [
|
||||||
|
ActionInput {
|
||||||
|
sourceDevice: mouseSourceDevice
|
||||||
|
buttons: [MouseEvent.LeftButton]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
Action {
|
||||||
|
id: actionRMB
|
||||||
|
inputs: [
|
||||||
|
ActionInput {
|
||||||
|
sourceDevice: mouseSourceDevice
|
||||||
|
buttons: [MouseEvent.RightButton]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
Action {
|
||||||
|
id: actionMMB
|
||||||
|
inputs: [
|
||||||
|
ActionInput {
|
||||||
|
sourceDevice: mouseSourceDevice
|
||||||
|
buttons: [MouseEvent.MiddleButton]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
Action {
|
||||||
|
id: actionAlt
|
||||||
|
onActiveChanged: root.moving = active
|
||||||
|
inputs: [
|
||||||
|
ActionInput {
|
||||||
|
sourceDevice: keyboardSourceDevice
|
||||||
|
buttons: [Qt.Key_Alt]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
axes: [
|
||||||
|
Axis {
|
||||||
|
id: axisMX
|
||||||
|
inputs: [
|
||||||
|
AnalogAxisInput {
|
||||||
|
sourceDevice: mouseSourceDevice
|
||||||
|
axis: MouseDevice.X
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
Axis {
|
||||||
|
id: axisMY
|
||||||
|
inputs: [
|
||||||
|
AnalogAxisInput {
|
||||||
|
sourceDevice: mouseSourceDevice
|
||||||
|
axis: MouseDevice.Y
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
components: [
|
||||||
|
FrameAction {
|
||||||
|
onTriggered: {
|
||||||
|
if(!actionAlt.active)
|
||||||
|
return;
|
||||||
|
if(actionLMB.active) { // rotate
|
||||||
|
var rx = -axisMX.value;
|
||||||
|
var ry = -axisMY.value;
|
||||||
|
root.camera.panAboutViewCenter(root.panSpeed * rx * dt, Qt.vector3d(0,1,0))
|
||||||
|
root.camera.tiltAboutViewCenter(root.tiltSpeed * ry * dt)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(actionMMB.active) { // translate
|
||||||
|
var d = (root.camera.viewCenter.minus(root.camera.position)).length() * 0.03;
|
||||||
|
var tx = axisMX.value * root.translateSpeed * d;
|
||||||
|
var ty = axisMY.value * root.translateSpeed * d;
|
||||||
|
root.camera.translate(Qt.vector3d(-tx, -ty, 0).times(dt))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(actionRMB.active) { // zoom
|
||||||
|
var d = (root.camera.viewCenter.minus(root.camera.position)).length() * 0.05;
|
||||||
|
var tz = axisMX.value * root.translateSpeed * d;
|
||||||
|
root.camera.translate(Qt.vector3d(0, 0, tz).times(dt), Camera.DontTranslateViewCenter)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
199
meshroom/ui/qml/Viewer/Viewer3D.qml
Normal file
199
meshroom/ui/qml/Viewer/Viewer3D.qml
Normal file
|
@ -0,0 +1,199 @@
|
||||||
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Controls 2.3
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
|
import QtQuick.Scene3D 2.0
|
||||||
|
import Qt3D.Core 2.1
|
||||||
|
import Qt3D.Render 2.1
|
||||||
|
import Qt3D.Input 2.1
|
||||||
|
|
||||||
|
|
||||||
|
FocusScope {
|
||||||
|
|
||||||
|
id: root
|
||||||
|
|
||||||
|
// functions
|
||||||
|
function resetCameraCenter() {
|
||||||
|
mainCamera.viewCenter = Qt.vector3d(0.0, 0.0, 0.0);
|
||||||
|
mainCamera.upVector = Qt.vector3d(0.0, 1.0, 0.0);
|
||||||
|
}
|
||||||
|
function resetCameraPosition() {
|
||||||
|
mainCamera.position = Qt.vector3d(28.0, 21.0, 28.0);
|
||||||
|
mainCamera.upVector = Qt.vector3d(0.0, 1.0, 0.0);
|
||||||
|
mainCamera.viewCenter = Qt.vector3d(0.0, 0.0, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function findChildrenByProperty(node, propertyName, container)
|
||||||
|
{
|
||||||
|
if(!node || !node.childNodes)
|
||||||
|
return;
|
||||||
|
for(var i=0; i < node.childNodes.length; ++i)
|
||||||
|
{
|
||||||
|
var childNode = node.childNodes[i];
|
||||||
|
if(!childNode)
|
||||||
|
continue;
|
||||||
|
if(childNode[propertyName] !== undefined)
|
||||||
|
container.push(childNode);
|
||||||
|
else
|
||||||
|
findChildrenByProperty(childNode, propertyName, container)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function unmirrorTextures(rootEntity)
|
||||||
|
{
|
||||||
|
var materials = [];
|
||||||
|
findChildrenByProperty(rootEntity, "diffuse", materials);
|
||||||
|
|
||||||
|
var textures = [];
|
||||||
|
materials.forEach(function(mat){
|
||||||
|
mat["diffuse"].magnificationFilter = Texture.Linear;
|
||||||
|
findChildrenByProperty(mat["diffuse"], "mirrored", textures)
|
||||||
|
})
|
||||||
|
|
||||||
|
//console.log(textures)
|
||||||
|
textures.forEach(function(tex){
|
||||||
|
//console.log("Unmirroring: " + tex.source)
|
||||||
|
tex.mirrored = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadModel(url)
|
||||||
|
{
|
||||||
|
modelLoader.source = Qt.resolvedUrl(url)
|
||||||
|
}
|
||||||
|
|
||||||
|
Scene3D {
|
||||||
|
id: scene3D
|
||||||
|
anchors.fill: parent
|
||||||
|
cameraAspectRatioMode: Scene3D.AutomaticAspectRatio // vs. UserAspectRatio
|
||||||
|
hoverEnabled: false // if true, will trigger positionChanged events in attached MouseHandler
|
||||||
|
aspects: ["logic", "input"]
|
||||||
|
focus: true
|
||||||
|
Keys.onPressed: {
|
||||||
|
if (event.key == Qt.Key_F) {
|
||||||
|
resetCameraCenter();
|
||||||
|
resetCameraPosition();
|
||||||
|
event.accepted = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity {
|
||||||
|
id: rootEntity
|
||||||
|
Camera {
|
||||||
|
id: mainCamera
|
||||||
|
projectionType: CameraLens.PerspectiveProjection
|
||||||
|
fieldOfView: 45
|
||||||
|
nearPlane : 0.1
|
||||||
|
farPlane : 1000.0
|
||||||
|
position: Qt.vector3d(28.0, 21.0, 28.0)
|
||||||
|
upVector: Qt.vector3d(0.0, 1.0, 0.0)
|
||||||
|
viewCenter: Qt.vector3d(0.0, 0.0, 0.0)
|
||||||
|
aspectRatio: width/height
|
||||||
|
|
||||||
|
Behavior on viewCenter {
|
||||||
|
Vector3dAnimation { duration: 250 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MayaCameraController {
|
||||||
|
id: cameraController
|
||||||
|
camera: mainCamera
|
||||||
|
onMousePressed: scene3D.forceActiveFocus()
|
||||||
|
onMouseReleased: {
|
||||||
|
if(moving)
|
||||||
|
return;
|
||||||
|
switch(mouse.button) {
|
||||||
|
case Qt.LeftButton:
|
||||||
|
break;
|
||||||
|
case Qt.RightButton:
|
||||||
|
contextMenu.x = mouse.x;
|
||||||
|
contextMenu.y = mouse.y;
|
||||||
|
contextMenu.open();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
components: [
|
||||||
|
RenderSettings {
|
||||||
|
// To avoid performance drop, only pick triangles when not moving the camera
|
||||||
|
pickingSettings.pickMethod: cameraController.moving ? PickingSettings.BoundingVolumePicking : PickingSettings.TrianglePicking
|
||||||
|
renderPolicy: RenderSettings.Always
|
||||||
|
activeFrameGraph: Viewport {
|
||||||
|
normalizedRect: Qt.rect(0.0, 0.0, 1.0, 1.0)
|
||||||
|
RenderSurfaceSelector {
|
||||||
|
CameraSelector {
|
||||||
|
id: cameraSelector
|
||||||
|
camera: mainCamera
|
||||||
|
//FrustumCulling {
|
||||||
|
ClearBuffers {
|
||||||
|
buffers : ClearBuffers.ColorDepthBuffer
|
||||||
|
clearColor: Qt.rgba(0, 0, 0, 0.1)
|
||||||
|
}
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
InputSettings {
|
||||||
|
eventSource: _window
|
||||||
|
enabled: true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
Entity {
|
||||||
|
id: modelLoader
|
||||||
|
property alias source: scene.source
|
||||||
|
components: [scene, transform, picker]
|
||||||
|
ObjectPicker {
|
||||||
|
id: picker
|
||||||
|
hoverEnabled: false
|
||||||
|
onPressed: {
|
||||||
|
if(Qt.LeftButton & pick.buttons)
|
||||||
|
{
|
||||||
|
if(!doubleClickTimer.running)
|
||||||
|
doubleClickTimer.start()
|
||||||
|
else
|
||||||
|
mainCamera.viewCenter = pick.worldIntersection
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
id: doubleClickTimer
|
||||||
|
running: false
|
||||||
|
interval: 400
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Transform {
|
||||||
|
id: transform
|
||||||
|
|
||||||
|
}
|
||||||
|
SceneLoader {
|
||||||
|
id: scene
|
||||||
|
onStatusChanged: {
|
||||||
|
if(scene.status == SceneLoader.Ready)
|
||||||
|
unmirrorTextures(parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Locator3D {}
|
||||||
|
}
|
||||||
|
|
||||||
|
Grid3D { }
|
||||||
|
Locator3D {}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// menus
|
||||||
|
Menu {
|
||||||
|
id: contextMenu
|
||||||
|
MenuItem {
|
||||||
|
text: "Reset camera position [F]"
|
||||||
|
onTriggered: {
|
||||||
|
resetCameraCenter();
|
||||||
|
resetCameraPosition();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,3 +1,8 @@
|
||||||
module Viewer
|
module Viewer
|
||||||
|
|
||||||
Viewer2D 1.0 Viewer2D.qml
|
Viewer2D 1.0 Viewer2D.qml
|
||||||
|
Viewer3D 1.0 Viewer3D.qml
|
||||||
|
MayaCameraController 1.0 MayaCameraController.qml
|
||||||
|
Locator3D 1.0 Locator3D.qml
|
||||||
|
Grid3D 1.0 Grid3D.qml
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue