mirror of
https://github.com/alicevision/Meshroom.git
synced 2025-04-28 17:57:16 +02:00
Backup viewer performance experiments
This commit is contained in:
parent
6e99f9daeb
commit
9f1b5a9e19
6 changed files with 301 additions and 244 deletions
|
@ -7,7 +7,7 @@ import json
|
||||||
from PySide6 import __version__ as PySideVersion
|
from PySide6 import __version__ as PySideVersion
|
||||||
from PySide6 import QtCore
|
from PySide6 import QtCore
|
||||||
from PySide6.QtCore import Qt, QUrl, QJsonValue, qInstallMessageHandler, QtMsgType, QSettings
|
from PySide6.QtCore import Qt, QUrl, QJsonValue, qInstallMessageHandler, QtMsgType, QSettings
|
||||||
from PySide6.QtGui import QIcon
|
from PySide6.QtGui import QIcon, QSurfaceFormat
|
||||||
from PySide6.QtWidgets import QApplication
|
from PySide6.QtWidgets import QApplication
|
||||||
|
|
||||||
import meshroom
|
import meshroom
|
||||||
|
@ -189,8 +189,13 @@ class MeshroomApp(QApplication):
|
||||||
def __init__(self, args):
|
def __init__(self, args):
|
||||||
meshroom.core.initPipelines()
|
meshroom.core.initPipelines()
|
||||||
|
|
||||||
|
|
||||||
QtArgs = [args[0], '-style', 'Fusion'] + args[1:] # force Fusion style by default
|
QtArgs = [args[0], '-style', 'Fusion'] + args[1:] # force Fusion style by default
|
||||||
|
|
||||||
|
#from PySide6.QtQml import QQmlDebuggingEnabler
|
||||||
|
#debugEnabled = QQmlDebuggingEnabler(True)
|
||||||
|
#QtArgs += ["-qmljsdebugger=port:8888"]
|
||||||
|
|
||||||
args = createMeshroomParser(args)
|
args = createMeshroomParser(args)
|
||||||
|
|
||||||
logStringToPython = {
|
logStringToPython = {
|
||||||
|
@ -213,6 +218,10 @@ class MeshroomApp(QApplication):
|
||||||
font.setPointSize(9)
|
font.setPointSize(9)
|
||||||
self.setFont(font)
|
self.setFont(font)
|
||||||
|
|
||||||
|
sFormat = QSurfaceFormat()
|
||||||
|
sFormat.setSwapInterval(0)
|
||||||
|
QSurfaceFormat.setDefaultFormat(sFormat)
|
||||||
|
|
||||||
pwd = os.path.dirname(__file__)
|
pwd = os.path.dirname(__file__)
|
||||||
self.setWindowIcon(QIcon(os.path.join(pwd, "img/meshroom.svg")))
|
self.setWindowIcon(QIcon(os.path.join(pwd, "img/meshroom.svg")))
|
||||||
|
|
||||||
|
|
|
@ -186,7 +186,7 @@ Panel {
|
||||||
highlightFollowsCurrentItem: true
|
highlightFollowsCurrentItem: true
|
||||||
keyNavigationEnabled: true
|
keyNavigationEnabled: true
|
||||||
property bool updateSelectedViewFromGrid: true
|
property bool updateSelectedViewFromGrid: true
|
||||||
|
/*
|
||||||
// Update grid current item when selected view changes
|
// Update grid current item when selected view changes
|
||||||
Connections {
|
Connections {
|
||||||
target: _reconstruction
|
target: _reconstruction
|
||||||
|
@ -195,7 +195,7 @@ Panel {
|
||||||
grid.updateCurrentIndexFromSelectionViewId()
|
grid.updateCurrentIndexFromSelectionViewId()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
function makeCurrentItemVisible() {
|
function makeCurrentItemVisible() {
|
||||||
grid.positionViewAtIndex(grid.currentIndex, GridView.Visible)
|
grid.positionViewAtIndex(grid.currentIndex, GridView.Visible)
|
||||||
}
|
}
|
||||||
|
@ -215,7 +215,7 @@ Panel {
|
||||||
_reconstruction.selectedViewId = grid.currentItem.viewpoint.get("viewId").value
|
_reconstruction.selectedViewId = grid.currentItem.viewpoint.get("viewId").value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
// Update grid item when corresponding thumbnail is computed
|
// Update grid item when corresponding thumbnail is computed
|
||||||
Connections {
|
Connections {
|
||||||
target: ThumbnailCache
|
target: ThumbnailCache
|
||||||
|
@ -233,8 +233,10 @@ Panel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
|
model: m.viewpoints
|
||||||
|
/*
|
||||||
model: SortFilterDelegateModel {
|
model: SortFilterDelegateModel {
|
||||||
id: sortedModel
|
id: sortedModel
|
||||||
model: m.viewpoints
|
model: m.viewpoints
|
||||||
|
@ -273,7 +275,6 @@ Panel {
|
||||||
|
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
delegate: ImageDelegate {
|
delegate: ImageDelegate {
|
||||||
id: imageDelegate
|
id: imageDelegate
|
||||||
|
|
||||||
|
@ -374,7 +375,7 @@ Panel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
// Keyboard shortcut to change current image group
|
// Keyboard shortcut to change current image group
|
||||||
Keys.priority: Keys.BeforeItem
|
Keys.priority: Keys.BeforeItem
|
||||||
|
|
|
@ -383,15 +383,15 @@ FloatingPane {
|
||||||
Text {
|
Text {
|
||||||
height: sync3DCheckBox.height
|
height: sync3DCheckBox.height
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
text: {
|
// text: {
|
||||||
// number of cached frames is the difference between the first and last frame of all intervals in the cache
|
// // number of cached frames is the difference between the first and last frame of all intervals in the cache
|
||||||
let cachedFrames = viewer ? viewer.cachedFrames : []
|
// let cachedFrames = viewer ? viewer.cachedFrames : []
|
||||||
let cachedFramesCount = 0
|
// let cachedFramesCount = 0
|
||||||
for (let i = 0; i < cachedFrames.length; i++) {
|
// for (let i = 0; i < cachedFrames.length; i++) {
|
||||||
cachedFramesCount += cachedFrames[i].y - cachedFrames[i].x + 1
|
// cachedFramesCount += cachedFrames[i].y - cachedFrames[i].x + 1
|
||||||
}
|
// }
|
||||||
return "Cached Frames: " + (viewer ? cachedFramesCount : "0") + " / " + sortedViewIds.length
|
// return "Cached Frames: " + (viewer ? cachedFramesCount : "0") + " / " + sortedViewIds.length
|
||||||
}
|
// }
|
||||||
color: palette.text
|
color: palette.text
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,8 +21,8 @@ FocusScope {
|
||||||
property url source
|
property url source
|
||||||
property var viewIn3D
|
property var viewIn3D
|
||||||
|
|
||||||
property Component floatViewerComp: Qt.createComponent("FloatImage.qml")
|
// property Component floatViewerComp: Qt.createComponent("FloatImage.qml")
|
||||||
property Component panoramaViewerComp: Qt.createComponent("PanoramaViewer.qml")
|
// property Component panoramaViewerComp: Qt.createComponent("PanoramaViewer.qml")
|
||||||
property var useFloatImageViewer: displayHDR.checked
|
property var useFloatImageViewer: displayHDR.checked
|
||||||
property alias useLensDistortionViewer: displayLensDistortionViewer.checked
|
property alias useLensDistortionViewer: displayLensDistortionViewer.checked
|
||||||
property alias usePanoramaViewer: displayPanoramaViewer.checked
|
property alias usePanoramaViewer: displayPanoramaViewer.checked
|
||||||
|
@ -47,12 +47,12 @@ FocusScope {
|
||||||
property variant viewpointMetadata: {
|
property variant viewpointMetadata: {
|
||||||
// Metadata from viewpoint attribute
|
// Metadata from viewpoint attribute
|
||||||
// Read from the reconstruction object
|
// Read from the reconstruction object
|
||||||
if (_reconstruction) {
|
// if (_reconstruction) {
|
||||||
let vp = getViewpoint(_reconstruction.selectedViewId)
|
// let vp = getViewpoint(_reconstruction.selectedViewId)
|
||||||
if (vp) {
|
// if (vp) {
|
||||||
return JSON.parse(vp.childAttribute("metadata").value)
|
// return JSON.parse(vp.childAttribute("metadata").value)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
return {}
|
return {}
|
||||||
}
|
}
|
||||||
property variant imgMetadata: {
|
property variant imgMetadata: {
|
||||||
|
@ -63,13 +63,13 @@ FocusScope {
|
||||||
}
|
}
|
||||||
// Metadata from PhongImageViewer
|
// Metadata from PhongImageViewer
|
||||||
// Directly read from the image file on disk
|
// Directly read from the image file on disk
|
||||||
if (phongImageViewerLoader.active) {
|
// if (phongImageViewerLoader.active) {
|
||||||
return phongImageViewerLoader.item.metadata
|
// return phongImageViewerLoader.item.metadata
|
||||||
}
|
// }
|
||||||
// Use viewpoint metadata for the special case of the 8-bit viewer
|
// // Use viewpoint metadata for the special case of the 8-bit viewer
|
||||||
if (qtImageViewerLoader.active) {
|
// if (qtImageViewerLoader.active) {
|
||||||
return viewpointMetadata
|
// return viewpointMetadata
|
||||||
}
|
// }
|
||||||
return {}
|
return {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -218,19 +218,27 @@ FocusScope {
|
||||||
}
|
}
|
||||||
|
|
||||||
function getViewpoint(viewId) {
|
function getViewpoint(viewId) {
|
||||||
// Get viewpoint from cameraInit with matching id
|
// print("getViewpoint: " + viewId)
|
||||||
// This requires to loop over all viewpoints
|
var index = _reconstruction.viewIdToIndex(viewId)
|
||||||
for (var i = 0; i < _reconstruction.viewpoints.count; i++) {
|
if (index < 0) {
|
||||||
var vp = _reconstruction.viewpoints.at(i)
|
|
||||||
if (vp.childAttribute("viewId").value == viewId) {
|
|
||||||
return vp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return undefined
|
return undefined
|
||||||
}
|
}
|
||||||
|
// print("getViewpoint index: " + index)
|
||||||
|
return _reconstruction.viewpoints.at(index)
|
||||||
|
|
||||||
function getImageFile() {
|
// // Get viewpoint from cameraInit with matching id
|
||||||
|
// // This requires to loop over all viewpoints
|
||||||
|
// for (var i = 0; i < _reconstruction.viewpoints.count; i++) {
|
||||||
|
// var vp = _reconstruction.viewpoints.at(i)
|
||||||
|
// if (vp.childAttribute("viewId").value == viewId) {
|
||||||
|
// return vp
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
property string myImageFile: {
|
||||||
if (useExternal) {
|
if (useExternal) {
|
||||||
// Entry point for getting the image file from an external URL
|
// Entry point for getting the image file from an external URL
|
||||||
return sourceExternal
|
return sourceExternal
|
||||||
|
@ -238,28 +246,30 @@ FocusScope {
|
||||||
|
|
||||||
if (_reconstruction && (!displayedNode || outputAttribute.name == "gallery")) {
|
if (_reconstruction && (!displayedNode || outputAttribute.name == "gallery")) {
|
||||||
// Entry point for getting the image file from the gallery
|
// Entry point for getting the image file from the gallery
|
||||||
let vp = getViewpoint(_reconstruction.pickedViewId)
|
// let vp = getViewpoint(_reconstruction.pickedViewId)
|
||||||
let path = vp ? vp.childAttribute("path").value : ""
|
// let path = vp ? vp.childAttribute("path").value : ""
|
||||||
_reconstruction.currentViewPath = path
|
// _reconstruction.currentViewPath = path
|
||||||
|
var viewId = sequencePlayer.sortedViewIds[currentFrame - frameRange.min]
|
||||||
|
let path = _reconstruction.viewIdToPath(viewId)
|
||||||
return Filepath.stringToUrl(path)
|
return Filepath.stringToUrl(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_reconstruction && displayedNode && displayedNode.hasSequenceOutput && displayedAttr &&
|
// if (_reconstruction && displayedNode && displayedNode.hasSequenceOutput && displayedAttr &&
|
||||||
(displayedAttr.desc.semantic === "imageList" || displayedAttr.desc.semantic === "sequence")) {
|
// (displayedAttr.desc.semantic === "imageList" || displayedAttr.desc.semantic === "sequence")) {
|
||||||
// Entry point for getting the image file from a sequence defined by an output attribute
|
// // Entry point for getting the image file from a sequence defined by an output attribute
|
||||||
var path = sequence[currentFrame - frameRange.min]
|
// var path = sequence[currentFrame - frameRange.min]
|
||||||
_reconstruction.currentViewPath = path
|
// // _reconstruction.currentViewPath = path
|
||||||
return Filepath.stringToUrl(path)
|
// return Filepath.stringToUrl(path)
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (_reconstruction) {
|
// if (_reconstruction) {
|
||||||
// Entry point for getting the image file from an output attribute and associated to the current viewpoint
|
// // Entry point for getting the image file from an output attribute and associated to the current viewpoint
|
||||||
let vp = getViewpoint(_reconstruction.pickedViewId)
|
// let vp = getViewpoint(_reconstruction.pickedViewId)
|
||||||
let path = displayedAttr ? displayedAttr.value : ""
|
// let path = displayedAttr ? displayedAttr.value : ""
|
||||||
let resolved = vp ? Filepath.resolve(path, vp) : path
|
// let resolved = vp ? Filepath.resolve(path, vp) : path
|
||||||
_reconstruction.currentViewPath = resolved
|
// // _reconstruction.currentViewPath = resolved
|
||||||
return Filepath.stringToUrl(resolved)
|
// return Filepath.stringToUrl(resolved)
|
||||||
}
|
// }
|
||||||
|
|
||||||
return undefined
|
return undefined
|
||||||
}
|
}
|
||||||
|
@ -310,6 +320,7 @@ FocusScope {
|
||||||
enableSequencePlayerAction.checked = true
|
enableSequencePlayerAction.checked = true
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
print("Viewer2D: buildOrderedSequence")
|
||||||
let objs = []
|
let objs = []
|
||||||
for (let i = 0; i < _reconstruction.viewpoints.count; i++) {
|
for (let i = 0; i < _reconstruction.viewpoints.count; i++) {
|
||||||
objs.push(_reconstruction.viewpoints.at(i))
|
objs.push(_reconstruction.viewpoints.at(i))
|
||||||
|
@ -369,7 +380,7 @@ FocusScope {
|
||||||
|
|
||||||
onDisplayedAttrValueChanged: {
|
onDisplayedAttrValueChanged: {
|
||||||
if (displayedNode && !displayedNode.hasSequenceOutput) {
|
if (displayedNode && !displayedNode.hasSequenceOutput) {
|
||||||
root.source = getImageFile()
|
root.source = myImageFile
|
||||||
root.sequence = []
|
root.sequence = []
|
||||||
} else {
|
} else {
|
||||||
root.source = ""
|
root.source = ""
|
||||||
|
@ -382,7 +393,7 @@ FocusScope {
|
||||||
Connections {
|
Connections {
|
||||||
target: _reconstruction
|
target: _reconstruction
|
||||||
function onSelectedViewIdChanged() {
|
function onSelectedViewIdChanged() {
|
||||||
root.source = getImageFile()
|
root.source = myImageFile
|
||||||
if (useExternal)
|
if (useExternal)
|
||||||
useExternal = false
|
useExternal = false
|
||||||
}
|
}
|
||||||
|
@ -480,7 +491,7 @@ FocusScope {
|
||||||
// qtAliceVision Image Viewer
|
// qtAliceVision Image Viewer
|
||||||
ExifOrientedViewer {
|
ExifOrientedViewer {
|
||||||
id: floatImageViewerLoader
|
id: floatImageViewerLoader
|
||||||
active: root.aliceVisionPluginAvailable && (root.useFloatImageViewer || root.useLensDistortionViewer) && !panoramaViewerLoader.active && !phongImageViewerLoader.active
|
active: root.aliceVisionPluginAvailable && (root.useFloatImageViewer || root.useLensDistortionViewer) // && !panoramaViewerLoader.active && !phongImageViewerLoader.active
|
||||||
visible: (floatImageViewerLoader.status === Loader.Ready) && active
|
visible: (floatImageViewerLoader.status === Loader.Ready) && active
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
orientationTag: imgContainer.orientationTag
|
orientationTag: imgContainer.orientationTag
|
||||||
|
@ -553,7 +564,7 @@ FocusScope {
|
||||||
// Instantiate and initialize a FloatImage component dynamically using Loader.setSource
|
// Instantiate and initialize a FloatImage component dynamically using Loader.setSource
|
||||||
// Note: It does not work to use previously created component, so we re-create it with setSource.
|
// Note: It does not work to use previously created component, so we re-create it with setSource.
|
||||||
floatImageViewerLoader.setSource("FloatImage.qml", {
|
floatImageViewerLoader.setSource("FloatImage.qml", {
|
||||||
"source": Qt.binding(function() { return getImageFile() }),
|
"source": Qt.binding(function() { return myImageFile }),
|
||||||
"gamma": Qt.binding(function() { return hdrImageToolbar.gammaValue }),
|
"gamma": Qt.binding(function() { return hdrImageToolbar.gammaValue }),
|
||||||
"gain": Qt.binding(function() { return hdrImageToolbar.gainValue }),
|
"gain": Qt.binding(function() { return hdrImageToolbar.gainValue }),
|
||||||
"channelModeString": Qt.binding(function() { return hdrImageToolbar.channelModeValue }),
|
"channelModeString": Qt.binding(function() { return hdrImageToolbar.channelModeValue }),
|
||||||
|
@ -584,181 +595,181 @@ FocusScope {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// qtAliceVision Panorama Viewer
|
// // qtAliceVision Panorama Viewer
|
||||||
Loader {
|
// Loader {
|
||||||
id: panoramaViewerLoader
|
// id: panoramaViewerLoader
|
||||||
active: root.aliceVisionPluginAvailable && root.usePanoramaViewer &&
|
// active: root.aliceVisionPluginAvailable && root.usePanoramaViewer &&
|
||||||
_reconstruction.activeNodes.get('sfm').node
|
// _reconstruction.activeNodes.get('sfm').node
|
||||||
visible: (panoramaViewerLoader.status === Loader.Ready) && active
|
// visible: (panoramaViewerLoader.status === Loader.Ready) && active
|
||||||
anchors.centerIn: parent
|
// anchors.centerIn: parent
|
||||||
|
|
||||||
onActiveChanged: {
|
// onActiveChanged: {
|
||||||
if (active) {
|
// if (active) {
|
||||||
setSource("PanoramaViewer.qml", {
|
// setSource("PanoramaViewer.qml", {
|
||||||
"subdivisionsPano": Qt.binding(function() { return panoramaViewerToolbar.subdivisionsValue }),
|
// "subdivisionsPano": Qt.binding(function() { return panoramaViewerToolbar.subdivisionsValue }),
|
||||||
"cropFisheyePano": Qt.binding(function() { return root.cropFisheye }),
|
// "cropFisheyePano": Qt.binding(function() { return root.cropFisheye }),
|
||||||
"downscale": Qt.binding(function() { return panoramaViewerToolbar.downscaleValue }),
|
// "downscale": Qt.binding(function() { return panoramaViewerToolbar.downscaleValue }),
|
||||||
"isEditable": Qt.binding(function() { return panoramaViewerToolbar.enableEdit }),
|
// "isEditable": Qt.binding(function() { return panoramaViewerToolbar.enableEdit }),
|
||||||
"isHighlightable": Qt.binding(function() { return panoramaViewerToolbar.enableHover }),
|
// "isHighlightable": Qt.binding(function() { return panoramaViewerToolbar.enableHover }),
|
||||||
"displayGridPano": Qt.binding(function() { return panoramaViewerToolbar.displayGrid }),
|
// "displayGridPano": Qt.binding(function() { return panoramaViewerToolbar.displayGrid }),
|
||||||
"mouseMultiplier": Qt.binding(function() { return panoramaViewerToolbar.mouseSpeed }),
|
// "mouseMultiplier": Qt.binding(function() { return panoramaViewerToolbar.mouseSpeed }),
|
||||||
"msfmData": Qt.binding(function() { return (msfmDataLoader && msfmDataLoader.item && msfmDataLoader.status === Loader.Ready
|
// "msfmData": Qt.binding(function() { return (msfmDataLoader && msfmDataLoader.item && msfmDataLoader.status === Loader.Ready
|
||||||
&& msfmDataLoader.item.status === 2) ? msfmDataLoader.item : null }),
|
// && msfmDataLoader.item.status === 2) ? msfmDataLoader.item : null }),
|
||||||
})
|
// })
|
||||||
} else {
|
// } else {
|
||||||
// Forcing the unload (instead of using Component.onCompleted to load it once and for all) is necessary since Qt 5.14
|
// // Forcing the unload (instead of using Component.onCompleted to load it once and for all) is necessary since Qt 5.14
|
||||||
setSource("", {})
|
// setSource("", {})
|
||||||
displayPanoramaViewer.checked = false
|
// displayPanoramaViewer.checked = false
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
// qtAliceVision Phong Image Viewer
|
// // qtAliceVision Phong Image Viewer
|
||||||
ExifOrientedViewer {
|
// ExifOrientedViewer {
|
||||||
id: phongImageViewerLoader
|
// id: phongImageViewerLoader
|
||||||
active: root.aliceVisionPluginAvailable && displayPhongLighting.enabled && displayPhongLighting.checked
|
// active: root.aliceVisionPluginAvailable && displayPhongLighting.enabled && displayPhongLighting.checked
|
||||||
visible: (phongImageViewerLoader.status === Loader.Ready) && active
|
// visible: (phongImageViewerLoader.status === Loader.Ready) && active
|
||||||
anchors.centerIn: parent
|
// anchors.centerIn: parent
|
||||||
orientationTag: imgContainer.orientationTag
|
// orientationTag: imgContainer.orientationTag
|
||||||
xOrigin: imgContainer.width / 2
|
// xOrigin: imgContainer.width / 2
|
||||||
yOrigin: imgContainer.height / 2
|
// yOrigin: imgContainer.height / 2
|
||||||
|
|
||||||
property var activeNode: _reconstruction ? _reconstruction.activeNodes.get('PhotometricStereo').node : null
|
// property var activeNode: _reconstruction ? _reconstruction.activeNodes.get('PhotometricStereo').node : null
|
||||||
property var vp: _reconstruction ? getViewpoint(_reconstruction.selectedViewId) : null
|
// property var vp: _reconstruction ? getViewpoint(_reconstruction.selectedViewId) : null
|
||||||
property url sourcePath: getAlbedoFile()
|
// property url sourcePath: getAlbedoFile()
|
||||||
property url normalPath: getNormalFile()
|
// property url normalPath: getNormalFile()
|
||||||
property bool fittedOnce: false
|
// property bool fittedOnce: false
|
||||||
property int previousWidth: 0
|
// property int previousWidth: 0
|
||||||
property int previousHeight: 0
|
// property int previousHeight: 0
|
||||||
property int previousOrientationTag: 1
|
// property int previousOrientationTag: 1
|
||||||
|
|
||||||
function getAlbedoFile() {
|
// function getAlbedoFile() {
|
||||||
|
|
||||||
if(vp && activeNode && activeNode.hasAttribute("albedo")) {
|
// if(vp && activeNode && activeNode.hasAttribute("albedo")) {
|
||||||
return Filepath.stringToUrl(Filepath.resolve(activeNode.attribute("albedo").value, vp))
|
// return Filepath.stringToUrl(Filepath.resolve(activeNode.attribute("albedo").value, vp))
|
||||||
}
|
// }
|
||||||
|
|
||||||
return getImageFile()
|
// return myImageFile
|
||||||
}
|
// }
|
||||||
|
|
||||||
function getNormalFile() {
|
// function getNormalFile() {
|
||||||
|
|
||||||
if(vp && activeNode && activeNode.hasAttribute("normals")) {
|
// if(vp && activeNode && activeNode.hasAttribute("normals")) {
|
||||||
return Filepath.stringToUrl(Filepath.resolve(activeNode.attribute("normals").value, vp))
|
// return Filepath.stringToUrl(Filepath.resolve(activeNode.attribute("normals").value, vp))
|
||||||
}
|
// }
|
||||||
|
|
||||||
return getImageFile()
|
// return myImageFile
|
||||||
}
|
// }
|
||||||
|
|
||||||
onWidthChanged: {
|
// onWidthChanged: {
|
||||||
/* We want to do the auto-fit on the first display of an image from the group, and then keep its
|
// /* We want to do the auto-fit on the first display of an image from the group, and then keep its
|
||||||
* scale when displaying another image from the group, so we need to know if an image in the
|
// * scale when displaying another image from the group, so we need to know if an image in the
|
||||||
* group has already been auto-fitted. If we change the group of images (when another project is
|
// * group has already been auto-fitted. If we change the group of images (when another project is
|
||||||
* opened, for example, and the images have a different size), then another auto-fit needs to be
|
// * opened, for example, and the images have a different size), then another auto-fit needs to be
|
||||||
* performed */
|
// * performed */
|
||||||
if ((!fittedOnce && imgContainer.image && imgContainer.image.width > 0) ||
|
// if ((!fittedOnce && imgContainer.image && imgContainer.image.width > 0) ||
|
||||||
(fittedOnce && ((width > 1 && previousWidth != width) || (height > 1 && previousHeight != height)))) {
|
// (fittedOnce && ((width > 1 && previousWidth != width) || (height > 1 && previousHeight != height)))) {
|
||||||
var ret = fit()
|
// var ret = fit()
|
||||||
if (!ret)
|
// if (!ret)
|
||||||
return
|
// return
|
||||||
fittedOnce = true
|
// fittedOnce = true
|
||||||
previousWidth = width
|
// previousWidth = width
|
||||||
previousHeight = height
|
// previousHeight = height
|
||||||
if (orientationTag != undefined)
|
// if (orientationTag != undefined)
|
||||||
previousOrientationTag = orientationTag
|
// previousOrientationTag = orientationTag
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
onOrientationTagChanged: {
|
// onOrientationTagChanged: {
|
||||||
/* For images of the same width and height but with different orientations, the auto-fit
|
// /* For images of the same width and height but with different orientations, the auto-fit
|
||||||
* will not be triggered by the "widthChanged()" signal, so it needs to be triggered upon
|
// * will not be triggered by the "widthChanged()" signal, so it needs to be triggered upon
|
||||||
* either a change in the image's size or in its orientation. */
|
// * either a change in the image's size or in its orientation. */
|
||||||
if (orientationTag != undefined && previousOrientationTag != orientationTag) {
|
// if (orientationTag != undefined && previousOrientationTag != orientationTag) {
|
||||||
var ret = fit()
|
// var ret = fit()
|
||||||
if (!ret)
|
// if (!ret)
|
||||||
return
|
// return
|
||||||
fittedOnce = true
|
// fittedOnce = true
|
||||||
previousWidth = width
|
// previousWidth = width
|
||||||
previousHeight = height
|
// previousHeight = height
|
||||||
previousOrientationTag = orientationTag
|
// previousOrientationTag = orientationTag
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
onActiveChanged: {
|
// onActiveChanged: {
|
||||||
if (active) {
|
// if (active) {
|
||||||
/* Instantiate and initialize a PhongImageViewer component dynamically using Loader.setSource
|
// /* Instantiate and initialize a PhongImageViewer component dynamically using Loader.setSource
|
||||||
* Note: It does not work to use previously created component, so we re-create it with setSource. */
|
// * Note: It does not work to use previously created component, so we re-create it with setSource. */
|
||||||
setSource("PhongImageViewer.qml", {
|
// setSource("PhongImageViewer.qml", {
|
||||||
'sourcePath': Qt.binding(function() { return sourcePath }),
|
// 'sourcePath': Qt.binding(function() { return sourcePath }),
|
||||||
'normalPath': Qt.binding(function() { return normalPath }),
|
// 'normalPath': Qt.binding(function() { return normalPath }),
|
||||||
'gamma': Qt.binding(function() { return hdrImageToolbar.gammaValue }),
|
// 'gamma': Qt.binding(function() { return hdrImageToolbar.gammaValue }),
|
||||||
'gain': Qt.binding(function() { return hdrImageToolbar.gainValue }),
|
// 'gain': Qt.binding(function() { return hdrImageToolbar.gainValue }),
|
||||||
'channelModeString': Qt.binding(function() { return hdrImageToolbar.channelModeValue }),
|
// 'channelModeString': Qt.binding(function() { return hdrImageToolbar.channelModeValue }),
|
||||||
'baseColor': Qt.binding(function() { return phongImageViewerToolbar.baseColorValue }),
|
// 'baseColor': Qt.binding(function() { return phongImageViewerToolbar.baseColorValue }),
|
||||||
'textureOpacity': Qt.binding(function() { return phongImageViewerToolbar.textureOpacityValue }),
|
// 'textureOpacity': Qt.binding(function() { return phongImageViewerToolbar.textureOpacityValue }),
|
||||||
'ka': Qt.binding(function() { return phongImageViewerToolbar.kaValue }),
|
// 'ka': Qt.binding(function() { return phongImageViewerToolbar.kaValue }),
|
||||||
'kd': Qt.binding(function() { return phongImageViewerToolbar.kdValue }),
|
// 'kd': Qt.binding(function() { return phongImageViewerToolbar.kdValue }),
|
||||||
'ks': Qt.binding(function() { return phongImageViewerToolbar.ksValue }),
|
// 'ks': Qt.binding(function() { return phongImageViewerToolbar.ksValue }),
|
||||||
'shininess': Qt.binding(function() { return phongImageViewerToolbar.shininessValue }),
|
// 'shininess': Qt.binding(function() { return phongImageViewerToolbar.shininessValue }),
|
||||||
'lightYaw': Qt.binding(function() { return -directionalLightPane.lightYawValue }), // left handed coordinate system
|
// 'lightYaw': Qt.binding(function() { return -directionalLightPane.lightYawValue }), // left handed coordinate system
|
||||||
'lightPitch': Qt.binding(function() { return directionalLightPane.lightPitchValue }),
|
// 'lightPitch': Qt.binding(function() { return directionalLightPane.lightPitchValue }),
|
||||||
})
|
// })
|
||||||
} else {
|
// } else {
|
||||||
// Forcing the unload (instead of using Component.onCompleted to load it once and for all) is necessary since Qt 5.14
|
// // Forcing the unload (instead of using Component.onCompleted to load it once and for all) is necessary since Qt 5.14
|
||||||
setSource("", {})
|
// setSource("", {})
|
||||||
fittedOnce = false
|
// fittedOnce = false
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Simple QML Image Viewer (using Qt or qtAliceVisionImageIO to load images)
|
// // Simple QML Image Viewer (using Qt or qtAliceVisionImageIO to load images)
|
||||||
ExifOrientedViewer {
|
// ExifOrientedViewer {
|
||||||
id: qtImageViewerLoader
|
// id: qtImageViewerLoader
|
||||||
active: !floatImageViewerLoader.active && !panoramaViewerLoader.active && !phongImageViewerLoader.active
|
// active: !floatImageViewerLoader.active && !panoramaViewerLoader.active && !phongImageViewerLoader.active
|
||||||
anchors.centerIn: parent
|
// anchors.centerIn: parent
|
||||||
orientationTag: imgContainer.orientationTag
|
// orientationTag: imgContainer.orientationTag
|
||||||
xOrigin: imgContainer.width / 2
|
// xOrigin: imgContainer.width / 2
|
||||||
yOrigin: imgContainer.height / 2
|
// yOrigin: imgContainer.height / 2
|
||||||
sourceComponent: Image {
|
// sourceComponent: Image {
|
||||||
id: qtImageViewer
|
// id: qtImageViewer
|
||||||
asynchronous: true
|
// asynchronous: true
|
||||||
smooth: false
|
// smooth: false
|
||||||
fillMode: Image.PreserveAspectFit
|
// fillMode: Image.PreserveAspectFit
|
||||||
onWidthChanged: if (status==Image.Ready) fit()
|
// onWidthChanged: if (status==Image.Ready) fit()
|
||||||
source: getImageFile()
|
// source: myImageFile
|
||||||
onStatusChanged: {
|
// onStatusChanged: {
|
||||||
// Update cache source when image is loaded
|
// // Update cache source when image is loaded
|
||||||
imageStatus = status
|
// imageStatus = status
|
||||||
if (status === Image.Ready)
|
// if (status === Image.Ready)
|
||||||
qtImageViewerCache.source = source
|
// qtImageViewerCache.source = source
|
||||||
}
|
// }
|
||||||
|
|
||||||
property var imageStatus: Image.Ready
|
// property var imageStatus: Image.Ready
|
||||||
|
|
||||||
// Image cache of the last loaded image
|
// // Image cache of the last loaded image
|
||||||
// Only visible when the main one is loading, to maintain a displayed image for smoother transitions
|
// // Only visible when the main one is loading, to maintain a displayed image for smoother transitions
|
||||||
Image {
|
// Image {
|
||||||
id: qtImageViewerCache
|
// id: qtImageViewerCache
|
||||||
|
|
||||||
anchors.fill: parent
|
// anchors.fill: parent
|
||||||
asynchronous: true
|
// asynchronous: true
|
||||||
smooth: parent.smooth
|
// smooth: parent.smooth
|
||||||
fillMode: parent.fillMode
|
// fillMode: parent.fillMode
|
||||||
|
|
||||||
visible: qtImageViewer.status === Image.Loading
|
// visible: qtImageViewer.status === Image.Loading
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
property var image: {
|
property var image: {
|
||||||
if (floatImageViewerLoader.active)
|
// if (floatImageViewerLoader.active)
|
||||||
floatImageViewerLoader.item
|
floatImageViewerLoader.item
|
||||||
else if (panoramaViewerLoader.active)
|
// else if (panoramaViewerLoader.active)
|
||||||
panoramaViewerLoader.item
|
// panoramaViewerLoader.item
|
||||||
else if (phongImageViewerLoader.active)
|
// else if (phongImageViewerLoader.active)
|
||||||
phongImageViewerLoader.item
|
// phongImageViewerLoader.item
|
||||||
else
|
// else
|
||||||
qtImageViewerLoader.item
|
// qtImageViewerLoader.item
|
||||||
}
|
}
|
||||||
width: image ? (image.width > 0 ? image.width : 1) : 1
|
width: image ? (image.width > 0 ? image.width : 1) : 1
|
||||||
height: image ? (image.height > 0 ? image.height : 1) : 1
|
height: image ? (image.height > 0 ? image.height : 1) : 1
|
||||||
|
@ -977,7 +988,7 @@ FocusScope {
|
||||||
font.pointSize: 8
|
font.pointSize: 8
|
||||||
readOnly: true
|
readOnly: true
|
||||||
selectByMouse: true
|
selectByMouse: true
|
||||||
text: (phongImageViewerLoader.active) ? Filepath.urlToString(phongImageViewerLoader.sourcePath) : Filepath.urlToString(getImageFile())
|
// text: (phongImageViewerLoader.active) ? Filepath.urlToString(phongImageViewerLoader.sourcePath) : Filepath.urlToString(myImageFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write which node is being displayed
|
// Write which node is being displayed
|
||||||
|
@ -1301,26 +1312,26 @@ FocusScope {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PhongImageViewerToolbar {
|
// PhongImageViewerToolbar {
|
||||||
id: phongImageViewerToolbar
|
// id: phongImageViewerToolbar
|
||||||
|
|
||||||
anchors {
|
// anchors {
|
||||||
bottom: parent.bottom
|
// bottom: parent.bottom
|
||||||
left: parent.left
|
// left: parent.left
|
||||||
margins: 2
|
// margins: 2
|
||||||
}
|
// }
|
||||||
visible: root.aliceVisionPluginAvailable && phongImageViewerLoader.active
|
// visible: root.aliceVisionPluginAvailable && phongImageViewerLoader.active
|
||||||
}
|
// }
|
||||||
|
|
||||||
DirectionalLightPane {
|
// DirectionalLightPane {
|
||||||
id: directionalLightPane
|
// id: directionalLightPane
|
||||||
anchors {
|
// anchors {
|
||||||
bottom: parent.bottom
|
// bottom: parent.bottom
|
||||||
right: parent.right
|
// right: parent.right
|
||||||
margins: 2
|
// margins: 2
|
||||||
}
|
// }
|
||||||
visible: root.aliceVisionPluginAvailable && phongImageViewerLoader.active && phongImageViewerToolbar.displayLightController
|
// visible: root.aliceVisionPluginAvailable && phongImageViewerLoader.active && phongImageViewerToolbar.displayLightController
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
FloatingPane {
|
FloatingPane {
|
||||||
|
@ -1601,7 +1612,7 @@ FocusScope {
|
||||||
Layout.preferredWidth: model.reduce((acc, label) => Math.max(acc, fontMetrics.boundingRect(label).width), 0) + 3.0 * Qt.application.font.pixelSize
|
Layout.preferredWidth: model.reduce((acc, label) => Math.max(acc, fontMetrics.boundingRect(label).width), 0) + 3.0 * Qt.application.font.pixelSize
|
||||||
|
|
||||||
onNameChanged: {
|
onNameChanged: {
|
||||||
root.source = getImageFile()
|
root.source = myImageFile
|
||||||
root.sequence = getSequence()
|
root.sequence = getSequence()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1731,8 +1742,8 @@ FocusScope {
|
||||||
visible: running
|
visible: running
|
||||||
|
|
||||||
onVisibleChanged: {
|
onVisibleChanged: {
|
||||||
if (panoramaViewerLoader.active)
|
// if (panoramaViewerLoader.active)
|
||||||
fit()
|
// fit()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -104,9 +104,14 @@ SfmDataEntity {
|
||||||
},
|
},
|
||||||
PhongMaterial{
|
PhongMaterial{
|
||||||
id: mat
|
id: mat
|
||||||
ambient: _reconstruction && (viewId === _reconstruction.selectedViewId ||
|
ambient: {
|
||||||
(viewId === _reconstruction.pickedViewId && syncPickedViewId)) ?
|
if(!_reconstruction)
|
||||||
activePalette.highlight : customColor // "#CCC"
|
return customColor
|
||||||
|
if((syncPickedViewId && viewId === _reconstruction.pickedViewId) ||
|
||||||
|
(viewId === _reconstruction.selectedViewId))
|
||||||
|
return activePalette.highlight
|
||||||
|
return customColor // "#CCC"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -461,6 +461,8 @@ class Reconstruction(UIGraph):
|
||||||
self._cameraInit = None # current CameraInit node
|
self._cameraInit = None # current CameraInit node
|
||||||
self._cameraInits = QObjectListModel(parent=self) # all CameraInit nodes
|
self._cameraInits = QObjectListModel(parent=self) # all CameraInit nodes
|
||||||
self._buildingIntrinsics = False
|
self._buildingIntrinsics = False
|
||||||
|
self._mapViewIdToIndex = {}
|
||||||
|
self._mapViewIdToPath = {}
|
||||||
self.intrinsicsBuilt.connect(self.onIntrinsicsAvailable)
|
self.intrinsicsBuilt.connect(self.onIntrinsicsAvailable)
|
||||||
|
|
||||||
self.cameraInitChanged.connect(self.onCameraInitChanged)
|
self.cameraInitChanged.connect(self.onCameraInitChanged)
|
||||||
|
@ -521,10 +523,39 @@ class Reconstruction(UIGraph):
|
||||||
def onCameraInitChanged(self):
|
def onCameraInitChanged(self):
|
||||||
if self._cameraInit is None:
|
if self._cameraInit is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# Keep a mapping between viewId and viewpoint index in the active CameraInit
|
||||||
|
# print("Update mapViewIdToIndex: before len=" + str(len(self._mapViewIdToIndex)))
|
||||||
|
self._mapViewIdToIndex = {}
|
||||||
|
self._mapViewIdToPath = {}
|
||||||
|
for index, viewpoint in enumerate(self.viewpoints):
|
||||||
|
viewId = viewpoint.childAttribute("viewId").value
|
||||||
|
|
||||||
|
# print(f"index: {index}, viewId: {viewId}, type viewId: {type(viewId)}")
|
||||||
|
self._mapViewIdToIndex[viewId] = index
|
||||||
|
self._mapViewIdToPath[viewId] = viewpoint.childAttribute("path").value
|
||||||
|
# print("Update mapViewIdToIndex: after len=" + str(len(self._mapViewIdToIndex)))
|
||||||
|
|
||||||
# Update active nodes when CameraInit changes
|
# Update active nodes when CameraInit changes
|
||||||
nodes = self._graph.dfsOnDiscover(startNodes=[self._cameraInit], reverse=True)[0]
|
nodes = self._graph.dfsOnDiscover(startNodes=[self._cameraInit], reverse=True)[0]
|
||||||
self.setActiveNodes(nodes)
|
self.setActiveNodes(nodes)
|
||||||
|
|
||||||
|
@Slot(str, result=int)
|
||||||
|
def viewIdToIndex(self, viewIdStr):
|
||||||
|
if not viewIdStr:
|
||||||
|
return -1
|
||||||
|
index = self._mapViewIdToIndex.get(int(viewIdStr), -1)
|
||||||
|
# print("Reconstruction.viewIdToIndex: " + str(type(viewId)))
|
||||||
|
# print("Reconstruction.viewIdToIndex: " + viewId + " => " + str(index))
|
||||||
|
return index
|
||||||
|
|
||||||
|
@Slot(str, result=str)
|
||||||
|
def viewIdToPath(self, viewIdStr):
|
||||||
|
if not viewIdStr:
|
||||||
|
return ""
|
||||||
|
path = self._mapViewIdToPath.get(int(viewIdStr), "")
|
||||||
|
return path
|
||||||
|
|
||||||
@Slot()
|
@Slot()
|
||||||
@Slot(str)
|
@Slot(str)
|
||||||
def new(self, pipeline=None):
|
def new(self, pipeline=None):
|
||||||
|
|
Loading…
Add table
Reference in a new issue