1 // Copyright (C) 2007-2023 CEA, EDF, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 #include "OCCViewer_ViewPort3d.h"
25 #include "OCCViewer_VService.h"
26 #include "OCCViewer_ViewWindow.h"
27 #include "OCCViewer_ViewModel.h"
29 #include <SUIT_ViewManager.h>
30 #include <SUIT_ViewModel.h>
31 #include <SUIT_Session.h>
32 #include <SUIT_ResourceMgr.h>
38 #include <QPaintEvent>
39 #include <QResizeEvent>
40 #include <QApplication>
44 #include <gp_Quaternion.hxx>
45 #include <V3d_View.hxx>
47 #include "utilities.h"
50 #include <WNT_Window.hxx>
52 //#include <Xw_Window.hxx>
55 static double rx = 0.;
56 static double ry = 0.;
59 static Standard_Boolean zRotation = Standard_False;
61 //#include <Standard_Version.hxx>
66 OCCViewer_ViewPort3d::OCCViewer_ViewPort3d( QWidget* parent, const Handle( V3d_Viewer)& viewer, V3d_TypeOfView type )
67 : OCCViewer_ViewPort( parent ),
70 myIsAdvancedZoomingEnabled( false ),
71 myIsRotating( false ),
74 // VSR: 01/07/2010 commented to avoid SIGSEGV at SALOME exit
77 myActiveView = new V3d_View( viewer, type );
88 OCCViewer_ViewPort3d::~OCCViewer_ViewPort3d()
104 Handle(V3d_View) aView = activeView();
110 Activates the desired 'type' of view in the viewer
111 ( view of 'type' is created if it doesn't exist ). [ public ]
113 /*void OCCViewer_ViewPort3d::setActive( V3d_TypeOfView type )
115 if ( activeView().IsNull() )
118 if ( activeView()->Type() != type )
120 if ( type == V3d_ORTHOGRAPHIC )
121 setView( myOrthoView );
122 if ( type == V3d_PERSPECTIVE )
123 setView( myPerspView );
128 Maps CasCade 'view' to this viewport. [ private ]
130 bool OCCViewer_ViewPort3d::mapView( const Handle(V3d_View)& view )
132 if ( !setWindow( view ) )
135 if ( !mapped( view ) ) {
136 view->SetWindow( myWindow );
137 if ( view != activeView() )
138 view->View()->Deactivate();
141 emit( vpMapped(this) );
149 Sets new CASCADE view on viewport. Returns the previous active view. [ public ]
151 Handle( V3d_View ) OCCViewer_ViewPort3d::setView( const Handle( V3d_View )& view )
153 /* map the new view */
154 if ( view == activeView() || !mapView( view ) )
157 /* activate the new view*/
158 Handle( V3d_View ) oldView = activeView();
159 if ( !oldView.IsNull() ) {
160 if (oldView->View()->IsDefined())
161 oldView->View()->Deactivate();
162 view->SetBackgroundColor( oldView->BackgroundColor() );
165 view->View()->Activate();
171 Returns CasCade 3D view. [ public ]
173 Handle(V3d_View) OCCViewer_ViewPort3d::getView() const
179 Returns CasCade 3D viewer [ public ]
181 Handle(V3d_Viewer) OCCViewer_ViewPort3d::getViewer() const
183 Handle(V3d_Viewer) viewer;
184 if ( !activeView().IsNull() )
185 viewer = activeView()->Viewer();
190 Syncronizes visual state of this viewport with 'ref'
191 ( scale, projection, eye etc ) Returns 'true' if copied OK,
192 'false' otherwise. [ virtual public ]
194 bool OCCViewer_ViewPort3d::syncronize( const OCCViewer_ViewPort3d* ref )
196 OCCViewer_ViewPort3d* ref3d = (OCCViewer_ViewPort3d*)ref;
197 Handle(V3d_View) refView = ref3d->getView();
198 Handle(V3d_View) tgtView = getView();
200 /* Syncronize view types */
201 /* if ( tgtView->Type() != refView->Type() )
203 setActive( refView->Type() );
207 /* The following params are copied:
208 - view type( ortho/persp )
209 - position of view point
210 - orientation of high point
211 - position of the eye
218 /* we'll update after setting all params */
219 tgtView->SetImmediateUpdate( Standard_False );
222 if ( refView->Type() == V3d_PERSPECTIVE )
223 tgtView->SetFocale( refView->Focale() );
226 Standard_Real x, y, z;
227 refView->At( x, y, z ); tgtView->SetAt( x, y, z );
228 refView->Up( x, y, z ); tgtView->SetUp( x, y, z );
229 refView->Eye( x, y, z ); tgtView->SetEye( x, y, z );
230 refView->Proj( x, y, z ); tgtView->SetProj( x, y, z );
231 tgtView->SetScale( refView->Scale() );
232 tgtView->SetTwist( refView->Twist() );
236 tgtView->SetImmediateUpdate( Standard_True );
243 Get axial scale to the view
245 void OCCViewer_ViewPort3d::getAxialScale( double& xScale, double& yScale, double& zScale )
247 xScale = yScale = zScale = 1.;
249 if ( !activeView().IsNull() )
250 activeView()->AxialScale( xScale, yScale, zScale );
254 Returns the background color [ virtual public ] [ obsolete ]
256 QColor OCCViewer_ViewPort3d::backgroundColor() const
258 return background().color();
262 Sets the background color [ virtual public ] [ obsolete ]
264 void OCCViewer_ViewPort3d::setBackgroundColor( const QColor& color )
266 Qtx::BackgroundData bg = background();
267 bg.setColor( color );
272 Returns the background data
274 Qtx::BackgroundData OCCViewer_ViewPort3d::background() const
280 Sets the background data
282 void OCCViewer_ViewPort3d::setBackground( const Qtx::BackgroundData& bgData )
284 if ( bgData.isValid() ) {
285 myBackground = bgData;
287 emit vpChangeBackground( myBackground );
291 void OCCViewer_ViewPort3d::updateBackground()
293 if ( activeView().IsNull() ) return;
294 if ( !myBackground.isValid() ) return;
296 switch ( myBackground.mode() ) {
297 case Qtx::ColorBackground:
299 QColor c = myBackground.color();
301 // Unset texture should be done here
303 Quantity_Color qCol( c.red()/255., c.green()/255., c.blue()/255., Quantity_TOC_RGB );
304 activeView()->SetBgGradientStyle( Aspect_GFM_NONE ); // cancel gradient background
305 activeView()->SetBgImageStyle( Aspect_FM_NONE ); // cancel texture background
306 // then change background color
307 activeView()->SetBackgroundColor( qCol );
309 activeView()->Update();
313 case Qtx::SimpleGradientBackground:
316 int type = myBackground.gradient( c1, c2 );
317 if ( c1.isValid() && type >= OCCViewer_Viewer::HorizontalGradient && type <= OCCViewer_Viewer::LastGradient ) {
318 // Unset texture should be done here
320 // Get colors and set-up gradiented background
321 if ( !c2.isValid() ) c2 = c1;
322 Quantity_Color qCol1( c1.red()/255., c1.green()/255., c1.blue()/255., Quantity_TOC_RGB );
323 Quantity_Color qCol2( c2.red()/255., c2.green()/255., c2.blue()/255., Quantity_TOC_RGB );
324 activeView()->SetBgImageStyle( Aspect_FM_NONE ); // cancel texture background
326 case OCCViewer_Viewer::HorizontalGradient:
327 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_HOR, Standard_True );
329 case OCCViewer_Viewer::VerticalGradient:
330 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_VER, Standard_True );
332 case OCCViewer_Viewer::Diagonal1Gradient:
333 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_DIAG1, Standard_True );
335 case OCCViewer_Viewer::Diagonal2Gradient:
336 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_DIAG2, Standard_True );
338 case OCCViewer_Viewer::Corner1Gradient:
339 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_CORNER1, Standard_True );
341 case OCCViewer_Viewer::Corner2Gradient:
342 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_CORNER2, Standard_True );
344 case OCCViewer_Viewer::Corner3Gradient:
345 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_CORNER3, Standard_True );
347 case OCCViewer_Viewer::Corner4Gradient:
348 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_CORNER4, Standard_True );
356 case Qtx::CustomGradientBackground:
358 // NOT IMPLEMENTED YET
364 if ( myBackground.isTextureShown() ) {
366 int textureMode = myBackground.texture( fileName );
367 QFileInfo fi( fileName );
368 if ( !fileName.isEmpty() && fi.exists() ) {
369 // set texture image: file name and fill mode
370 switch ( textureMode ) {
371 case Qtx::CenterTexture:
372 activeView()->SetBackgroundImage( fi.absoluteFilePath().toUtf8().constData(), Aspect_FM_CENTERED );
374 case Qtx::TileTexture:
375 activeView()->SetBackgroundImage( fi.absoluteFilePath().toUtf8().constData(), Aspect_FM_TILED );
377 case Qtx::StretchTexture:
378 activeView()->SetBackgroundImage( fi.absoluteFilePath().toUtf8().constData(), Aspect_FM_STRETCH );
383 activeView()->Update();
389 Updates the active viewport. [ virtual public ]
391 void OCCViewer_ViewPort3d::onUpdate()
393 if ( !activeView().IsNull() )
394 activeView()->Update();
398 Called at 'window fit' transformation. [ virtual protected ]
400 void OCCViewer_ViewPort3d::fitRect( const QRect& rect )
402 if ( !activeView().IsNull() ) {
403 activeView()->WindowFit( rect.left(), rect.top(), rect.right(), rect.bottom() );
404 emit vpTransformed( this );
409 Inits 'zoom' transformation. [ protected ]
411 void OCCViewer_ViewPort3d::startZoomAtPoint( int x, int y )
416 if ( !activeView().IsNull() && isAdvancedZoomingEnabled() )
417 activeView()->StartZoomAtPoint( x, y );
421 Called at 'zoom' transformation. [ virtual protected ]
423 void OCCViewer_ViewPort3d::zoom( int x0, int y0, int x, int y )
428 if ( !activeView().IsNull() ) {
429 // as OCCT respects a sign of only dx,
430 // but we want both signes to be taken into account
431 //activeView()->Zoom( x0, y0, x, y );
432 if ( isAdvancedZoomingEnabled() )
433 activeView()->ZoomAtPoint( x0, y0, x, y );
435 activeView()->Zoom( x0 + y0, 0, x + y, 0 );
436 emit vpTransformed( this );
441 Centers the viewport. [ virtual protected ]
443 void OCCViewer_ViewPort3d::setCenter( int x, int y )
448 if ( !activeView().IsNull() ) {
449 activeView()->Place( x, y, myScale );
450 emit vpTransformed( this );
455 Called at 'pan' transformation. [ virtual protected ]
457 void OCCViewer_ViewPort3d::pan( int dx, int dy )
462 if ( !activeView().IsNull() ) {
463 activeView()->Pan( dx, dy, 1.0 );
464 emit vpTransformed( this );
469 Inits 'rotation' transformation. [ protected ]
471 void OCCViewer_ViewPort3d::startRotation( int x, int y,
472 int theRotationPointType,
473 const gp_Pnt& theSelectedPoint )
478 if ( !activeView().IsNull() ) {
480 Standard_Real zRotationThreshold, X, Y;
482 activeView()->Size(X,Y);
483 rx = Standard_Real(activeView()->Convert(X));
484 ry = Standard_Real(activeView()->Convert(Y));
487 switch ( theRotationPointType ) {
488 case OCCViewer_ViewWindow::BBCENTER:
489 centerPnt = activeView()->GravityPoint();
490 zRotation = Standard_False;
491 zRotationThreshold = 0.45;
492 if( zRotationThreshold > 0. ) {
493 Standard_Real dx = Abs(sx - rx/2.);
494 Standard_Real dy = Abs(sy - ry/2.);
495 Standard_Real dd = zRotationThreshold * (rx + ry)/2.;
496 if( dx > dd || dy > dd ) zRotation = Standard_True;
498 activeView()->StartRotation( x, y, 0.45 );
500 case OCCViewer_ViewWindow::SELECTED:
501 activeView()->Rotate( 0., 0., 0.,
502 theSelectedPoint.X(),theSelectedPoint.Y(), theSelectedPoint.Z(),
505 zRotation = Standard_False;
506 zRotationThreshold = 0.45;
507 if( zRotationThreshold > 0. ) {
508 Standard_Real dx = Abs(sx - rx/2.);
509 Standard_Real dy = Abs(sy - ry/2.);
510 Standard_Real dd = zRotationThreshold * (rx + ry)/2.;
511 if( dx > dd || dy > dd ) zRotation = Standard_True;
517 // VSR: 10.06.2015: next line commented out - causes ugly blinking on starting rotation with Perspective projection mode
518 //activeView()->DepthFitAll();
523 Rotates the viewport. [ protected ]
525 void OCCViewer_ViewPort3d::rotate( int x, int y,
526 int theRotationPointType,
527 const gp_Pnt& theSelectedPoint )
529 if ( !activeView().IsNull() ) {
530 switch ( theRotationPointType ) {
531 case OCCViewer_ViewWindow::BBCENTER:
532 activeView()->Rotation( x, y );
534 case OCCViewer_ViewWindow::SELECTED:
537 dz = atan2(Standard_Real(x)-rx/2., ry/2.-Standard_Real(y)) -
538 atan2(sx-rx/2.,ry/2.-sy);
542 dx = (Standard_Real(x) - sx) * M_PI/rx;
543 dy = (sy - Standard_Real(y)) * M_PI/ry;
547 activeView()->Rotate( dx, dy, dz,
548 theSelectedPoint.X(),theSelectedPoint.Y(), theSelectedPoint.Z(),
554 emit vpTransformed( this );
556 // setZSize( getZSize() );
560 Resets the viewport after 'rotation'. [ protected ]
562 void OCCViewer_ViewPort3d::endRotation()
564 if ( !activeView().IsNull() ) {
565 activeView()->Update();
566 emit vpTransformed( this );
571 Set the rotation axis and start automatic rotation
573 void OCCViewer_ViewPort3d::setRotationAxis(const gp_Vec& theAxis, double theAngle, double theZAngle)
575 myRotAxis.SetLocation(activeView()->GravityPoint());
577 gp_Dir anAxisDir = activeView()->Camera()->Direction();
578 myRotAxis.SetDirection(anAxisDir.Reversed());
579 myRotAngle = theZAngle;
582 myRotAxis.SetDirection(gp_Dir(theAxis));
583 myRotAngle = theAngle;
586 myRotTimer = new QTimer(this);
587 myRotTimer->setSingleShot(true);
588 connect(myRotTimer, SIGNAL(timeout()), this, SLOT(updateRotation()));
594 myLastRender = QDateTime::currentMSecsSinceEpoch();
595 Handle(Graphic3d_Camera) aCamera = activeView()->Camera();
597 trsfRot.SetRotation (myRotAxis, myRotAngle);
598 aCamera->Transform(trsfRot);
599 activeView()->SetCamera(aCamera);
600 myRotTimer->start(20);
604 Stop the automatic rotation
606 void OCCViewer_ViewPort3d::stopRotation()
608 myIsRotating = false;
614 Update the automatic rotation animation
616 void OCCViewer_ViewPort3d::updateRotation()
621 qint64 curTime = QDateTime::currentMSecsSinceEpoch();
622 double angle = myRotAngle * (curTime - myLastRender) / 100.;
623 Handle(Graphic3d_Camera) aCamera = activeView()->Camera();
625 trsfRot.SetRotation(myRotAxis, angle);
626 aCamera->Transform(trsfRot);
627 activeView()->SetCamera(aCamera);
629 myLastRender = curTime;
631 myRotTimer->start(20);
635 Repaints the viewport. [ virtual protected ]
637 void OCCViewer_ViewPort3d::paintEvent( QPaintEvent* e )
640 /* X11 : map before show doesn't work */
641 if ( !mapped( activeView() ) )
642 mapView( activeView() );
644 if ( !myWindow.IsNull() ) {
645 if ( !myPaintersRedrawing ) {
646 activeView()->Redraw();
649 OCCViewer_ViewPort::paintEvent( e );
654 Resizes the viewport. [ virtual protected ]
656 void OCCViewer_ViewPort3d::resizeEvent( QResizeEvent* e )
658 /* Map before first show to avoid flicker */
659 if ( !mapped( activeView() ) )
660 mapView( activeView() );
661 QTimer::singleShot( 0, this, SLOT( repaintViewAfterMove() ) );
662 emit vpResizeEvent( e );
668 void OCCViewer_ViewPort3d::repaintViewAfterMove( )
670 if ( !activeView().IsNull() ){
671 activeView()->MustBeResized();
676 Fits all objects in view. [ virtual protected ]
678 void OCCViewer_ViewPort3d::fitAll( bool keepScale, bool /*withZ*/, bool upd )
680 if ( activeView().IsNull() )
687 myScale = activeView()->Scale();
689 Standard_Real margin = 0.01;
691 activeView()->FitAll( margin, upd );
693 emit vpTransformed( this );
697 Resets the view. [ virtual protected ]
699 void OCCViewer_ViewPort3d::reset()
704 // double zsize = getZSize();
705 if ( !activeView().IsNull() ) {
706 activeView()->Reset();
707 emit vpTransformed( this );
708 // setZSize( zsize );
713 Rotate the view in the view plane (orthogonal to the view vector)
715 void OCCViewer_ViewPort3d::rotateXY( double degrees )
717 if ( activeView().IsNull() )
723 int x = width()/2, y = height()/2;
725 activeView()->Convert( x, y, X, Y, Z );
726 activeView()->Rotate( 0, 0, degrees * M_PI / 180., X, Y, Z );
727 emit vpTransformed( this );
731 Set axial scale to the view
733 void OCCViewer_ViewPort3d::setAxialScale( double xScale, double yScale, double zScale )
735 if ( activeView().IsNull() )
738 activeView()->SetAxialScale( xScale, yScale, zScale );
739 emit vpTransformed( this );
743 Passed the handle of native window of the component to CASCADE view. [ private ]
745 bool OCCViewer_ViewPort3d::setWindow( const Handle(V3d_View)& view )
747 if ( !myWindow.IsNull() )
753 attachWindow( view, OCCViewer_VService::CreateWindow( view, winId() ) );
755 myWindow = view->Window();
756 return !myWindow.IsNull();
759 void OCCViewer_ViewPort3d::attachWindow( const Handle(V3d_View)& view,
760 const Handle(Aspect_Window)& window)
762 if (!view.IsNull()) {
763 view->SetWindow( window );
769 Returns the current active view. [ private ]
771 Handle(V3d_View) OCCViewer_ViewPort3d::activeView() const
777 Returns the current inactive view [ private ]
779 /*Handle(V3d_View) OCCViewer_ViewPort3d::inactiveView() const
781 return ( activeView() == myOrthoView ? myPerspView : myOrthoView );
785 Returns 'true' if the given view is mapped to window. [ private ]
787 bool OCCViewer_ViewPort3d::mapped( const Handle(V3d_View)& view ) const
789 return ( !view.IsNull() && view->View()->IsDefined() );
793 Performs synchronization of view parameters with the specified view.
794 Returns \c true if synchronization is done successfully or \c false otherwise.
795 Default implementation does nothing (return \c false)
797 bool OCCViewer_ViewPort3d::synchronize( OCCViewer_ViewPort* view )
800 OCCViewer_ViewPort3d* vp3d = qobject_cast<OCCViewer_ViewPort3d*>( view );
802 bool blocked = blockSignals( false );
803 Handle(V3d_View) aView3d = getView();
804 Handle(V3d_View) aRefView3d = vp3d->getView();
805 aView3d->SetImmediateUpdate( Standard_False );
806 aView3d->Camera()->Copy( aRefView3d->Camera() );
807 aView3d->SetImmediateUpdate( Standard_True );
809 blockSignals( blocked );
816 * Show/Hide static triedron
818 void OCCViewer_ViewPort3d::showStaticTrihedron( bool on )
820 Handle(V3d_View) aView = activeView();
821 if ( !aView ) return;
824 aView->ZBufferTriedronSetup();
825 aView->TriedronDisplay( Aspect_TOTP_LEFT_LOWER, Quantity_NOC_WHITE, 0.05, V3d_ZBUFFER );
827 aView->TriedronErase();
833 * Create default cursor with a specific shape
835 void OCCViewer_ViewPort3d::setDefaultCursor( Qt::CursorShape theCursorShape )
838 myCursor = new QCursor();
840 myCursor->setShape( theCursorShape );
844 * Get default cursor with a specific shape
846 QCursor* OCCViewer_ViewPort3d::getDefaultCursor() const
852 * Set default parameters from preferences
854 void OCCViewer_ViewPort3d::setDefaultParams()
856 setBackground( Qtx::BackgroundData( Qt::black ) ); // set default background
858 // get ray tracing parameters from preferences
859 int aDepth = SUIT_Session::session()->resourceMgr()->integerValue( "OCCViewer", "rt_depth", 3 );
860 bool aReflection = SUIT_Session::session()->resourceMgr()->booleanValue( "OCCViewer", "rt_reflection", true );
861 bool anAntialiasing = SUIT_Session::session()->resourceMgr()->booleanValue( "OCCViewer", "rt_antialiasing", false );
862 bool aShadow = SUIT_Session::session()->resourceMgr()->booleanValue( "OCCViewer", "rt_shadow", true );
863 bool aTransparentShadow = SUIT_Session::session()->resourceMgr()->booleanValue( "OCCViewer", "rt_trans_shadow", true );
865 Graphic3d_RenderingParams& aParams = myActiveView->ChangeRenderingParams();
866 aParams.RaytracingDepth = aDepth;
867 aParams.IsReflectionEnabled = aReflection;
868 aParams.IsAntialiasingEnabled = anAntialiasing;
869 aParams.IsShadowEnabled = aShadow;
870 aParams.IsTransparentShadowEnabled = aTransparentShadow;
871 myActiveView->Redraw();