[ui] add 3D viewer components

This commit is contained in:
Yann Lanthony 2017-11-17 19:02:24 +01:00
parent cdcc8df33e
commit ae28a5477e
5 changed files with 446 additions and 0 deletions

View 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)
}
]
}

View 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 }
]
}

View 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;
}
}
}
]
}

View 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();
}
}
}
}

View file

@ -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