mirror of
https://github.com/alicevision/Meshroom.git
synced 2025-05-31 18:06:31 +02:00
[Panorama Viewer] change pitch and yaw from SfMTransform Node
This commit is contained in:
parent
733362fe1d
commit
2e1c80b879
3 changed files with 303 additions and 12 deletions
|
@ -62,7 +62,9 @@ AliceVision.FloatImageViewer {
|
|||
property string sfmPath: ""
|
||||
|
||||
function updateSfmPath() {
|
||||
var activeNode = _reconstruction.activeNodes.get('sfm').node;
|
||||
console.warn("SFM UPDATE - Float IV")
|
||||
|
||||
var activeNode = _reconstruction.activeNodes.get('SfMTransform').node;
|
||||
|
||||
if(!activeNode)
|
||||
{
|
||||
|
@ -70,7 +72,7 @@ AliceVision.FloatImageViewer {
|
|||
}
|
||||
else
|
||||
{
|
||||
root.sfmPath = activeNode.attribute("outputViewsAndPoses").value;
|
||||
root.sfmPath = activeNode.attribute("input").value;
|
||||
}
|
||||
root.setSfmPath(sfmPath);
|
||||
}
|
||||
|
@ -81,8 +83,12 @@ AliceVision.FloatImageViewer {
|
|||
ppRect.y = pp.y;
|
||||
}
|
||||
|
||||
function rotatePanorama(dx, dy) {
|
||||
root.setRotationPano(dx, dy);
|
||||
function rotatePanoDegrees(yaw, pitch) {
|
||||
root.rotatePanoramaDegrees(yaw, pitch);
|
||||
}
|
||||
|
||||
function rotatePanoRadians(yaw, pitch) {
|
||||
root.rotatePanoramaRadians(yaw, pitch);
|
||||
}
|
||||
|
||||
function updateMouseAreaPano() {
|
||||
|
|
|
@ -60,6 +60,28 @@ AliceVision.PanoramaViewer {
|
|||
property int yaw: 0;
|
||||
property int pitch: 0;
|
||||
|
||||
// Yaw and Pitch in Degrees from SfMTransform sliders
|
||||
property int yawNode: _reconstruction.activeNodes.get('SfMTransform').node.attribute("manualTransform.manualRotation.y").value;
|
||||
property int pitchNode: _reconstruction.activeNodes.get('SfMTransform').node.attribute("manualTransform.manualRotation.x").value;
|
||||
|
||||
|
||||
onYawNodeChanged: {
|
||||
if (!isRotating) {
|
||||
for (var i = 0; i < repeater.model; i++) {
|
||||
repeater.itemAt(i).item.rotatePanoramaDegrees(yawNode, pitchNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onPitchNodeChanged: {
|
||||
if (!isRotating) {
|
||||
for (var i = 0; i < repeater.model; i++) {
|
||||
repeater.itemAt(i).item.rotatePanoDegrees(yawNode, pitchNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Item {
|
||||
id: containerPanorama
|
||||
z: 10
|
||||
|
@ -90,8 +112,7 @@ AliceVision.PanoramaViewer {
|
|||
lastX = mouse.x;
|
||||
lastY = mouse.y;
|
||||
for (var i = 0; i < repeater.model; i++) {
|
||||
//repeater.itemAt(i).item.rotatePanorama((xoffset / width) * mouseMultiplier, -(yoffset / height) * mouseMultiplier)
|
||||
repeater.itemAt(i).item.rotatePanorama(0, -(yoffset / height) * mouseMultiplier)
|
||||
repeater.itemAt(i).item.rotatePanoRadians((xoffset / width) * mouseMultiplier, -(yoffset / height) * mouseMultiplier);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -106,7 +127,7 @@ AliceVision.PanoramaViewer {
|
|||
if (isRotating)
|
||||
{
|
||||
// Update Euler angles
|
||||
var activeNode = _reconstruction.activeNodes.get('sfm').node;
|
||||
var activeNode = _reconstruction.activeNodes.get('SfMTransform').node;
|
||||
|
||||
root.yaw = repeater.itemAt(0).item.getYaw();
|
||||
root.pitch = repeater.itemAt(0).item.getPitch();
|
||||
|
@ -152,12 +173,11 @@ AliceVision.PanoramaViewer {
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
property string sfmPath: ""
|
||||
|
||||
function updateSfmPath() {
|
||||
var activeNode = _reconstruction.activeNodes.get('sfm').node;
|
||||
console.warn("SFM UPDATE - PANO")
|
||||
var activeNode = _reconstruction.activeNodes.get('SfMTransform').node;
|
||||
|
||||
if(!activeNode)
|
||||
{
|
||||
|
@ -165,7 +185,7 @@ AliceVision.PanoramaViewer {
|
|||
}
|
||||
else
|
||||
{
|
||||
root.sfmPath = activeNode.attribute("outputViewsAndPoses").value;
|
||||
root.sfmPath = activeNode.attribute("input").value;
|
||||
}
|
||||
root.setSfmPath(sfmPath);
|
||||
}
|
||||
|
@ -196,7 +216,6 @@ AliceVision.PanoramaViewer {
|
|||
'index' : index,
|
||||
'idView': Qt.binding(function() { return cId; }),
|
||||
})
|
||||
//repeater.itemAt(index).item.rotatePanorama(yaw * (3.14 / 180), pitch * (3.14 / 180))
|
||||
|
||||
} else {
|
||||
// Force the unload (instead of using Component.onCompleted to load it once and for all) is necessary since Qt 5.14
|
||||
|
|
266
meshroom/ui/qml/Viewer/PanoramaViewer.qml.autosave
Normal file
266
meshroom/ui/qml/Viewer/PanoramaViewer.qml.autosave
Normal file
|
@ -0,0 +1,266 @@
|
|||
import QtQuick 2.11
|
||||
import Utils 1.0
|
||||
|
||||
import AliceVision 1.0 as AliceVision
|
||||
|
||||
/**
|
||||
* FloatImage displays an Image with gamma / offset / channel controls
|
||||
* Requires QtAliceVision plugin.
|
||||
*/
|
||||
|
||||
AliceVision.PanoramaViewer {
|
||||
id: root
|
||||
|
||||
width: 3000
|
||||
height: 1500
|
||||
visible: (status === Image.Ready)
|
||||
|
||||
// paintedWidth / paintedHeight / status for compatibility with standard Image
|
||||
property int paintedWidth: textureSize.width
|
||||
property int paintedHeight: textureSize.height
|
||||
property var status: Image.Null
|
||||
|
||||
property int downscaleValue: 2
|
||||
|
||||
property int subdivisionsPano: 12
|
||||
|
||||
property bool isEditable: true
|
||||
property bool isHighlightable: true
|
||||
|
||||
property bool displayGridPano: true
|
||||
|
||||
property int mouseMultiplier: 1
|
||||
|
||||
onIsHighlightableChanged:{
|
||||
for (var i = 0; i < repeater.model; i++) {
|
||||
repeater.itemAt(i).item.onChangedHighlightState(isHighlightable);
|
||||
}
|
||||
}
|
||||
|
||||
onSubdivisionsPanoChanged:{
|
||||
for (var i = 0; i < repeater.model; i++) {
|
||||
repeater.itemAt(i).item.updateSubdivisions(subdivisionsPano);
|
||||
}
|
||||
}
|
||||
|
||||
onDownscaleValueChanged: {
|
||||
for (var i = 0; i < repeater.model; i++) {
|
||||
repeater.itemAt(i).item.setDownscale(downscaleValue);
|
||||
}
|
||||
}
|
||||
|
||||
clearBeforeLoad: true
|
||||
|
||||
property alias containsMouse: mouseAreaPano.containsMouse
|
||||
|
||||
property bool isRotating: false
|
||||
property var lastX : 0
|
||||
property var lastY: 0
|
||||
|
||||
property int yaw: 0;
|
||||
property int pitch: 0;
|
||||
|
||||
// Yaw and Pitch in Degrees from SfMTransform sliders
|
||||
property int yawNode: _reconstruction.activeNodes.get('SfMTransform').node.attribute("manualTransform.manualRotation.y").value;
|
||||
property int pitchNode: _reconstruction.activeNodes.get('SfMTransform').node.attribute("manualTransform.manualRotation.x").value;
|
||||
|
||||
|
||||
onYawNodeChanged: {
|
||||
if (!isRotating) {
|
||||
for (var i = 0; i < repeater.model; i++) {
|
||||
repeater.itemAt(i).item.rotatePanoramaDegrees(yawNode, pitchNod);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onPitchNodeChanged: {
|
||||
if (!isRotating) {
|
||||
for (var i = 0; i < repeater.model; i++) {
|
||||
repeater.itemAt(i).item.rotatePanoDegrees(yawNode, pitchNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Item {
|
||||
id: containerPanorama
|
||||
z: 10
|
||||
Rectangle {
|
||||
width: 3000
|
||||
height: 1500
|
||||
//color: mouseAreaPano.containsMouse? "red" : "green"
|
||||
color: "transparent"
|
||||
MouseArea {
|
||||
id: mouseAreaPano
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: {
|
||||
if (isEditable)
|
||||
isRotating ? Qt.ClosedHandCursor : Qt.OpenHandCursor
|
||||
}
|
||||
onPositionChanged: {
|
||||
// Send Mouse Coordinates to Float Images Viewers
|
||||
for (var i = 0; i < repeater.model && isHighlightable; i++) {
|
||||
var highlight = repeater.itemAt(i).item.getMouseCoordinates(mouse.x, mouse.y);
|
||||
repeater.itemAt(i).z = highlight ? 2 : 0
|
||||
}
|
||||
|
||||
// Rotate Panorama
|
||||
if (isRotating && isEditable) {
|
||||
var xoffset = mouse.x - lastX;
|
||||
var yoffset = mouse.y - lastY;
|
||||
lastX = mouse.x;
|
||||
lastY = mouse.y;
|
||||
for (var i = 0; i < repeater.model; i++) {
|
||||
repeater.itemAt(i).item.rotatePanoRadians((xoffset / width) * mouseMultiplier, -(yoffset / height) * mouseMultiplier);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onPressed:{
|
||||
isRotating = true;
|
||||
lastX = mouse.x;
|
||||
lastY = mouse.y;
|
||||
}
|
||||
|
||||
onReleased: {
|
||||
if (isRotating)
|
||||
{
|
||||
// Update Euler angles
|
||||
var activeNode = _reconstruction.activeNodes.get('SfMTransform').node;
|
||||
|
||||
root.yaw = repeater.itemAt(0).item.getYaw();
|
||||
root.pitch = repeater.itemAt(0).item.getPitch();
|
||||
|
||||
activeNode.attribute("manualTransform.manualRotation.y").value = root.yaw;
|
||||
activeNode.attribute("manualTransform.manualRotation.x").value = root.pitch;
|
||||
}
|
||||
|
||||
isRotating = false;
|
||||
lastX = 0
|
||||
lastY = 0
|
||||
}
|
||||
}
|
||||
|
||||
// Grid Panorama Viewer
|
||||
Canvas {
|
||||
id: gridPano
|
||||
visible: displayGridPano
|
||||
anchors.fill : parent
|
||||
property int wgrid: 40
|
||||
onPaint: {
|
||||
var ctx = getContext("2d")
|
||||
ctx.lineWidth = 1.0
|
||||
ctx.shadowBlur = 0
|
||||
ctx.strokeStyle = "grey"
|
||||
var nrows = height/wgrid;
|
||||
for(var i=0; i < nrows+1; i++){
|
||||
ctx.moveTo(0, wgrid*i);
|
||||
ctx.lineTo(width, wgrid*i);
|
||||
}
|
||||
|
||||
var ncols = width/wgrid
|
||||
for(var j=0; j < ncols+1; j++){
|
||||
ctx.moveTo(wgrid*j, 0);
|
||||
ctx.lineTo(wgrid*j, height);
|
||||
}
|
||||
|
||||
ctx.closePath()
|
||||
ctx.stroke()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
property string sfmPath: ""
|
||||
|
||||
function updateSfmPath() {
|
||||
console.warn("SFM UPDATE - PANO")
|
||||
var activeNode = _reconstruction.activeNodes.get('SfMTransform').node;
|
||||
|
||||
if(!activeNode)
|
||||
{
|
||||
root.sfmPath = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
root.sfmPath = activeNode.attribute("input").value;
|
||||
}
|
||||
root.setSfmPath(sfmPath);
|
||||
}
|
||||
|
||||
property var pathList : []
|
||||
property var idList : []
|
||||
|
||||
Item {
|
||||
id: panoImages
|
||||
width: root.width
|
||||
height: root.height
|
||||
|
||||
Component {
|
||||
id: imgPano
|
||||
Loader {
|
||||
id: floatOneLoader
|
||||
active: root.status
|
||||
visible: (floatOneLoader.status === Loader.Ready)
|
||||
z:0
|
||||
//anchors.centerIn: parent
|
||||
property string cSource: Filepath.stringToUrl(root.pathList[index].toString())
|
||||
property int cId: root.idList[index]
|
||||
onActiveChanged: {
|
||||
if(active) {
|
||||
setSource("FloatImage.qml", {
|
||||
'isPanoViewer' : true,
|
||||
'source': Qt.binding(function() { return cSource; }),
|
||||
'index' : index,
|
||||
'idView': Qt.binding(function() { return cId; }),
|
||||
})
|
||||
|
||||
} else {
|
||||
// Force the unload (instead of using Component.onCompleted to load it once and for all) is necessary since Qt 5.14
|
||||
setSource("", {})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Repeater {
|
||||
id: repeater
|
||||
model: 0
|
||||
delegate: imgPano
|
||||
|
||||
}
|
||||
Connections {
|
||||
target: root
|
||||
onImagesDataChanged: {
|
||||
//We receive the map<ImgPath, idView> from C++
|
||||
//Resetting arrays to avoid problem with push
|
||||
pathList = []
|
||||
idList = []
|
||||
|
||||
//Iterating through the map
|
||||
for (var path in imagesData) {
|
||||
console.warn("Object item:", path, "=", imagesData[path])
|
||||
root.pathList.push(path)
|
||||
root.idList.push(imagesData[path])
|
||||
}
|
||||
console.warn(root.pathList.length)
|
||||
|
||||
//Changing the repeater model (number of elements)
|
||||
panoImages.updateRepeater()
|
||||
|
||||
root.status = Image.Ready;
|
||||
}
|
||||
}
|
||||
|
||||
function updateRepeater() {
|
||||
if(repeater.model !== root.pathList.length){
|
||||
repeater.model = 0;
|
||||
}
|
||||
repeater.model = root.pathList.length;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue