///////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2017 Statoil ASA // // ResInsight is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. // // See the GNU General Public License at // for more details. // ///////////////////////////////////////////////////////////////////////////////// #include "RimViewManipulator.h" #include "RigMainGrid.h" #include "Rim3dView.h" #include "RimCase.h" #include "RimEclipseView.h" #include "RiuViewer.h" #include "cvfBoundingBox.h" #include "cvfCamera.h" #include "cvfMatrix4.h" #include "cvfScene.h" //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RimViewManipulator::applySourceViewCameraOnDestinationViews( Rim3dView* sourceView, const std::vector& destinationViews ) { bool setPointOfInterest = false; cvf::Vec3d sourceCamUp; cvf::Vec3d sourceCamEye; cvf::Vec3d sourceCamViewRefPoint; cvf::Vec3d sourcePointOfInterest; sourceView->viewer()->mainCamera()->toLookAt( &sourceCamEye, &sourceCamViewRefPoint, &sourceCamUp ); cvf::Vec3d sourceCamGlobalEye = sourceCamEye; cvf::Vec3d sourceCamGlobalViewRefPoint = sourceCamViewRefPoint; if ( sourceView->viewer()->getNavigationPolicy() != nullptr ) { setPointOfInterest = true; sourcePointOfInterest = sourceView->viewer()->pointOfInterest(); } // Source bounding box in global coordinates including scaleZ cvf::BoundingBox sourceSceneBB; { if ( sourceView->viewer()->currentScene() ) { sourceSceneBB = sourceView->viewer()->currentScene()->boundingBox(); } cvf::Vec3d offset = cvf::Vec3d::ZERO; RimCase* sourceOwnerCase = sourceView->ownerCase(); if ( sourceOwnerCase ) { offset = sourceOwnerCase->displayModelOffset(); offset.z() *= sourceView->scaleZ(); } sourceCamGlobalEye += offset; sourceCamGlobalViewRefPoint += offset; if ( setPointOfInterest ) sourcePointOfInterest += offset; cvf::Mat4d trans; trans.setTranslation( offset ); sourceSceneBB.transform( trans ); } for ( auto destinationView : destinationViews ) { if ( !destinationView ) continue; destinationView->isPerspectiveView = sourceView->isPerspectiveView; RiuViewer* destinationViewer = destinationView->viewer(); if ( destinationViewer ) { destinationViewer->enableParallelProjection( !sourceView->isPerspectiveView ); // Destination bounding box in global coordinates including scaleZ cvf::BoundingBox destSceneBB; if ( destinationViewer->currentScene() ) { destSceneBB = destinationViewer->currentScene()->boundingBox(); } cvf::Vec3d destinationCamEye = sourceCamGlobalEye; cvf::Vec3d destinationCamViewRefPoint = sourceCamGlobalViewRefPoint; cvf::Vec3d offset = cvf::Vec3d::ZERO; RimCase* destinationOwnerCase = destinationView->ownerCase(); if ( destinationOwnerCase ) { offset = destinationOwnerCase->displayModelOffset(); offset.z() *= destinationView->scaleZ(); } destinationCamEye -= offset; destinationCamViewRefPoint -= offset; cvf::Mat4d trans; trans.setTranslation( offset ); destSceneBB.transform( trans ); if ( isBoundingBoxesOverlappingOrClose( sourceSceneBB, destSceneBB ) ) { destinationViewer->mainCamera()->setFromLookAt( destinationCamEye, destinationCamViewRefPoint, sourceCamUp ); } else { // Fallback using values from source camera destinationViewer->mainCamera()->setFromLookAt( sourceCamEye, sourceCamViewRefPoint, sourceCamUp ); } if ( setPointOfInterest ) { cvf::Vec3d pointOfInterest = sourcePointOfInterest; pointOfInterest -= offset; destinationViewer->updateParallelProjectionHeightFromMoveZoom( pointOfInterest ); destinationViewer->updateParallelProjectionCameraPosFromPointOfInterestMove( pointOfInterest ); } destinationViewer->update(); } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- cvf::Vec3d RimViewManipulator::calculateEquivalentCamPosOffset( Rim3dView* sourceView, Rim3dView* destView ) { cvf::Vec3d soffset = cvf::Vec3d::ZERO; RimCase* sourceOwnerCase = sourceView->ownerCase(); if ( sourceOwnerCase ) { soffset = sourceOwnerCase->displayModelOffset(); soffset.z() *= sourceView->scaleZ(); } cvf::Vec3d doffset = cvf::Vec3d::ZERO; RimCase* destinationOwnerCase = destView->ownerCase(); if ( destinationOwnerCase ) { doffset = destinationOwnerCase->displayModelOffset(); doffset.z() *= sourceView->scaleZ(); } return soffset - doffset; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RimViewManipulator::isBoundingBoxesOverlappingOrClose( const cvf::BoundingBox& sourceBB, const cvf::BoundingBox& destBB ) { if ( !sourceBB.isValid() || !destBB.isValid() ) return false; if ( sourceBB.intersects( destBB ) ) return true; double largestExtent = sourceBB.extent().length(); if ( destBB.extent().length() > largestExtent ) { largestExtent = destBB.extent().length(); } double centerDist = ( sourceBB.center() - destBB.center() ).length(); return centerDist < largestExtent * 5; }