| 430 | } |
| 431 | |
| 432 | void Viewport::preciseFitToScreenBorder_( std::function<Box3f( bool zoomFOV, bool globalBasis )> getBoxFn, const BaseFitParams& fitParams ) |
| 433 | { |
| 434 | if ( fitParams.snapView ) |
| 435 | params_.cameraTrackballAngle = getClosestCanonicalQuaternion( params_.cameraTrackballAngle ); |
| 436 | |
| 437 | const auto safeZoom = params_.cameraZoom; |
| 438 | params_.cameraZoom = 1; |
| 439 | |
| 440 | Box3f sceneObjsBox = getBoxFn( false, false ); |
| 441 | Box3f unitedBox; |
| 442 | if ( getViewerInstance().globalBasis && getViewerInstance().globalBasis->isVisible( id ) ) |
| 443 | unitedBox = getBoxFn( false, true ); // calculate box of global basis separately, not to interfere with actual scene size |
| 444 | unitedBox.include( sceneObjsBox ); |
| 445 | |
| 446 | if ( !unitedBox.valid() ) |
| 447 | { |
| 448 | params_.cameraZoom = safeZoom; |
| 449 | setRotationPivot_( params_.staticRotationPivot ? *params_.staticRotationPivot : Vector3f() ); |
| 450 | return; |
| 451 | } |
| 452 | |
| 453 | if ( params_.orthographic ) |
| 454 | { |
| 455 | sceneBox_ = transformed( unitedBox, getViewXf_().inverse() ); |
| 456 | } |
| 457 | else |
| 458 | { |
| 459 | sceneBox_ = unitedBox; |
| 460 | } |
| 461 | Vector3f sceneCenter = params_.orthographic ? |
| 462 | getViewXf_().inverse()( unitedBox.center() ) : unitedBox.center(); |
| 463 | setRotationPivot_( params_.staticRotationPivot ? *params_.staticRotationPivot : sceneCenter ); |
| 464 | |
| 465 | params_.cameraTranslation = -sceneCenter; |
| 466 | params_.cameraViewAngle = 45.0f; |
| 467 | params_.objectScale = sceneObjsBox.valid() ? sceneObjsBox.diagonal() : 1.0f; // we should not take global basis into account here |
| 468 | if ( params_.objectScale == 0.0f ) |
| 469 | params_.objectScale = 1.0f; |
| 470 | |
| 471 | auto unitedSceneScale = unitedBox.diagonal(); |
| 472 | |
| 473 | if ( params_.orthographic ) |
| 474 | { |
| 475 | auto factor = 1.f / ( cameraEye - cameraCenter ).length(); |
| 476 | auto tanFOV = tan( 0.5f * params_.cameraViewAngle / 180.f * PI_F ); |
| 477 | params_.cameraZoom = factor / ( unitedSceneScale * tanFOV ); |
| 478 | |
| 479 | const auto winRatio = getRatio(); |
| 480 | auto dX = ( unitedBox.max.x - unitedBox.min.x ) / 2.f / winRatio; |
| 481 | auto dY = ( unitedBox.max.y - unitedBox.min.y ) / 2.f; |
| 482 | float maxD = std::max( dX, dY ); |
| 483 | |
| 484 | if ( maxD == 0.0f ) |
| 485 | maxD = 1.0f; |
| 486 | |
| 487 | params_.cameraViewAngle = ( 2.f * atan2( maxD * params_.cameraZoom, params_.cameraDnear ) ) / PI_F * 180.f / fitParams.factor; |
| 488 | } |
| 489 | else |
nothing calls this directly
no test coverage detected