Skip to content

Commit

Permalink
Merge pull request #2235 from alicevision/dev/resectionIdFiltering
Browse files Browse the repository at this point in the history
[Viewer3D] Add slider to display cameras based on their resection IDs
  • Loading branch information
fabiencastan committed Nov 17, 2023
2 parents 5e435ed + a579ea3 commit df6d38f
Show file tree
Hide file tree
Showing 9 changed files with 301 additions and 18 deletions.
76 changes: 76 additions & 0 deletions meshroom/ui/qml/Controls/ExpandableGroup.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.11
import MaterialIcons 2.2

/**
* A custom GroupBox with predefined header that can be hidden and expanded.
*/
GroupBox {
id: root

title: ""
property int sidePadding: 6
property alias labelBackground: labelBg
property alias toolBarContent: toolBar.data
property bool expanded: expandButton.checked

padding: 2
leftPadding: sidePadding
rightPadding: sidePadding
topPadding: label.height + padding
background: Item {}

label: Pane {
background: Rectangle {
id: labelBg
color: palette.base
opacity: 0.8

MouseArea {
anchors.fill: parent
onClicked: {
expandButton.checked = !expandButton.checked
}
}
}
padding: 2
width: root.width

RowLayout {
width: parent.width
Label {
text: root.title
Layout.fillWidth: true
elide: Text.ElideRight
padding: 3
font.bold: true
font.pointSize: 8
}
RowLayout {
id: toolBar
height: parent.height

MaterialToolButton {
id: expandButton
ToolTip.text: "Expand More"
text: MaterialIcons.expand_more
font.pointSize: 10
implicitHeight: parent.height
checkable: true
checked: false

onCheckedChanged: {
if (checked) {
ToolTip.text = "Expand Less"
text = MaterialIcons.expand_less
} else {
ToolTip.text = "Expand More"
text = MaterialIcons.expand_more
}
}
}
}
}
}
}
1 change: 1 addition & 0 deletions meshroom/ui/qml/Controls/qmldir
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module Controls

ColorChart 1.0 ColorChart.qml
ExpandableGroup 1.0 ExpandableGroup.qml
FloatingPane 1.0 FloatingPane.qml
Group 1.0 Group.qml
KeyValue 1.0 KeyValue.qml
Expand Down
1 change: 1 addition & 0 deletions meshroom/ui/qml/MaterialIcons/MaterialIcons.qml
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ QtObject {
readonly property string attachment: "\ue2bc"
readonly property string audiotrack: "\ue3a1"
readonly property string autorenew: "\ue863"
readonly property string auto_awesome_motion: "\ue661"
readonly property string av_timer: "\ue01b"
readonly property string backspace: "\ue14a"
readonly property string backup: "\ue864"
Expand Down
183 changes: 170 additions & 13 deletions meshroom/ui/qml/Viewer3D/Inspector3D.qml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ FloatingPane {
anchors.fill: parent
spacing: 4

Group {
ExpandableGroup {
id: displayGroup
Layout.fillWidth: true
title: "DISPLAY"

Expand All @@ -43,6 +44,7 @@ FloatingPane {
Flow {
Layout.columnSpan: 2
Layout.fillWidth: true
visible: displayGroup.expanded
spacing: 1
MaterialToolButton {
text: MaterialIcons.grid_on
Expand All @@ -63,8 +65,13 @@ FloatingPane {
onClicked: Viewer3DSettings.displayOrigin = !Viewer3DSettings.displayOrigin
}
}
MaterialLabel { text: MaterialIcons.grain; padding: 2 }
MaterialLabel {
text: MaterialIcons.grain
padding: 2
visible: displayGroup.expanded
}
RowLayout {
visible: displayGroup.expanded
Slider {
Layout.fillWidth: true; from: 0; to: 5; stepSize: 0.001
value: Viewer3DSettings.pointSize
Expand All @@ -83,8 +90,13 @@ FloatingPane {
}

}
MaterialLabel { text: MaterialIcons.videocam; padding: 2 }
MaterialLabel {
text: MaterialIcons.videocam
padding: 2
visible: displayGroup.expanded
}
Slider {
visible: displayGroup.expanded
value: Viewer3DSettings.cameraScale
from: 0
to: 2
Expand All @@ -99,25 +111,30 @@ FloatingPane {
}
}

Group {
ExpandableGroup {
id: cameraGroup
Layout.fillWidth: true
title: "CAMERA"

ColumnLayout {
width: parent.width

// Image/Camera synchronization
Flow {
Layout.fillWidth: true
visible: cameraGroup.expanded
spacing: 2

// Synchronization
MaterialToolButton {
id: syncViewpointCamera
enabled: _reconstruction ? _reconstruction.sfmReport : false
text: MaterialIcons.linked_camera
ToolTip.text: "Sync with Image Selection"
ToolTip.text: "View Through The Active Camera"
checked: enabled && Viewer3DSettings.syncViewpointCamera
onClicked: Viewer3DSettings.syncViewpointCamera = !Viewer3DSettings.syncViewpointCamera
}

// Image Overlay controls
RowLayout {
visible: syncViewpointCamera.enabled && Viewer3DSettings.syncViewpointCamera
Expand Down Expand Up @@ -152,6 +169,109 @@ FloatingPane {
onClicked: Viewer3DSettings.viewpointImageFrame = !Viewer3DSettings.viewpointImageFrame
}
}

ColumnLayout {
Layout.fillWidth: true
spacing: 2
visible: cameraGroup.expanded

RowLayout {
Layout.fillHeight: true
spacing: 2

MaterialToolButton {
id: resectionIdButton
text: MaterialIcons.switch_video
ToolTip.text: "Timeline Of Camera Reconstruction Groups"
ToolTip.visible: hovered
enabled: Viewer3DSettings.resectionIdCount
checked: enabled && Viewer3DSettings.displayResectionIds
onClicked: {
Viewer3DSettings.displayResectionIds = !Viewer3DSettings.displayResectionIds
Viewer3DSettings.resectionId = Viewer3DSettings.resectionIdCount
resectionIdSlider.value = Viewer3DSettings.resectionId
}

onEnabledChanged: {
Viewer3DSettings.resectionId = Viewer3DSettings.resectionIdCount
resectionIdSlider.value = Viewer3DSettings.resectionId
if (!enabled) {
Viewer3DSettings.displayResectionIds = false
}
}
}

Slider {
id: resectionIdSlider
value: Viewer3DSettings.resectionId
from: 0
to: Viewer3DSettings.resectionIdCount
stepSize: 1
onMoved: Viewer3DSettings.resectionId = value
Layout.fillWidth: true
leftPadding: 2
rightPadding: 2
visible: Viewer3DSettings.displayResectionIds
}

Label {
text: resectionIdSlider.value + "/" + Viewer3DSettings.resectionIdCount
visible: Viewer3DSettings.displayResectionIds
}
}

RowLayout {
spacing: 10
Layout.fillWidth: true
Layout.margins: 2
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter

MaterialToolLabel {
iconText: MaterialIcons.stop
label: {
var id = undefined
// Ensure there are entries in resectionGroups and a valid resectionId before accessing anything
if (Viewer3DSettings.resectionId !== undefined && Viewer3DSettings.resectionGroups.length > 0)
id = Math.min(Viewer3DSettings.resectionId, Viewer3DSettings.resectionIdCount)
if (id !== undefined && Viewer3DSettings.resectionGroups[id] !== undefined)
return Viewer3DSettings.resectionGroups[id]
return 0

}
ToolTip.text: "Number Of Cameras In Current Resection Group"
visible: Viewer3DSettings.displayResectionIds
}

MaterialToolLabel {
iconText: MaterialIcons.auto_awesome_motion
label: {
let currentCameras = 0
for (let i = 0; i <= Viewer3DSettings.resectionIdCount; i++) {
if (i <= Viewer3DSettings.resectionId)
currentCameras += Viewer3DSettings.resectionGroups[i]
}

return currentCameras
}
ToolTip.text: "Number Of Cumulated Cameras"
visible: Viewer3DSettings.displayResectionIds
}

MaterialToolLabel {
iconText: MaterialIcons.videocam
label: {
let totalCameras = 0
for (let i = 0; i <= Viewer3DSettings.resectionIdCount; i++) {
totalCameras += Viewer3DSettings.resectionGroups[i]
}

return totalCameras
}
ToolTip.text: "Total Number Of Cameras"
visible: Viewer3DSettings.displayResectionIds
}
}
}
}
}

Expand Down Expand Up @@ -192,6 +312,12 @@ FloatingPane {

ScrollBar.vertical: ScrollBar { id: scrollBar }

onCountChanged: {
if (mediaListView.count === 0) {
Viewer3DSettings.resectionIdCount = 0
}
}

currentIndex: -1

Connections {
Expand All @@ -217,13 +343,25 @@ FloatingPane {
// add mediaLibrary.count in the binding to ensure 'entity'
// is re-evaluated when mediaLibrary delegates are modified
property bool loading: model.status === SceneLoader.Loading
property bool hovered: model.attribute ? (uigraph ? uigraph.hoveredNode === model.attribute.node : false) : containsMouse
property bool hovered: model.attribute ? (uigraph ? uigraph.hoveredNode === model.attribute.node : false) : containsMouse
property bool isSelectedNode: model.attribute ? (uigraph ? uigraph.selectedNode === model.attribute.node : false) : false

onIsSelectedNodeChanged: updateCurrentIndex()

function updateCurrentIndex() {
if(isSelectedNode) { mediaListView.currentIndex = index }
if (isSelectedNode) {
mediaListView.currentIndex = index
}

// If the index is updated, and the resection ID count is available, update every resection-related variable:
// this covers the changes of index that occur when a node whose output is already loaded in the 3D viewer is
// clicked/double-clicked, and when the active entry is removed from the list.
if (model.resectionIdCount) {
Viewer3DSettings.resectionIdCount = model.resectionIdCount
Viewer3DSettings.resectionGroups = model.resectionGroups
Viewer3DSettings.resectionId = model.resectionId
resectionIdSlider.value = model.resectionId
}
}

height: childrenRect.height
Expand All @@ -234,22 +372,41 @@ FloatingPane {
}

hoverEnabled: true
onEntered: { if (model.attribute) uigraph.hoveredNode = model.attribute.node }
onExited: { if (model.attribute) uigraph.hoveredNode = null }
onEntered: {
if (model.attribute)
uigraph.hoveredNode = model.attribute.node
}
onExited: {
if (model.attribute)
uigraph.hoveredNode = null
}
onClicked: {
if (model.attribute)
uigraph.selectedNode = model.attribute.node;
uigraph.selectedNode = model.attribute.node
else
uigraph.selectedNode = null;
uigraph.selectedNode = null
if (mouse.button == Qt.RightButton)
contextMenu.popup();
mediaListView.currentIndex = index;
contextMenu.popup()
mediaListView.currentIndex = index

// Update the resection ID-related objects based on the active model
Viewer3DSettings.resectionIdCount = model.resectionIdCount
Viewer3DSettings.resectionGroups = model.resectionGroups
Viewer3DSettings.resectionId = model.resectionId
resectionIdSlider.value = model.resectionId
}
onDoubleClicked: {
model.visible = true;
nodeActivated(model.attribute.node);
}

Connections {
target: resectionIdSlider
function onValueChanged() {
model.resectionId = resectionIdSlider.value
}
}

RowLayout {
width: parent.width
spacing: 2
Expand Down
8 changes: 5 additions & 3 deletions meshroom/ui/qml/Viewer3D/MediaLibrary.qml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ Entity {
"faceCount": 0,
"cameraCount": 0,
"textureCount": 0,
"resectionIdCount": 0,
"resectionId": 0,
"resectionGroups": [],
"status": SceneLoader.None
})
}
Expand Down Expand Up @@ -308,12 +311,11 @@ Entity {
if (object) {
// bind media info to corresponding model roles
// (test for object validity to avoid error messages right after object has been deleted)
var boundProperties = ["vertexCount", "faceCount", "cameraCount", "textureCount"]
var boundProperties = ["vertexCount", "faceCount", "cameraCount", "textureCount", "resectionIdCount", "resectionId", "resectionGroups"]
boundProperties.forEach(function(prop) {
model[prop] = Qt.binding(function() { return object ? object[prop] : 0 })
})
}
else if (finalSource && status === Component.Ready) {
} else if (finalSource && status === Component.Ready) {
// source was valid but no loader was created, remove element
// check if component is ready to avoid removing element from the model before adding instance to the node
remove(index)
Expand Down
Loading

0 comments on commit df6d38f

Please sign in to comment.