diff --git a/src/AIS/AIS_Animation.cxx b/src/AIS/AIS_Animation.cxx new file mode 100644 index 0000000000..32a055fef5 --- /dev/null +++ b/src/AIS/AIS_Animation.cxx @@ -0,0 +1,306 @@ +// Created by: Anastasia BORISOVA +// Copyright (c) 2016 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +#include + +IMPLEMENT_STANDARD_RTTIEXT(AIS_Animation, Standard_Transient) + +//============================================================================= +//function : Constructor +//purpose : +//============================================================================= +AIS_Animation::AIS_Animation (const TCollection_AsciiString& theAnimationName) +: myName (theAnimationName), + myState (AnimationState_Stopped), + myPtsStart (0.0), + myOwnDuration (0.0), + myChildrenDuration (0.0) +{ + // +} + +//============================================================================= +//function : ~AIS_Animation +//purpose : +//============================================================================= +AIS_Animation::~AIS_Animation() +{ + Clear(); +} + +//============================================================================= +//function : Clear +//purpose : +//============================================================================= +void AIS_Animation::Clear() +{ + myAnimations.Clear(); + myOwnDuration = 0.0; +} + +//============================================================================= +//function : Add +//purpose : +//============================================================================= +void AIS_Animation::Add (const Handle(AIS_Animation)& theAnimation) +{ + if (theAnimation.IsNull()) + { + Standard_ProgramError::Raise ("AIS_Animation::Add() - attempt to add a NULL animation!"); + } + + for (NCollection_Sequence::Iterator anIter (myAnimations); anIter.More(); anIter.Next()) + { + if (anIter.Value() == theAnimation) + { + UpdateTotalDuration(); + return; + } + } + + myAnimations.Append (theAnimation); + UpdateTotalDuration(); +} + +//============================================================================= +//function : Find +//purpose : +//============================================================================= +Handle(AIS_Animation) AIS_Animation::Find (const TCollection_AsciiString& theAnimationName) const +{ + for (NCollection_Sequence::Iterator anIter (myAnimations); anIter.More(); anIter.Next()) + { + if (anIter.Value()->Name() == theAnimationName) + { + return anIter.Value(); + } + } + return Handle(AIS_Animation)(); +} + +//============================================================================= +//function : Remove +//purpose : +//============================================================================= +Standard_Boolean AIS_Animation::Remove (const Handle(AIS_Animation)& theAnimation) +{ + for (NCollection_Sequence::Iterator anIter (myAnimations); anIter.More(); anIter.Next()) + { + if (anIter.Value() == theAnimation) + { + myAnimations.Remove (anIter); + UpdateTotalDuration(); + return Standard_True; + } + } + return Standard_False; +} + +//============================================================================= +//function : Replace +//purpose : +//============================================================================= +Standard_Boolean AIS_Animation::Replace (const Handle(AIS_Animation)& theAnimationOld, + const Handle(AIS_Animation)& theAnimationNew) +{ + for (NCollection_Sequence::Iterator anIter (myAnimations); anIter.More(); anIter.Next()) + { + if (anIter.Value() == theAnimationOld) + { + anIter.ChangeValue() = theAnimationNew; + UpdateTotalDuration(); + return Standard_True; + } + } + return Standard_False; +} + +//============================================================================= +//function : CopyFrom +//purpose : +//============================================================================= +void AIS_Animation::CopyFrom (const Handle(AIS_Animation)& theOther) +{ + myAnimations.Clear(); + for (NCollection_Sequence::Iterator anIter (theOther->myAnimations); anIter.More(); anIter.Next()) + { + myAnimations.Append (anIter.Value()); + } + UpdateTotalDuration(); + myPtsStart = theOther->myPtsStart; + myOwnDuration = theOther->myOwnDuration; +} + +//============================================================================= +//function : UpdateTotalDuration +//purpose : +//============================================================================= +void AIS_Animation::UpdateTotalDuration() +{ + myChildrenDuration = 0.0; + for (NCollection_Sequence::Iterator anIter (myAnimations); anIter.More(); anIter.Next()) + { + myChildrenDuration = Max (myChildrenDuration, anIter.Value()->StartPts() + anIter.Value()->Duration()); + } +} + +//============================================================================= +//function : StartTimer +//purpose : +//============================================================================= +void AIS_Animation::StartTimer (const Standard_Real theStartPts, + const Standard_Real thePlaySpeed, + const Standard_Boolean theToUpdate) +{ + if (myTimer.IsNull()) + { + myTimer = new AIS_AnimationTimer(); + } + myTimer->Stop(); + myTimer->Seek (theStartPts); + myTimer->SetPlaybackSpeed (thePlaySpeed); + Start (theToUpdate); +} + +//============================================================================= +//function : UpdateTimer +//purpose : +//============================================================================= +Standard_Real AIS_Animation::UpdateTimer() +{ + if (myTimer.IsNull()) + { + Standard_ProgramError::Raise ("AIS_Animation::UpdateTimer() - timer was not created!"); + } + + const Standard_Real anElapsedTime = myTimer->ElapsedTime(); + Update (anElapsedTime); + return anElapsedTime; +} + +//============================================================================= +//function : Start +//purpose : +//============================================================================= +void AIS_Animation::Start (const Standard_Boolean theToUpdate) +{ + UpdateTotalDuration(); + myState = AnimationState_Started; + for (NCollection_Sequence::Iterator anIter (myAnimations); anIter.More(); anIter.Next()) + { + anIter.ChangeValue()->Start (Standard_False); + } + + if (theToUpdate) + { + const Standard_Real anElapsedTime = !myTimer.IsNull() + ? myTimer->ElapsedTime() + : 0.0; + Update (anElapsedTime); + } + + if (!myTimer.IsNull()) + { + myTimer->Start(); + } +} + +//============================================================================= +//function : Pause +//purpose : +//============================================================================= +void AIS_Animation::Pause() +{ + myState = AnimationState_Paused; + if (!myTimer.IsNull()) + { + myTimer->Pause(); + } + + for (NCollection_Sequence::Iterator anIter (myAnimations); anIter.More(); anIter.Next()) + { + anIter.ChangeValue()->Stop(); + } +} + +//============================================================================= +//function : Stop +//purpose : +//============================================================================= +void AIS_Animation::Stop() +{ + myState = AnimationState_Stopped; + if (!myTimer.IsNull()) + { + myTimer->Stop(); + } + + for (NCollection_Sequence::Iterator anIter (myAnimations); anIter.More(); anIter.Next()) + { + anIter.ChangeValue()->Stop(); + } +} + +//============================================================================= +//function : Update +//purpose : +//============================================================================= +Standard_Boolean AIS_Animation::Update (const Standard_Real thePts) +{ + AIS_AnimationProgress aPosition; + aPosition.Pts = thePts; + aPosition.LocalPts = thePts - myPtsStart; + aPosition.LocalNormalized = HasOwnDuration() + ? (aPosition.LocalPts / myOwnDuration) + : 0.0; + aPosition.LocalNormalized = Max (0.0, aPosition.LocalNormalized); + aPosition.LocalNormalized = Min (1.0, aPosition.LocalNormalized); + updateWithChildren (aPosition); + return thePts < myPtsStart + Duration(); +} + +//============================================================================= +//function : updateWithChildren +//purpose : +//============================================================================= +void AIS_Animation::updateWithChildren (const AIS_AnimationProgress& thePosition) +{ + if (thePosition.LocalPts < 0.0 + || IsStopped()) + { + return; + } + + for (NCollection_Sequence::Iterator anIter (myAnimations); anIter.More(); anIter.Next()) + { + const Handle(AIS_Animation)& anAnim = anIter.Value(); + AIS_AnimationProgress aPosition = thePosition; + aPosition.LocalPts = aPosition.LocalPts - anAnim->StartPts(); + aPosition.LocalNormalized = anAnim->HasOwnDuration() + ? (aPosition.LocalPts / anAnim->OwnDuration()) + : 0.0; + aPosition.LocalNormalized = Max (0.0, aPosition.LocalNormalized); + aPosition.LocalNormalized = Min (1.0, aPosition.LocalNormalized); + anAnim->updateWithChildren (aPosition); + } + + if (thePosition.LocalPts >= Duration()) + { + Stop(); + } + + update (thePosition); +} diff --git a/src/AIS/AIS_Animation.hxx b/src/AIS/AIS_Animation.hxx new file mode 100644 index 0000000000..9b192ccfaf --- /dev/null +++ b/src/AIS/AIS_Animation.hxx @@ -0,0 +1,172 @@ +// Created by: Anastasia BORISOVA +// Copyright (c) 2016 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _AIS_Animation_HeaderFile +#define _AIS_Animation_HeaderFile + +#include +#include +#include + +//! Structure defining current animation progress. +struct AIS_AnimationProgress +{ + Standard_Real Pts; //!< global presentation timestamp + Standard_Real LocalPts; //!< presentation within current animation + Standard_Real LocalNormalized; //!< normalized position within current animation within 0..1 range + + AIS_AnimationProgress() : Pts (-1.0), LocalPts (-1.0), LocalNormalized (-1.0) {} +}; + +DEFINE_STANDARD_HANDLE(AIS_Animation, Standard_Transient) + +//! Class represents single animation. +//! It is defined with: +//! - Start time on the timeline started from 0, in seconds +//! - Duration, in seconds +//! - virtual method Update() for handling an update +class AIS_Animation : public Standard_Transient +{ + DEFINE_STANDARD_RTTIEXT(AIS_Animation, Standard_Transient) +public: + + //! Creates empty animation. + Standard_EXPORT AIS_Animation (const TCollection_AsciiString& theAnimationName); + + //! Destruct object, clear arguments + Standard_EXPORT virtual ~AIS_Animation(); + + //! Animation name. + const TCollection_AsciiString& Name() const { return myName; } + +public: + + //! @return start time of the animation in the timeline + Standard_Real StartPts() const { return myPtsStart; } + + //! Sets time limits for animation in the animation timeline + void SetStartPts (const Standard_Real thePtsStart) { myPtsStart = thePtsStart; } + + //! @return duration of the animation in the timeline + Standard_Real Duration() const { return Max (myOwnDuration, myChildrenDuration); } + + //! Update total duration considering all animations on timeline. + Standard_EXPORT void UpdateTotalDuration(); + + //! Return true if duration is defined. + Standard_Boolean HasOwnDuration() const { return myOwnDuration > 0.0; } + + //! @return own duration of the animation in the timeline + Standard_Real OwnDuration() const { return myOwnDuration; } + + //! Defines duration of the animation. + void SetOwnDuration (const Standard_Real theDuration) { myOwnDuration = theDuration; } + + //! Add single animation to the timeline. + //! @param theAnimation input animation + Standard_EXPORT void Add (const Handle(AIS_Animation)& theAnimation); + + //! Clear animation timeline - remove all animations from it. + Standard_EXPORT void Clear(); + + //! Return the child animation with the given name. + Standard_EXPORT Handle(AIS_Animation) Find (const TCollection_AsciiString& theAnimationName) const; + + //! Remove the child animation. + Standard_EXPORT Standard_Boolean Remove (const Handle(AIS_Animation)& theAnimation); + + //! Replace the child animation. + Standard_EXPORT Standard_Boolean Replace (const Handle(AIS_Animation)& theAnimationOld, + const Handle(AIS_Animation)& theAnimationNew); + + //! Clears own children and then copy child animations from another object. + //! Copy also Start Time and Duration values. + Standard_EXPORT void CopyFrom (const Handle(AIS_Animation)& theOther); + + //! Return sequence of child animations. + const NCollection_Sequence& Children() const { return myAnimations; } + +public: + + //! Start animation with internally defined timer instance. + //! Calls ::Start() internally. + Standard_EXPORT virtual void StartTimer (const Standard_Real theStartPts, + const Standard_Real thePlaySpeed, + const Standard_Boolean theToUpdate); + + //! Update single frame of animation, update timer state + //! @return current time of timeline progress. + Standard_EXPORT virtual Standard_Real UpdateTimer(); + + //! Return elapsed time. + Standard_Real ElapsedTime() const { return !myTimer.IsNull() ? myTimer->ElapsedTime() : 0.0; } + +public: + + //! Start animation. This method changes status of the animation to Started. + //! This status defines whether animation is to be performed in the timeline or not. + //! @param theToUpdate call Update() method + Standard_EXPORT virtual void Start (const Standard_Boolean theToUpdate); + + //! Pause the process timeline. + Standard_EXPORT virtual void Pause(); + + //! Stop animation. This method changed status of the animation to Stopped. + //! This status shows that animation will not be performed in the timeline or it is finished. + Standard_EXPORT virtual void Stop(); + + //! Check if animation is to be performed in the animation timeline. + //! @return True if it is stopped of finished. + bool IsStopped() { return myState != AnimationState_Started; } + + //! Update single frame of animation, update timer state + //! @param thePts [in] the time moment within [0; Duration()] + //! @return True if timeline is in progress + Standard_EXPORT virtual Standard_Boolean Update (const Standard_Real thePts); + +protected: + + //! Process one step of the animation according to the input time progress, including all children. + //! Calls also ::update() to update own animation. + Standard_EXPORT virtual void updateWithChildren (const AIS_AnimationProgress& thePosition); + + //! Update the own animation to specified position - should be overridden by sub-class. + virtual void update (const AIS_AnimationProgress& theProgress) { (void )theProgress; } + +protected: + + //! Defines animation state. + enum AnimationState + { + AnimationState_Started, //!< animation is in progress + AnimationState_Stopped, //!< animation is finished, force stopped or not started + AnimationState_Paused //!< animation is paused and can be started from the pause moment + }; + +protected: + + Handle(AIS_AnimationTimer) myTimer; + + TCollection_AsciiString myName; //!< animation name + NCollection_Sequence + myAnimations; //!< sequence of child animations + + AnimationState myState; //!< animation state - started, stopped of paused + Standard_Real myPtsStart; //!< time of start in the timeline + Standard_Real myOwnDuration; //!< duration of animation excluding children + Standard_Real myChildrenDuration; //!< duration of animation including children + +}; + +#endif // _AIS_Animation_HeaderFile diff --git a/src/AIS/AIS_AnimationCamera.cxx b/src/AIS/AIS_AnimationCamera.cxx new file mode 100644 index 0000000000..b5c6935c5d --- /dev/null +++ b/src/AIS/AIS_AnimationCamera.cxx @@ -0,0 +1,57 @@ +// Created by: Anastasia BORISOVA +// Copyright (c) 2016 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +#include +#include +#include + +IMPLEMENT_STANDARD_RTTIEXT(AIS_AnimationCamera, AIS_Animation) + +//============================================================================= +//function : AIS_AnimationCamera +//purpose : +//============================================================================= +AIS_AnimationCamera::AIS_AnimationCamera (const TCollection_AsciiString& theAnimationName, + const Handle(V3d_View)& theView) +: AIS_Animation (theAnimationName), + myView (theView) +{ + // +} + +//============================================================================= +//function : update +//purpose : +//============================================================================= +void AIS_AnimationCamera::update (const AIS_AnimationProgress& theProgress) +{ + if (myView.IsNull() + || myCamStart.IsNull() + || myCamEnd.IsNull()) + { + return; + } + + Handle(Graphic3d_Camera) aCamera = myView->Camera(); + + Graphic3d_CameraLerp aCamLerp (myCamStart, myCamEnd); + aCamLerp.Interpolate (theProgress.LocalNormalized, aCamera); + + const Standard_Boolean aPrevImmUpdate = myView->SetImmediateUpdate (Standard_False); + myView->SetCamera (aCamera); + myView->SetImmediateUpdate (aPrevImmUpdate); + myView->Invalidate(); +} diff --git a/src/AIS/AIS_AnimationCamera.hxx b/src/AIS/AIS_AnimationCamera.hxx new file mode 100644 index 0000000000..cd6d7e1fde --- /dev/null +++ b/src/AIS/AIS_AnimationCamera.hxx @@ -0,0 +1,63 @@ +// Created by: Anastasia BORISOVA +// Copyright (c) 2016 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _AIS_AnimationCamera_HeaderFile +#define _AIS_AnimationCamera_HeaderFile + +#include + +class Graphic3d_Camera; +class V3d_View; + +//! Camera animation. +class AIS_AnimationCamera : public AIS_Animation +{ + DEFINE_STANDARD_RTTIEXT(AIS_AnimationCamera, AIS_Animation) +public: + + //! Main constructor. + Standard_EXPORT AIS_AnimationCamera (const TCollection_AsciiString& theAnimationName, + const Handle(V3d_View)& theView); + + //! Return the target view. + const Handle(V3d_View)& View() const { return myView; } + + //! Return camera start position. + const Handle(Graphic3d_Camera)& CameraStart() const { return myCamStart; } + + //! Define camera start position. + void SetCameraStart (const Handle(Graphic3d_Camera)& theCameraStart) { myCamStart = theCameraStart; } + + //! Return camera end position. + const Handle(Graphic3d_Camera)& CameraEnd() const { return myCamEnd; } + + //! Define camera end position. + void SetCameraEnd (const Handle(Graphic3d_Camera)& theCameraEnd) { myCamEnd = theCameraEnd; } + +protected: + + //! Update the progress. + Standard_EXPORT virtual void update (const AIS_AnimationProgress& theProgress) Standard_OVERRIDE; + +protected: + + Handle(V3d_View) myView; //!< view to setup camera + Handle(Graphic3d_Camera) myCamStart; //!< starting camera position + Handle(Graphic3d_Camera) myCamEnd; //!< end camera position + +}; + +DEFINE_STANDARD_HANDLE(AIS_AnimationCamera, AIS_Animation) + +#endif // _AIS_AnimationCamera_HeaderFile diff --git a/src/AIS/AIS_AnimationObject.cxx b/src/AIS/AIS_AnimationObject.cxx new file mode 100644 index 0000000000..74ec0e4040 --- /dev/null +++ b/src/AIS/AIS_AnimationObject.cxx @@ -0,0 +1,102 @@ +// Created by: Anastasia BORISOVA +// Copyright (c) 2016 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +#include +#include +#include +#include + +IMPLEMENT_STANDARD_RTTIEXT(AIS_AnimationObject, AIS_Animation) + +//============================================================================= +//function : Constructor +//purpose : +//============================================================================= +AIS_AnimationObject::AIS_AnimationObject (const TCollection_AsciiString& theAnimationName, + const Handle(AIS_InteractiveContext)& theContext, + const Handle(AIS_InteractiveObject)& theObject, + const gp_Trsf& theTrsfStart, + const gp_Trsf& theTrsfEnd) +: AIS_Animation (theAnimationName), + myContext (theContext), + myObject (theObject), + myTrsfLerp (theTrsfStart, theTrsfEnd) +{ + // +} + +//============================================================================= +//function : update +//purpose : +//============================================================================= +void AIS_AnimationObject::update (const AIS_AnimationProgress& theProgress) +{ + if (myObject.IsNull()) + { + return; + } + + gp_Trsf aTrsf; + myTrsfLerp.Interpolate (theProgress.LocalNormalized, aTrsf); + if (!myContext.IsNull()) + { + myContext->SetLocation (myObject, aTrsf); + invalidateViewer(); + } + else + { + myObject->SetLocalTransformation (aTrsf); + } +} + +//============================================================================= +//function : invalidateViewer +//purpose : +//============================================================================= +void AIS_AnimationObject::invalidateViewer() +{ + if (myContext.IsNull()) + { + return; + } + + const Standard_Boolean isImmediate = myContext->CurrentViewer()->ZLayerSettings (myObject->ZLayer()).IsImmediate(); + if (!isImmediate) + { + myContext->CurrentViewer()->Invalidate(); + return; + } + + // Invalidate immediate view only if it is going out of z-fit range. + // This might be sub-optimal performing this for each animated objects in case of many animated objects. + for (V3d_ListOfView::Iterator aDefViewIter = myContext->CurrentViewer()->DefinedViewIterator(); + aDefViewIter.More(); aDefViewIter.Next()) + { + const Handle(V3d_View)& aView = aDefViewIter.Value(); + const Bnd_Box aMinMaxBox = aView->View()->MinMaxValues (Standard_False); + const Bnd_Box aGraphicBox = aView->View()->MinMaxValues (Standard_True); + Standard_Real aZNear = 0.0; + Standard_Real aZFar = 0.0; + if (aView->Camera()->ZFitAll (aDefViewIter.Value()->AutoZFitScaleFactor(), aMinMaxBox, aGraphicBox, aZNear, aZFar)) + { + if (aZNear < aView->Camera()->ZNear() + || aZFar > aView->Camera()->ZFar()) + { + aDefViewIter.Value()->Invalidate(); + } + } + } +} diff --git a/src/AIS/AIS_AnimationObject.hxx b/src/AIS/AIS_AnimationObject.hxx new file mode 100644 index 0000000000..5202c231e2 --- /dev/null +++ b/src/AIS/AIS_AnimationObject.hxx @@ -0,0 +1,60 @@ +// Created by: Anastasia BORISOVA +// Copyright (c) 2016 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _AIS_AnimationObject_HeaderFile +#define _AIS_AnimationObject_HeaderFile + +#include +#include +#include + +//! Animation defining object transformation. +class AIS_AnimationObject : public AIS_Animation +{ + DEFINE_STANDARD_RTTIEXT(AIS_AnimationObject, AIS_Animation) +public: + + //! Constructor with initialization. + //! Note that start/end transformations specify exactly local transformation of the object, + //! not the transformation to be applied to existing local transformation. + //! @param theAnimationName animation identifier + //! @param theContext interactive context where object have been displayed + //! @param theObject object to apply local transformation + //! @param theTrsfStart local transformation at the start of animation (e.g. theObject->LocalTransformation()) + //! @param theTrsfEnd local transformation at the end of animation + Standard_EXPORT AIS_AnimationObject (const TCollection_AsciiString& theAnimationName, + const Handle(AIS_InteractiveContext)& theContext, + const Handle(AIS_InteractiveObject)& theObject, + const gp_Trsf& theTrsfStart, + const gp_Trsf& theTrsfEnd); + +protected: + + //! Update the progress. + Standard_EXPORT virtual void update (const AIS_AnimationProgress& theProgress) Standard_OVERRIDE; + + //! Invalidate the viewer for proper update. + Standard_EXPORT void invalidateViewer(); + +protected: + + Handle(AIS_InteractiveContext) myContext; //!< context where object is displayed + Handle(AIS_InteractiveObject) myObject; //!< presentation object to set location + gp_TrsfNLerp myTrsfLerp; //!< interpolation tool + +}; + +DEFINE_STANDARD_HANDLE(AIS_AnimationObject, AIS_Animation) + +#endif // _AIS_AnimationObject_HeaderFile diff --git a/src/AIS/AIS_AnimationTimer.cxx b/src/AIS/AIS_AnimationTimer.cxx new file mode 100644 index 0000000000..8d5d962568 --- /dev/null +++ b/src/AIS/AIS_AnimationTimer.cxx @@ -0,0 +1,74 @@ +// Created by: Kirill Gavrilov +// Copyright (c) 2016 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +IMPLEMENT_STANDARD_RTTIEXT(AIS_AnimationTimer, Standard_Transient) + +//============================================================================= +//function : Pause +//purpose : +//============================================================================= +void AIS_AnimationTimer::Pause() +{ + myTimer.Stop(); + myTimerFrom += myTimer.ElapsedTime() * myTimerSpeed; + myTimer.Reset(); +} + +//============================================================================= +//function : Stop +//purpose : +//============================================================================= +void AIS_AnimationTimer::Stop() +{ + myTimer.Stop(); + myTimer.Reset(); + myTimerFrom = 0.0; +} + +//============================================================================= +//function : SetPlaybackSpeed +//purpose : +//============================================================================= +void AIS_AnimationTimer::SetPlaybackSpeed (const Standard_Real theSpeed) +{ + if (!myTimer.IsStarted()) + { + myTimerSpeed = theSpeed; + return; + } + + myTimer.Stop(); + myTimerFrom += myTimer.ElapsedTime() * myTimerSpeed; + myTimer.Reset(); + myTimerSpeed = theSpeed; + myTimer.Start(); +} + +//============================================================================= +//function : SetPlaybackSpeed +//purpose : +//============================================================================= +void AIS_AnimationTimer::Seek (const Standard_Real theTime) +{ + const Standard_Boolean isStarted = myTimer.IsStarted(); + myTimer.Stop(); + myTimer.Reset(); + myTimerFrom = theTime; + if (isStarted) + { + myTimer.Start(); + } +} diff --git a/src/AIS/AIS_AnimationTimer.hxx b/src/AIS/AIS_AnimationTimer.hxx new file mode 100644 index 0000000000..14add5186a --- /dev/null +++ b/src/AIS/AIS_AnimationTimer.hxx @@ -0,0 +1,74 @@ +// Created by: Kirill Gavrilov +// Copyright (c) 2016 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _AIS_AnimationTimer_HeaderFile +#define _AIS_AnimationTimer_HeaderFile + +#include +#include +#include + +//! Auxiliary class defining the animation timer. +class AIS_AnimationTimer : public Standard_Transient +{ + DEFINE_STANDARD_RTTIEXT(AIS_Animation, Standard_Transient) +public: + + //! Empty constructor. + AIS_AnimationTimer() : myTimerFrom (0.0), myTimerSpeed (1.0) {} + + //! Return elapsed time in seconds. + Standard_Real ElapsedTime() const + { + return myTimerFrom + myTimer.ElapsedTime() * myTimerSpeed; + } + + //! Return playback speed coefficient (1.0 means normal speed). + Standard_Real PlaybackSpeed() const { return myTimerSpeed; } + + //! Setup playback speed coefficient. + Standard_EXPORT void SetPlaybackSpeed (const Standard_Real theSpeed); + + //! Return true if timer has been started. + Standard_Boolean IsStarted() const + { + return myTimer.IsStarted(); + } + + //! Start the timer. + void Start() + { + myTimer.Start(); + } + + //! Pause the timer. + Standard_EXPORT void Pause(); + + //! Stop the timer. + Standard_EXPORT void Stop(); + + //! Seek the timer to specified position. + Standard_EXPORT void Seek (const Standard_Real theTime); + +protected: + + OSD_Timer myTimer; + Standard_Real myTimerFrom; + Standard_Real myTimerSpeed; + +}; + +DEFINE_STANDARD_HANDLE(AIS_AnimationTimer, Standard_Transient) + +#endif // _AIS_AnimationTimer_HeaderFile diff --git a/src/AIS/AIS_InteractiveContext.cxx b/src/AIS/AIS_InteractiveContext.cxx index 83089b8b79..70708ac6c6 100644 --- a/src/AIS/AIS_InteractiveContext.cxx +++ b/src/AIS/AIS_InteractiveContext.cxx @@ -2376,11 +2376,15 @@ void AIS_InteractiveContext::ClearGlobal (const Handle(AIS_InteractiveObject)& t aDefViewIter.Value()->View()->ChangeHiddenObjects()->Remove (theIObj.get()); } - if (!myLastinMain.IsNull() && myLastinMain->IsSameSelectable (theIObj)) - myLastinMain.Nullify(); - if (!myLastPicked.IsNull() && myLastPicked->IsSameSelectable (theIObj)) - myLastPicked.Nullify(); - myMainPM->ClearImmediateDraw(); + if (!myLastinMain.IsNull()) + { + if (myLastinMain->IsSameSelectable (theIObj) + || myLastPicked->IsSameSelectable(theIObj)) + { + myLastinMain.Nullify(); + myMainPM->ClearImmediateDraw(); + } + } if (theToUpdateviewer && aStatus->GraphicStatus() == AIS_DS_Displayed) { diff --git a/src/AIS/FILES b/src/AIS/FILES index 254e329fe3..aa6d72cfe8 100644 --- a/src/AIS/FILES +++ b/src/AIS/FILES @@ -1,5 +1,13 @@ AIS.cxx AIS.hxx +AIS_Animation.cxx +AIS_Animation.hxx +AIS_AnimationTimer.cxx +AIS_AnimationTimer.hxx +AIS_AnimationCamera.cxx +AIS_AnimationCamera.hxx +AIS_AnimationObject.cxx +AIS_AnimationObject.hxx AIS_AngleDimension.cxx AIS_AngleDimension.hxx AIS_AttributeFilter.cxx diff --git a/src/Graphic3d/Graphic3d_Camera.cxx b/src/Graphic3d/Graphic3d_Camera.cxx index f9f5c034c2..e46988d692 100644 --- a/src/Graphic3d/Graphic3d_Camera.cxx +++ b/src/Graphic3d/Graphic3d_Camera.cxx @@ -13,19 +13,18 @@ // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. -#include -#include - #include + +#include +#include +#include #include #include - +#include +#include #include #include -#include - - IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_Camera,Standard_Transient) namespace @@ -61,6 +60,16 @@ namespace Standard_Real aExp = Floor (aLogRadix); return FLT_EPSILON * Pow (FLT_RADIX, aExp); } + + //! Convert camera definition to Ax3 + gp_Ax3 cameraToAx3 (const Graphic3d_Camera& theCamera) + { + const gp_Dir aBackDir(gp_Vec(theCamera.Center(), theCamera.Eye())); + const gp_Dir anXAxis (theCamera.Up().Crossed (aBackDir)); + const gp_Dir anYAxis (aBackDir .Crossed (anXAxis)); + const gp_Dir aZAxis (anXAxis .Crossed (anYAxis)); + return gp_Ax3 (gp_Pnt (0.0, 0.0, 0.0), aZAxis, anXAxis); + } } // ======================================================================= @@ -1298,3 +1307,84 @@ bool Graphic3d_Camera::ZFitAll (const Standard_Real theScaleFactor, theZFar = aZFar; return true; } + +//============================================================================= +//function : Interpolate +//purpose : +//============================================================================= +template<> +Standard_EXPORT void NCollection_Lerp::Interpolate (const double theT, + Handle(Graphic3d_Camera)& theCamera) const +{ + if (Abs (theT - 1.0) < Precision::Confusion()) + { + // just copy end-point transformation + theCamera->Copy (myEnd); + return; + } + + theCamera->Copy (myStart); + if (Abs (theT - 0.0) < Precision::Confusion()) + { + return; + } + + // apply rotation + { + gp_Ax3 aCamStart = cameraToAx3 (*myStart); + gp_Ax3 aCamEnd = cameraToAx3 (*myEnd); + gp_Trsf aTrsfStart, aTrsfEnd; + aTrsfStart.SetTransformation (aCamStart, gp::XOY()); + aTrsfEnd .SetTransformation (aCamEnd, gp::XOY()); + + gp_Quaternion aRotStart = aTrsfStart.GetRotation(); + gp_Quaternion aRotEnd = aTrsfEnd .GetRotation(); + gp_Quaternion aRotDelta = aRotEnd * aRotStart.Inverted(); + gp_Quaternion aRot = gp_QuaternionNLerp::Interpolate (gp_Quaternion(), aRotDelta, theT); + gp_Trsf aTrsfRot; + aTrsfRot.SetRotation (aRot); + theCamera->Transform (aTrsfRot); + } + + // apply translation + { + gp_XYZ aCenter = NCollection_Lerp::Interpolate (myStart->Center().XYZ(), myEnd->Center().XYZ(), theT); + gp_XYZ anEye = NCollection_Lerp::Interpolate (myStart->Eye().XYZ(), myEnd->Eye().XYZ(), theT); + gp_XYZ anAnchor = aCenter; + Standard_Real aKc = 0.0; + + const Standard_Real aDeltaCenter = myStart->Center().Distance (myEnd->Center()); + const Standard_Real aDeltaEye = myStart->Eye() .Distance (myEnd->Eye()); + if (aDeltaEye <= gp::Resolution()) + { + anAnchor = anEye; + aKc = 1.0; + } + else if (aDeltaCenter > gp::Resolution()) + { + aKc = aDeltaCenter / (aDeltaCenter + aDeltaEye); + + const gp_XYZ anAnchorStart = NCollection_Lerp::Interpolate (myStart->Center().XYZ(), myStart->Eye().XYZ(), aKc); + const gp_XYZ anAnchorEnd = NCollection_Lerp::Interpolate (myEnd ->Center().XYZ(), myEnd ->Eye().XYZ(), aKc); + anAnchor = NCollection_Lerp::Interpolate (anAnchorStart, anAnchorEnd, theT); + } + + const gp_Vec aDirEyeToCenter = theCamera->Direction(); + const Standard_Real aDistEyeCenterStart = myStart->Eye().Distance (myStart->Center()); + const Standard_Real aDistEyeCenterEnd = myEnd ->Eye().Distance (myEnd ->Center()); + const Standard_Real aDistEyeCenter = NCollection_Lerp::Interpolate (aDistEyeCenterStart, aDistEyeCenterEnd, theT); + aCenter = anAnchor + aDirEyeToCenter.XYZ() * aDistEyeCenter * aKc; + anEye = anAnchor - aDirEyeToCenter.XYZ() * aDistEyeCenter * (1.0 - aKc); + + theCamera->SetCenter (aCenter); + theCamera->SetEye (anEye); + } + + // apply scaling + if (Abs(myStart->Scale() - myEnd->Scale()) > Precision::Confusion() + && myStart->IsOrthographic()) + { + const Standard_Real aScale = NCollection_Lerp::Interpolate (myStart->Scale(), myEnd->Scale(), theT); + theCamera->SetScale (aScale); + } +} diff --git a/src/Graphic3d/Graphic3d_Camera.hxx b/src/Graphic3d/Graphic3d_Camera.hxx index bc710d3230..93b7cdb827 100644 --- a/src/Graphic3d/Graphic3d_Camera.hxx +++ b/src/Graphic3d/Graphic3d_Camera.hxx @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -665,4 +666,26 @@ public: DEFINE_STANDARD_HANDLE (Graphic3d_Camera, Standard_Transient) +//! Linear interpolation tool for camera orientation and position. +//! This tool interpolates camera parameters scale, eye, center, rotation (up and direction vectors) independently. +//! +//! Eye/Center interpolation is performed through defining an anchor point in-between Center and Eye. +//! The anchor position is defined as point near to the camera point which has smaller translation part. +//! The main idea is to keep the distance between Center and Eye +//! (which will change if Center and Eye translation will be interpolated independently). +//! E.g.: +//! - When both Center and Eye are moved at the same vector -> both will be just translated by straight line +//! - When Center is not moved -> camera Eye will move around Center through arc +//! - When Eye is not moved -> camera Center will move around Eye through arc +//! - When both Center and Eye are move by different vectors -> transformation will be something in between, +//! and will try interpolate linearly the distance between Center and Eye. +//! +//! This transformation might be not in line with user expectations. +//! In this case, application might define intermediate camera positions for interpolation +//! or implement own interpolation logic. +template<> +Standard_EXPORT void NCollection_Lerp::Interpolate (const double theT, + Handle(Graphic3d_Camera)& theResult) const; +typedef NCollection_Lerp Graphic3d_CameraLerp; + #endif diff --git a/src/NCollection/FILES b/src/NCollection/FILES index 32fe100f96..7027ac5983 100755 --- a/src/NCollection/FILES +++ b/src/NCollection/FILES @@ -46,6 +46,7 @@ NCollection_IncAllocator.cxx NCollection_IncAllocator.hxx NCollection_IndexedDataMap.hxx NCollection_IndexedMap.hxx +NCollection_Lerp.hxx NCollection_List.hxx NCollection_ListNode.hxx NCollection_LocalArray.hxx diff --git a/src/NCollection/NCollection_Lerp.hxx b/src/NCollection/NCollection_Lerp.hxx new file mode 100644 index 0000000000..3453a05779 --- /dev/null +++ b/src/NCollection/NCollection_Lerp.hxx @@ -0,0 +1,71 @@ +// Created by: Kirill GAVRILOV +// Copyright (c) 2016 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _NCollection_Lerp_HeaderFile +#define _NCollection_Lerp_HeaderFile + +//! Simple linear interpolation tool (also known as mix() in GLSL). +//! The main purpose of this template class is making interpolation routines more readable. +template +class NCollection_Lerp +{ +public: + //! Compute interpolated value between two values. + //! @param theStart first value + //! @param theEnd second value + //! @param theT normalized interpolation coefficient within [0, 1] range, + //! with 0 pointing to theStart and 1 to theEnd. + static T Interpolate (const T& theStart, + const T& theEnd, + double theT) + { + T aResult; + NCollection_Lerp aLerp (theStart, theEnd); + aLerp.Interpolate (theT, aResult); + return aResult; + } + +public: + + //! Empty constructor + NCollection_Lerp() : myStart(), myEnd() {} + + //! Main constructor. + NCollection_Lerp (const T& theStart, const T& theEnd) + { + Init (theStart, theEnd); + } + + //! Initialize values. + void Init (const T& theStart, const T& theEnd) + { + myStart = theStart; + myEnd = theEnd; + } + + //! Compute interpolated value between two values. + //! @param theT normalized interpolation coefficient within [0, 1] range, + //! with 0 pointing to first value and 1 to the second value. + //! @param theResult [out] interpolated value + void Interpolate (double theT, T& theResult) const + { + theResult = (1.0 - theT) * myStart + theT * myEnd; + } + +private: + T myStart; + T myEnd; +}; + +#endif // _NCollection_Lerp_HeaderFile diff --git a/src/OSD/OSD_Chronometer.hxx b/src/OSD/OSD_Chronometer.hxx index 4c8c77b040..8942d61613 100644 --- a/src/OSD/OSD_Chronometer.hxx +++ b/src/OSD/OSD_Chronometer.hxx @@ -48,7 +48,10 @@ public: //! process (all threads, and completed children) is measured. Standard_EXPORT OSD_Chronometer(const Standard_Boolean ThisThreadOnly = Standard_False); Standard_EXPORT virtual ~OSD_Chronometer(); - + + //! Return true if timer has been started. + Standard_Boolean IsStarted() const { return !Stopped; } + //! Stops and Reinitializes the Chronometer. Standard_EXPORT virtual void Reset(); diff --git a/src/OSD/OSD_Timer.cxx b/src/OSD/OSD_Timer.cxx index 93ca383c3c..412a7ac505 100644 --- a/src/OSD/OSD_Timer.cxx +++ b/src/OSD/OSD_Timer.cxx @@ -102,6 +102,18 @@ static void Compute (Standard_Real Time, second = Time - heure * 3600 - minut * 60; } +//======================================================================= +//function : Reset +//purpose : +//======================================================================= + +void OSD_Timer::Reset (const Standard_Real theTimeElapsedSec) +{ + TimeStart = 0.0; + TimeCumul = theTimeElapsedSec; + OSD_Chronometer::Reset(); +} + //======================================================================= //function : Reset //purpose : diff --git a/src/OSD/OSD_Timer.hxx b/src/OSD/OSD_Timer.hxx index 3d6162ec27..5ff9e8a70e 100644 --- a/src/OSD/OSD_Timer.hxx +++ b/src/OSD/OSD_Timer.hxx @@ -44,11 +44,13 @@ public: DEFINE_STANDARD_ALLOC - //! Builds a Chronometer initialized and stopped. Standard_EXPORT OSD_Timer(); - - //! Stops and reinitializes the timer. + + //! Stops and reinitializes the timer with specified elapsed time. + Standard_EXPORT void Reset (const Standard_Real theTimeElapsedSec); + + //! Stops and reinitializes the timer with zero elapsed time. Standard_EXPORT virtual void Reset() Standard_OVERRIDE; //! Shows both the elapsed time and CPU time on the standard output @@ -74,29 +76,11 @@ public: //! Returns elapsed time in seconds. Standard_EXPORT Standard_Real ElapsedTime() const; - - - -protected: - - - - - private: - - Standard_Real TimeStart; Standard_Real TimeCumul; - }; - - - - - - #endif // _OSD_Timer_HeaderFile diff --git a/src/V3d/V3d_View.hxx b/src/V3d/V3d_View.hxx index 1e722508b4..9bed1e9d49 100644 --- a/src/V3d/V3d_View.hxx +++ b/src/V3d/V3d_View.hxx @@ -895,6 +895,9 @@ public: //! the camera approach. Standard_EXPORT const Handle(Graphic3d_Camera)& Camera() const; + //! Return default camera. + const Handle(Graphic3d_Camera)& DefaultCamera() const { return myDefaultCamera; } + //! Returns current rendering parameters and effect settings. //! By default it returns default parameters of current viewer. //! To define view-specific settings use method V3d_View::ChangeRenderingParams(). diff --git a/src/ViewerTest/ViewerTest.cxx b/src/ViewerTest/ViewerTest.cxx index 7eb042d6ac..c49692c2bc 100644 --- a/src/ViewerTest/ViewerTest.cxx +++ b/src/ViewerTest/ViewerTest.cxx @@ -303,7 +303,7 @@ Standard_Boolean ViewerTest::Display (const TCollection_AsciiString& theNa Handle(AIS_InteractiveObject) anOldObj = Handle(AIS_InteractiveObject)::DownCast (aMap.Find2 (theName)); if (!anOldObj.IsNull()) { - aCtx->Remove (anOldObj, Standard_True); + aCtx->Remove (anOldObj, theObject.IsNull() && theToUpdate); } aMap.UnBind2 (theName); } @@ -3973,125 +3973,6 @@ static int VPerf(Draw_Interpretor& di, Standard_Integer , const char** argv) { return 0; } - -//================================================================================== -// Function : VAnimation -//================================================================================== -static int VAnimation (Draw_Interpretor& di, Standard_Integer argc, const char** argv) { - if (argc != 5) { - di<<"Use: "<SetMutable (Standard_True); - myAisEngineBlock ->SetMutable (Standard_True); - myAisCrankArm ->SetMutable (Standard_True); - myAisPropeller ->SetMutable (Standard_True); - - TheAISContext()->SetColor (myAisCylinderHead, Quantity_NOC_INDIANRED); - TheAISContext()->SetColor (myAisEngineBlock, Quantity_NOC_RED); - TheAISContext()->SetColor (myAisPropeller, Quantity_NOC_GREEN); - - TheAISContext()->Display (myAisCylinderHead, Standard_False); - TheAISContext()->Display (myAisEngineBlock, Standard_False); - TheAISContext()->Display (myAisCrankArm, Standard_False); - TheAISContext()->Display (myAisPropeller, Standard_False); - - TheAISContext()->Deactivate(myAisCylinderHead); - TheAISContext()->Deactivate(myAisEngineBlock ); - TheAISContext()->Deactivate(myAisCrankArm ); - TheAISContext()->Deactivate(myAisPropeller ); - - // Boucle de mouvement - for (Standard_Real myAngle = 0;angleA<2*M_PI*10.175 ;myAngle++) { - - angleA = thread*myAngle*M_PI/180; - X = Sin(angleA)*3/8; - angleB = atan(X / Sqrt(-X * X + 1)); - Standard_Real decal(25*0.6); - - - //Build a transformation on the display - gp_Trsf aPropellerTrsf; - aPropellerTrsf.SetRotation(Ax1,angleA); - TheAISContext()->SetLocation(myAisPropeller,aPropellerTrsf); - - gp_Ax3 base(gp_Pnt(3*decal*(1-Cos(angleA)),-3*decal*Sin(angleA),0),gp_Vec(0,0,1),gp_Vec(1,0,0)); - gp_Trsf aCrankArmTrsf; - aCrankArmTrsf.SetTransformation( base.Rotated(gp_Ax1(gp_Pnt(3*decal,0,0),gp_Dir(0,0,1)),angleB)); - TheAISContext()->SetLocation(myAisCrankArm,aCrankArmTrsf); - - TheAISContext()->UpdateCurrentViewer(); - } - - TopoDS_Shape myNewCrankArm =myAisCrankArm ->Shape().Located( myAisCrankArm ->Transformation() ); - TopoDS_Shape myNewPropeller =myAisPropeller->Shape().Located( myAisPropeller->Transformation() ); - - myAisCrankArm ->ResetTransformation(); - myAisPropeller->ResetTransformation(); - - myAisCrankArm -> Set(myNewCrankArm ); - myAisPropeller -> Set(myNewPropeller); - - TheAISContext()->Activate(myAisCylinderHead,0); - TheAISContext()->Activate(myAisEngineBlock,0 ); - TheAISContext()->Activate(myAisCrankArm ,0 ); - TheAISContext()->Activate(myAisPropeller ,0 ); - - myTimer.Stop(); - myTimer.Show(); - myTimer.Start(); - - TheAISContext()->Redisplay(myAisCrankArm ,Standard_False); - TheAISContext()->Redisplay(myAisPropeller,Standard_False); - - TheAISContext()->UpdateCurrentViewer(); - a3DView()->Redraw(); - - myTimer.Stop(); - myTimer.Show(); - - return 0; - -} - //============================================================================== //function : VShading //purpose : Sharpen or roughten the quality of the shading @@ -5763,10 +5644,6 @@ void ViewerTest::Commands(Draw_Interpretor& theCommands) "\n\t\t: Tests the animation of an object along a predefined trajectory.", __FILE__,VPerf,group); - theCommands.Add("vanimation", - "vanimation CrankArmFile CylinderHeadFile PropellerFile EngineBlockFile", - __FILE__,VAnimation,group); - theCommands.Add("vsetshading", "vsetshading : vsetshading name Quality(default=0.0008) " "\n\t\t: Sets deflection coefficient that defines the quality of the shape representation in the shading mode.", diff --git a/src/ViewerTest/ViewerTest_AutoUpdater.cxx b/src/ViewerTest/ViewerTest_AutoUpdater.cxx index 2d6db65e3a..62307d44f9 100644 --- a/src/ViewerTest/ViewerTest_AutoUpdater.cxx +++ b/src/ViewerTest/ViewerTest_AutoUpdater.cxx @@ -70,8 +70,9 @@ Standard_Boolean ViewerTest_AutoUpdater::parseRedrawMode (const TCollection_Asci //======================================================================= void ViewerTest_AutoUpdater::Invalidate() { - myContext.Nullify(); - if (myWasAutoUpdate) + myToUpdate = ViewerTest_AutoUpdater::RedrawMode_Suppressed; + if (myWasAutoUpdate + && !myView.IsNull()) { myView->SetImmediateUpdate (myWasAutoUpdate); } @@ -83,16 +84,34 @@ void ViewerTest_AutoUpdater::Invalidate() //======================================================================= void ViewerTest_AutoUpdater::Update() { - if (myContext.IsNull()) + if (!myView.IsNull()) { - return; + myView->SetImmediateUpdate (myWasAutoUpdate); } - // update the screen and redraw the view - myView->SetImmediateUpdate (myWasAutoUpdate); - if ((myWasAutoUpdate && myToUpdate != ViewerTest_AutoUpdater::RedrawMode_Suppressed) - || myToUpdate == ViewerTest_AutoUpdater::RedrawMode_Forced) + switch (myToUpdate) { - myContext->UpdateCurrentViewer(); + case ViewerTest_AutoUpdater::RedrawMode_Suppressed: + { + return; + } + case ViewerTest_AutoUpdater::RedrawMode_Auto: + { + if (!myWasAutoUpdate) + { + return; + } + } + case ViewerTest_AutoUpdater::RedrawMode_Forced: + { + if (!myContext.IsNull()) + { + myContext->UpdateCurrentViewer(); + } + else if (!myView.IsNull()) + { + myView->Redraw(); + } + } } } diff --git a/src/ViewerTest/ViewerTest_ObjectCommands.cxx b/src/ViewerTest/ViewerTest_ObjectCommands.cxx index 15a7f9fcad..10e5dfdaa0 100644 --- a/src/ViewerTest/ViewerTest_ObjectCommands.cxx +++ b/src/ViewerTest/ViewerTest_ObjectCommands.cxx @@ -78,6 +78,7 @@ #include #include #include +#include #include #include @@ -2491,12 +2492,15 @@ static int VDrawText (Draw_Interpretor& theDI, Handle(AIS_TextLabel) aTextPrs; ViewerTest_AutoUpdater anAutoUpdater (aContext, ViewerTest::CurrentView()); + Standard_Boolean isNewPrs = Standard_False; if (GetMapOfAIS().IsBound2 (aName)) { - aTextPrs = Handle(AIS_TextLabel)::DownCast (GetMapOfAIS().Find2 (aName)); + aTextPrs = Handle(AIS_TextLabel)::DownCast (GetMapOfAIS().Find2 (aName)); } - else + + if (aTextPrs.IsNull()) { + isNewPrs = Standard_True; aTextPrs = new AIS_TextLabel(); aTextPrs->SetFont ("Courier"); } @@ -2851,7 +2855,15 @@ static int VDrawText (Draw_Interpretor& theDI, { aContext->SetTransformPersistence (aTextPrs, Handle(Graphic3d_TransformPers)()); } - ViewerTest::Display (aName, aTextPrs, Standard_False); + + if (isNewPrs) + { + ViewerTest::Display (aName, aTextPrs, Standard_False); + } + else + { + aContext->Redisplay (aTextPrs, Standard_False, Standard_True); + } return 0; } @@ -3699,12 +3711,47 @@ static int VDrawPArray (Draw_Interpretor& di, Standard_Integer argc, const char* return 0; } +namespace +{ + //! Auxiliary function for parsing translation vector - either 2D or 3D. + static Standard_Integer parseTranslationVec (Standard_Integer theArgNb, + const char** theArgVec, + gp_Vec& theVec) + { + if (theArgNb < 2) + { + return 0; + } + + TCollection_AsciiString anX (theArgVec[0]); + TCollection_AsciiString anY (theArgVec[1]); + if (!anX.IsRealValue() + || !anY.IsRealValue()) + { + return 0; + } + + theVec.SetX (anX.RealValue()); + theVec.SetY (anY.RealValue()); + if (theArgNb >= 3) + { + TCollection_AsciiString anZ (theArgVec[2]); + if (anZ.IsRealValue()) + { + theVec.SetZ (anZ.RealValue()); + return 3; + } + } + return 2; + } +} + //======================================================================= //function : VSetLocation //purpose : Change location of AIS interactive object //======================================================================= -static Standard_Integer VSetLocation (Draw_Interpretor& /*di*/, +static Standard_Integer VSetLocation (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec) { @@ -3716,36 +3763,301 @@ static Standard_Integer VSetLocation (Draw_Interpretor& /*di*/, return 1; } - TCollection_AsciiString aName; - gp_Vec aLocVec; - Standard_Boolean isSetLoc = Standard_False; - - Standard_Integer anArgIter = 1; - for (; anArgIter < theArgNb; ++anArgIter) + Standard_Boolean toPrintInfo = Standard_True; + Handle(AIS_InteractiveObject) anObj; + TCollection_AsciiString aCmdName (theArgVec[0]); + aCmdName.LowerCase(); + for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter) { - Standard_CString anArg = theArgVec[anArgIter]; - if (anUpdateTool.parseRedrawMode (theArgVec[anArgIter])) + TCollection_AsciiString anArg = theArgVec[anArgIter]; + anArg.LowerCase(); + if (anUpdateTool.parseRedrawMode (anArg)) { continue; } - else if (aName.IsEmpty()) + else if (anObj.IsNull()) { - aName = anArg; - } - else if (!isSetLoc) - { - isSetLoc = Standard_True; - if (anArgIter + 1 >= theArgNb) + const TCollection_AsciiString aName (theArgVec[anArgIter]); + const ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS(); + if (aMap.IsBound2 (aName)) { - std::cout << "Error: syntax error at '" << anArg << "'\n"; + anObj = Handle(AIS_InteractiveObject)::DownCast (aMap.Find2 (aName)); + } + if (anObj.IsNull()) + { + std::cout << "Error: object '" << aName << "' is not displayed!\n"; return 1; } - aLocVec.SetX (Draw::Atof (theArgVec[anArgIter++])); - aLocVec.SetY (Draw::Atof (theArgVec[anArgIter])); - if (anArgIter + 1 < theArgNb) + } + else if (anArg == "-reset") + { + toPrintInfo = Standard_False; + aContext->SetLocation (anObj, gp_Trsf()); + } + else if (anArg == "-copyfrom" + || anArg == "-copy") + { + if (anArgIter + 1 >= theArgNb) { - aLocVec.SetZ (Draw::Atof (theArgVec[++anArgIter])); + std::cout << "Syntax error at '" << anArg << "'\n"; + return 1; } + + const TCollection_AsciiString aName2 (theArgVec[anArgIter + 1]); + const ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS(); + Handle(AIS_InteractiveObject) anObj2; + if (aMap.IsBound2 (aName2)) + { + anObj2 = Handle(AIS_InteractiveObject)::DownCast (aMap.Find2 (aName2)); + } + if (anObj2.IsNull()) + { + std::cout << "Error: object '" << aName2 << "' is not displayed!\n"; + return 1; + } + + ++anArgIter; + aContext->SetLocation (anObj, anObj2->LocalTransformation()); + } + else if (anArg == "-rotate") + { + toPrintInfo = Standard_False; + if (anArgIter + 7 >= theArgNb) + { + std::cout << "Syntax error at '" << anArg << "'\n"; + return 1; + } + + gp_Trsf aTrsf; + aTrsf.SetRotation (gp_Ax1 (gp_Pnt (Draw::Atof (theArgVec[anArgIter + 1]), + Draw::Atof (theArgVec[anArgIter + 2]), + Draw::Atof (theArgVec[anArgIter + 3])), + gp_Vec (Draw::Atof (theArgVec[anArgIter + 4]), + Draw::Atof (theArgVec[anArgIter + 5]), + Draw::Atof (theArgVec[anArgIter + 6]))), + Draw::Atof (theArgVec[anArgIter + 7]) * (M_PI / 180.0)); + anArgIter += 7; + + aTrsf = anObj->LocalTransformation() * aTrsf; + aContext->SetLocation (anObj, aTrsf); + } + else if (anArg == "-translate") + { + toPrintInfo = Standard_False; + gp_Vec aLocVec; + Standard_Integer aNbParsed = parseTranslationVec (theArgNb - anArgIter - 1, theArgVec + anArgIter + 1, aLocVec); + anArgIter += aNbParsed; + if (aNbParsed == 0) + { + std::cout << "Syntax error at '" << anArg << "'\n"; + return 1; + } + + gp_Trsf aTrsf; + aTrsf.SetTranslationPart (aLocVec); + aTrsf = anObj->LocalTransformation() * aTrsf; + aContext->SetLocation (anObj, aTrsf); + } + else if (anArg == "-scale" + || anArg == "-setscale") + { + toPrintInfo = Standard_False; + gp_XYZ aScaleLoc; + Standard_Real aScale = 1.0; + Standard_Boolean toPrintScale = Standard_True; + Standard_Boolean hasScaleLoc = Standard_False; + if (anArgIter + 4 < theArgNb) + { + TCollection_AsciiString aScaleArgs[4] = + { + TCollection_AsciiString (theArgVec[anArgIter + 1]), + TCollection_AsciiString (theArgVec[anArgIter + 2]), + TCollection_AsciiString (theArgVec[anArgIter + 3]), + TCollection_AsciiString (theArgVec[anArgIter + 4]) + }; + Standard_Integer aScaleArgIter = 0; + for (; aScaleArgIter < 4; ++aScaleArgIter) + { + if (!aScaleArgs[aScaleArgIter].IsRealValue()) + { + break; + } + } + if (aScaleArgIter == 4) + { + aScaleLoc.SetCoord (aScaleArgs[0].RealValue(), aScaleArgs[1].RealValue(), aScaleArgs[2].RealValue()); + aScale = aScaleArgs[3].RealValue(); + anArgIter += 4; + toPrintScale = Standard_False; + hasScaleLoc = Standard_True; + } + else if (aScaleArgIter >= 1) + { + aScale = aScaleArgs[0].RealValue(); + ++anArgIter; + toPrintScale = Standard_False; + } + } + else if (anArgIter + 1 < theArgNb) + { + TCollection_AsciiString aScaleArg (theArgVec[anArgIter + 1]); + if (aScaleArg.IsRealValue()) + { + aScale = aScaleArg.RealValue(); + ++anArgIter; + toPrintScale = Standard_False; + } + } + + if (toPrintScale) + { + if (anArg == "-setscale") + { + std::cout << "Syntax error at '" << anArg << "'\n"; + return 1; + } + + char aText[1024]; + Sprintf (aText, "%g ", anObj->LocalTransformation().ScaleFactor()); + theDI << aText; + continue; + } + + if (anArg == "-setscale") + { + gp_Trsf aTrsf = anObj->LocalTransformation(); + if (hasScaleLoc) + { + aTrsf.SetScale (aScaleLoc, aScale); + } + else + { + aTrsf.SetScaleFactor (aScale); + } + aContext->SetLocation (anObj, aTrsf); + } + else + { + gp_Trsf aTrsf; + if (hasScaleLoc) + { + aTrsf.SetScale (aScaleLoc, aScale); + aTrsf = anObj->LocalTransformation() * aTrsf; + } + else + { + aTrsf = anObj->LocalTransformation(); + aTrsf.SetScaleFactor (aTrsf.ScaleFactor() * aScale); + } + aContext->SetLocation (anObj, aTrsf); + } + } + else if (anArg == "-mirror") + { + toPrintInfo = Standard_False; + if (anArgIter + 6 >= theArgNb) + { + std::cout << "Syntax error at '" << anArg << "'\n"; + return 1; + } + + gp_Trsf aTrsf; + aTrsf.SetMirror (gp_Ax2 (gp_Pnt (Draw::Atof(theArgVec[theArgNb - 6]), + Draw::Atof(theArgVec[theArgNb - 5]), + Draw::Atof(theArgVec[theArgNb - 4])), + gp_Vec (Draw::Atof(theArgVec[theArgNb - 3]), + Draw::Atof(theArgVec[theArgNb - 2]), + Draw::Atof(theArgVec[theArgNb - 1])))); + anArgIter += 6; + aTrsf = anObj->LocalTransformation() * aTrsf; + aContext->SetLocation (anObj, aTrsf); + } + else if (anArg == "-setrotation" + || anArg == "-rotation") + { + toPrintInfo = Standard_False; + if (anArgIter + 4 < theArgNb) + { + TCollection_AsciiString aQuatArgs[4] = + { + TCollection_AsciiString (theArgVec[anArgIter + 1]), + TCollection_AsciiString (theArgVec[anArgIter + 2]), + TCollection_AsciiString (theArgVec[anArgIter + 3]), + TCollection_AsciiString (theArgVec[anArgIter + 4]) + }; + Standard_Integer aQuatArgIter = 0; + for (; aQuatArgIter < 4; ++aQuatArgIter) + { + if (!aQuatArgs[aQuatArgIter].IsRealValue()) + { + break; + } + } + + if (aQuatArgIter == 4) + { + anArgIter += 4; + const gp_Quaternion aQuat (aQuatArgs[0].RealValue(), + aQuatArgs[1].RealValue(), + aQuatArgs[2].RealValue(), + aQuatArgs[3].RealValue()); + gp_Trsf aTrsf = anObj->LocalTransformation(); + aTrsf.SetRotation (aQuat); + aContext->SetLocation (anObj, aTrsf); + continue; + } + else if (anArg == "-setrotation") + { + std::cout << "Syntax error at '" << anArg << "'\n"; + return 1; + } + } + + char aText[1024]; + const gp_Quaternion aQuat = anObj->LocalTransformation().GetRotation(); + Sprintf (aText, "%g %g %g %g ", aQuat.X(), aQuat.Y(), aQuat.Z(), aQuat.W()); + theDI << aText; + } + else if (anArg == "-setlocation" + || anArg == "-location") + { + toPrintInfo = Standard_False; + gp_Vec aLocVec; + Standard_Integer aNbParsed = parseTranslationVec (theArgNb - anArgIter - 1, theArgVec + anArgIter + 1, aLocVec); + anArgIter += aNbParsed; + if (aNbParsed != 0) + { + gp_Trsf aTrsf = anObj->LocalTransformation(); + aTrsf.SetTranslationPart (aLocVec); + aContext->SetLocation (anObj, aTrsf); + } + else if (anArg == "-setlocation") + { + std::cout << "Syntax error at '" << anArg << "'\n"; + return 1; + } + + char aText[1024]; + const gp_XYZ aLoc = anObj->LocalTransformation().TranslationPart(); + Sprintf (aText, "%g %g %g ", aLoc.X(), aLoc.Y(), aLoc.Z()); + theDI << aText; + } + else if (aCmdName == "vsetlocation") + { + // compatibility with old syntax + gp_Vec aLocVec; + Standard_Integer aNbParsed = parseTranslationVec (theArgNb - anArgIter, theArgVec + anArgIter, aLocVec); + if (aNbParsed == 0) + { + std::cout << "Syntax error at '" << anArg << "'\n"; + return 1; + } + anArgIter = anArgIter + aNbParsed - 1; + + gp_Trsf aTrsf; + aTrsf.SetTranslationPart (aLocVec); + aContext->SetLocation (anObj, aTrsf); + toPrintInfo = Standard_False; } else { @@ -3754,183 +4066,27 @@ static Standard_Integer VSetLocation (Draw_Interpretor& /*di*/, } } - // find object - const ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS(); - Handle(AIS_InteractiveObject) anIObj; - if (aMap.IsBound2 (aName)) + if (anObj.IsNull()) { - anIObj = Handle(AIS_InteractiveObject)::DownCast (aMap.Find2 (aName)); - } - if (anIObj.IsNull()) - { - std::cout << "Error: object '" << aName << "' is not displayed!\n"; + std::cout << "Syntax error - wrong number of arguments\n"; return 1; } - - gp_Trsf aTrsf; - aTrsf.SetTranslation (aLocVec); - TopLoc_Location aLocation (aTrsf); - aContext->SetLocation (anIObj, aLocation); - return 0; -} - -//======================================================================= -//function : TransformPresentation -//purpose : Change transformation of AIS interactive object -//======================================================================= -static Standard_Integer LocalTransformPresentation (Draw_Interpretor& /*theDi*/, - Standard_Integer theArgNb, - const char** theArgVec) -{ - if (theArgNb <= 1) + else if (!toPrintInfo) { - std::cout << "Error: too few arguments.\n"; - return 1; - } - - Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext(); - ViewerTest_AutoUpdater anUpdateTool(aContext, ViewerTest::CurrentView()); - if (aContext.IsNull()) - { - std::cout << "Error: no active view!\n"; - return 1; - } - - gp_Trsf aTrsf; - Standard_Integer aLast = theArgNb; - const char* aName = theArgVec[0]; - - Standard_Boolean isReset = Standard_False; - Standard_Boolean isMove = Standard_False; - - // Prefix 'vloc' - aName += 4; - - if (!strcmp (aName, "reset")) - { - isReset = Standard_True; - } - else if (!strcmp (aName, "move")) - { - if (theArgNb < 3) - { - std::cout << "Error: too few arguments.\n"; - return 1; - } - - const ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS(); - - Handle(AIS_InteractiveObject) anIObj; - if (aMap.IsBound2 (theArgVec[theArgNb - 1])) - { - anIObj = Handle(AIS_InteractiveObject)::DownCast (aMap.Find2 (theArgVec[theArgNb - 1])); - } - - if (anIObj.IsNull()) - { - std::cout << "Error: object '" << theArgVec[theArgNb - 1] << "' is not displayed!\n"; - return 1; - } - - isMove = Standard_True; - - aTrsf = anIObj->Transformation(); - aLast = theArgNb - 1; - } - else if (!strcmp (aName, "translate")) - { - if (theArgNb < 5) - { - std::cout << "Error: too few arguments.\n"; - return 1; - } - aTrsf.SetTranslation (gp_Vec (Draw::Atof (theArgVec[theArgNb - 3]), - Draw::Atof (theArgVec[theArgNb - 2]), - Draw::Atof (theArgVec[theArgNb - 1]))); - aLast = theArgNb - 3; - } - else if (!strcmp (aName, "rotate")) - { - if (theArgNb < 9) - { - std::cout << "Error: too few arguments.\n"; - return 1; - } - - aTrsf.SetRotation ( - gp_Ax1 (gp_Pnt (Draw::Atof (theArgVec[theArgNb - 7]), - Draw::Atof (theArgVec[theArgNb - 6]), - Draw::Atof (theArgVec[theArgNb - 5])), - gp_Vec (Draw::Atof (theArgVec[theArgNb - 4]), - Draw::Atof (theArgVec[theArgNb - 3]), - Draw::Atof (theArgVec[theArgNb - 2]))), - Draw::Atof (theArgVec[theArgNb - 1]) * (M_PI / 180.0)); - - aLast = theArgNb - 7; - } - else if (!strcmp (aName, "mirror")) - { - if (theArgNb < 8) - { - std::cout << "Error: too few arguments.\n"; - return 1; - } - - aTrsf.SetMirror (gp_Ax2 (gp_Pnt (Draw::Atof(theArgVec[theArgNb - 6]), - Draw::Atof(theArgVec[theArgNb - 5]), - Draw::Atof(theArgVec[theArgNb - 4])), - gp_Vec (Draw::Atof(theArgVec[theArgNb - 3]), - Draw::Atof(theArgVec[theArgNb - 2]), - Draw::Atof(theArgVec[theArgNb - 1])))); - aLast = theArgNb - 6; - } - else if (!strcmp (aName, "scale")) - { - if (theArgNb < 6) - { - std::cout << "Error: too few arguments.\n"; - return 1; - } - - aTrsf.SetScale (gp_Pnt (Draw::Atof(theArgVec[theArgNb - 4]), - Draw::Atof(theArgVec[theArgNb - 3]), - Draw::Atof(theArgVec[theArgNb - 2])), - Draw::Atof(theArgVec[theArgNb - 1])); - aLast = theArgNb - 4; - } - - for (Standard_Integer anIdx = 1; anIdx < aLast; anIdx++) - { - // find object - const ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS(); - Handle(AIS_InteractiveObject) anIObj; - if (aMap.IsBound2 (theArgVec[anIdx])) - { - anIObj = Handle(AIS_InteractiveObject)::DownCast (aMap.Find2 (theArgVec[anIdx])); - } - if (anIObj.IsNull()) - { - std::cout << "Error: object '" << theArgVec[anIdx] << "' is not displayed!\n"; - return 1; - } - - if (isReset) - { - // aTrsf already identity - } - else if (isMove) - { - aTrsf = anIObj->LocalTransformation() * anIObj->Transformation().Inverted() * aTrsf; - } - else - { - aTrsf = anIObj->LocalTransformation() * aTrsf; - } - - TopLoc_Location aLocation (aTrsf); - aContext->SetLocation (anIObj, aLocation); + return 0; } + const gp_Trsf aTrsf = anObj->LocalTransformation(); + const gp_XYZ aLoc = aTrsf.TranslationPart(); + const gp_Quaternion aRot = aTrsf.GetRotation(); + char aText[4096]; + Sprintf (aText, "Location: %g %g %g\n" + "Rotation: %g %g %g %g\n" + "Scale: %g\n", + aLoc.X(), aLoc.Y(), aLoc.Z(), + aRot.X(), aRot.Y(), aRot.Z(), aRot.W(), + aTrsf.ScaleFactor()); + theDI << aText; return 0; } @@ -6411,9 +6567,29 @@ void ViewerTest::ObjectCommands(Draw_Interpretor& theCommands) "vdrawsphere: vdrawsphere shapeName Fineness [X=0.0 Y=0.0 Z=0.0] [Radius=100.0] [ToShowEdges=0] [ToPrintInfo=1]\n", __FILE__,VDrawSphere,group); + theCommands.Add ("vlocation", + "vlocation name" + "\n\t\t: [-reset]" + "\n\t\t: [-copyFrom otherName]" + "\n\t\t: [-translate X Y [Z]]" + "\n\t\t: [-rotate x y z dx dy dz angle]" + "\n\t\t: [-scale [X Y Z] scale]" + "\n\t\t: [-mirror x y z dx dy dz]" + "\n\t\t: [-setLocation X Y [Z]]" + "\n\t\t: [-setRotation QX QY QZ QW]" + "\n\t\t: [-setScale [X Y Z] scale]" + "\n\t\t: Object local transformation management:" + "\n\t\t: -reset reset transformation to identity" + "\n\t\t: -translate translate object" + "\n\t\t: -rotate applies rotation to local transformation" + "\n\t\t: -scale applies scale to local transformation" + "\n\t\t: -mirror applies mirror to local transformation" + "\n\t\t: -setLocation assign object location" + "\n\t\t: -setRotation assign object rotation (quaternion)" + "\n\t\t: -setScale assign object scale factor", + __FILE__, VSetLocation, group); theCommands.Add ("vsetlocation", - "vsetlocation [-noupdate|-update] name x y z" - "\n\t\t: Set new location for an interactive object.", + "alias for vlocation", __FILE__, VSetLocation, group); theCommands.Add ( @@ -6562,36 +6738,6 @@ void ViewerTest::ObjectCommands(Draw_Interpretor& theCommands) "\n", __FILE__, VPointCloud, group); - theCommands.Add("vlocreset", - "vlocreset name1 name2 ...\n\t\t remove object local transformation", - __FILE__, - LocalTransformPresentation, group); - - theCommands.Add("vlocmove", - "vlocmove name1 name2 ... name\n\t\t set local transform to match transform of 'name'", - __FILE__, - LocalTransformPresentation, group); - - theCommands.Add("vloctranslate", - "vloctranslate name1 name2 ... dx dy dz\n\t\t applies translation to local transformation", - __FILE__, - LocalTransformPresentation, group); - - theCommands.Add("vlocrotate", - "vlocrotate name1 name2 ... x y z dx dy dz angle\n\t\t applies rotation to local transformation", - __FILE__, - LocalTransformPresentation, group); - - theCommands.Add("vlocmirror", - "vlocmirror name x y z dx dy dz\n\t\t applies mirror to local transformation", - __FILE__, - LocalTransformPresentation, group); - - theCommands.Add("vlocscale", - "vlocscale name x y z scale\n\t\t applies scale to local transformation", - __FILE__, - LocalTransformPresentation, group); - theCommands.Add("vpriority", "vpriority [-noupdate|-update] name [value]\n\t\t prints or sets the display priority for an object", __FILE__, diff --git a/src/ViewerTest/ViewerTest_ViewerCommands.cxx b/src/ViewerTest/ViewerTest_ViewerCommands.cxx index d1dca89bed..df8b73f284 100644 --- a/src/ViewerTest/ViewerTest_ViewerCommands.cxx +++ b/src/ViewerTest/ViewerTest_ViewerCommands.cxx @@ -15,6 +15,10 @@ // commercial license or contractual agreement. #include + +#include +#include +#include #include #include #include @@ -187,6 +191,7 @@ int X_ButtonPress = 0; // Last ButtonPress position int Y_ButtonPress = 0; Standard_Boolean IsDragged = Standard_False; Standard_Boolean DragFirst = Standard_False; +Standard_Boolean TheIsAnimating = Standard_False; Standard_EXPORT const Handle(AIS_RubberBand)& GetRubberBand() @@ -1569,6 +1574,12 @@ Standard_Boolean VT_ProcessButton1Press (Standard_Integer , Standard_Boolean theToPick, Standard_Boolean theIsShift) { + if (TheIsAnimating) + { + TheIsAnimating = Standard_False; + return Standard_False; + } + if (theToPick) { Standard_Real X, Y, Z; @@ -2497,33 +2508,42 @@ static void OSWindowSetup() //============================================================================== //function : VFit - -//purpose : Fitall, no DRAW arguments -//Draw arg : No args +//purpose : //============================================================================== -static int VFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgc, const char** theArgv) +static int VFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgv) { - if (theArgc > 2) + const Handle(V3d_View) aView = ViewerTest::CurrentView(); + if (aView.IsNull()) { - std::cout << "Wrong number of arguments! Use: vfit [-selected]" << std::endl; + std::cout << "Error: no active viewer!\n"; + return 1; } - const Handle(V3d_View) aView = ViewerTest::CurrentView(); - - if (theArgc == 2) + Standard_Boolean toFit = Standard_True; + ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView); + for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter) { - TCollection_AsciiString anArg (theArgv[1]); + TCollection_AsciiString anArg (theArgv[anArgIter]); anArg.LowerCase(); - if (anArg == "-selected") + if (anUpdateTool.parseRedrawMode (anArg)) { - ViewerTest::GetAISContext()->FitSelected (aView); - return 0; + continue; + } + else if (anArg == "-selected") + { + ViewerTest::GetAISContext()->FitSelected (aView, 0.01, Standard_False); + toFit = Standard_False; + } + else + { + std::cout << "Syntax error at '" << anArg << "'\n"; } } - if (aView.IsNull() == Standard_False) { - aView->FitAll(); + if (toFit) + { + aView->FitAll (0.01, Standard_False); } return 0; } @@ -5981,206 +6001,908 @@ static Standard_Integer VMoveTo (Draw_Interpretor& di, return 0; } +namespace +{ + //! Global map storing all animations registered in ViewerTest. + static NCollection_DataMap ViewerTest_AnimationTimelineMap; + + //! The animation calling the Draw Harness command. + class ViewerTest_AnimationProc : public AIS_Animation + { + public: + + //! Main constructor. + ViewerTest_AnimationProc (const TCollection_AsciiString& theAnimationName, + Draw_Interpretor* theDI, + const TCollection_AsciiString& theCommand) + : AIS_Animation (theAnimationName), + myDrawInter(theDI), + myCommand (theCommand) + { + // + } + + protected: + + //! Evaluate the command. + virtual void update (const AIS_AnimationProgress& theProgress) Standard_OVERRIDE + { + TCollection_AsciiString aCmd = myCommand; + replace (aCmd, "%pts", TCollection_AsciiString(theProgress.Pts)); + replace (aCmd, "%localpts", TCollection_AsciiString(theProgress.LocalPts)); + replace (aCmd, "%ptslocal", TCollection_AsciiString(theProgress.LocalPts)); + replace (aCmd, "%normalized", TCollection_AsciiString(theProgress.LocalNormalized)); + replace (aCmd, "%localnormalized", TCollection_AsciiString(theProgress.LocalNormalized)); + myDrawInter->Eval (aCmd.ToCString()); + } + + //! Find the keyword in the command and replace it with value. + //! @return the position of the keyword to pass value + void replace (TCollection_AsciiString& theCmd, + const TCollection_AsciiString& theKey, + const TCollection_AsciiString& theVal) + { + TCollection_AsciiString aCmd (theCmd); + aCmd.LowerCase(); + const Standard_Integer aPos = aCmd.Search (theKey); + if (aPos == -1) + { + return; + } + + TCollection_AsciiString aPart1, aPart2; + Standard_Integer aPart1To = aPos - 1; + if (aPart1To >= 1 + && aPart1To <= theCmd.Length()) + { + aPart1 = theCmd.SubString (1, aPart1To); + } + + Standard_Integer aPart2From = aPos + theKey.Length(); + if (aPart2From >= 1 + && aPart2From <= theCmd.Length()) + { + aPart2 = theCmd.SubString (aPart2From, theCmd.Length()); + } + + theCmd = aPart1 + theVal + aPart2; + } + + protected: + + Draw_Interpretor* myDrawInter; + TCollection_AsciiString myCommand; + + }; + + //! Replace the animation with the new one. + static void replaceAnimation (const Handle(AIS_Animation)& theParentAnimation, + Handle(AIS_Animation)& theAnimation, + const Handle(AIS_Animation)& theAnimationNew) + { + theAnimationNew->CopyFrom (theAnimation); + if (!theParentAnimation.IsNull()) + { + theParentAnimation->Replace (theAnimation, theAnimationNew); + } + else + { + ViewerTest_AnimationTimelineMap.UnBind (theAnimationNew->Name()); + ViewerTest_AnimationTimelineMap.Bind (theAnimationNew->Name(), theAnimationNew); + } + theAnimation = theAnimationNew; + } + + //! Parse the point. + static Standard_Boolean parseXYZ (const char** theArgVec, gp_XYZ& thePnt) + { + const TCollection_AsciiString anXYZ[3] = { theArgVec[0], theArgVec[1], theArgVec[2] }; + if (!anXYZ[0].IsRealValue() + || !anXYZ[1].IsRealValue() + || !anXYZ[2].IsRealValue()) + { + return Standard_False; + } + + thePnt.SetCoord (anXYZ[0].RealValue(), anXYZ[1].RealValue(), anXYZ[2].RealValue()); + return Standard_True; + } + + //! Parse the quaternion. + static Standard_Boolean parseQuaternion (const char** theArgVec, gp_Quaternion& theQRot) + { + const TCollection_AsciiString anXYZW[4] = {theArgVec[0], theArgVec[1], theArgVec[2], theArgVec[3]}; + if (!anXYZW[0].IsRealValue() + || !anXYZW[1].IsRealValue() + || !anXYZW[2].IsRealValue() + || !anXYZW[3].IsRealValue()) + { + return Standard_False; + } + + theQRot.Set (anXYZW[0].RealValue(), anXYZW[1].RealValue(), anXYZW[2].RealValue(), anXYZW[3].RealValue()); + return Standard_True; + } + +} + //================================================================================================= //function : VViewParams //purpose : Gets or sets AIS View characteristics //================================================================================================= static int VViewParams (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec) { - Handle(V3d_View) anAISView = ViewerTest::CurrentView(); - if (anAISView.IsNull()) + Handle(V3d_View) aView = ViewerTest::CurrentView(); + if (aView.IsNull()) { std::cout << theArgVec[0] << ": please initialize or activate view.\n"; return 1; } + Standard_Boolean toSetProj = Standard_False; + Standard_Boolean toSetUp = Standard_False; + Standard_Boolean toSetAt = Standard_False; + Standard_Boolean toSetEye = Standard_False; + Standard_Boolean toSetScale = Standard_False; + Standard_Boolean toSetSize = Standard_False; + Standard_Boolean toSetCenter2d = Standard_False; + Quantity_Factor aViewScale = aView->Scale(); + Quantity_Length aViewSize = 1.0; + Graphic3d_Vec2i aCenter2d; + gp_XYZ aViewProj, aViewUp, aViewAt, aViewEye; + aView->Proj (aViewProj.ChangeCoord (1), aViewProj.ChangeCoord (2), aViewProj.ChangeCoord (3)); + aView->Up (aViewUp .ChangeCoord (1), aViewUp .ChangeCoord (2), aViewUp .ChangeCoord (3)); + aView->At (aViewAt .ChangeCoord (1), aViewAt .ChangeCoord (2), aViewAt .ChangeCoord (3)); + aView->Eye (aViewEye .ChangeCoord (1), aViewEye .ChangeCoord (2), aViewEye .ChangeCoord (3)); if (theArgsNb == 1) { // print all of the available view parameters - Quantity_Factor anAISViewScale = anAISView->Scale(); - - Standard_Real anAISViewProjX = 0.0; - Standard_Real anAISViewProjY = 0.0; - Standard_Real anAISViewProjZ = 0.0; - anAISView->Proj (anAISViewProjX, anAISViewProjY, anAISViewProjZ); - - Standard_Real anAISViewUpX = 0.0; - Standard_Real anAISViewUpY = 0.0; - Standard_Real anAISViewUpZ = 0.0; - anAISView->Up (anAISViewUpX, anAISViewUpY, anAISViewUpZ); - - Standard_Real anAISViewAtX = 0.0; - Standard_Real anAISViewAtY = 0.0; - Standard_Real anAISViewAtZ = 0.0; - anAISView->At (anAISViewAtX, anAISViewAtY, anAISViewAtZ); - - Standard_Real anAISViewEyeX = 0.0; - Standard_Real anAISViewEyeY = 0.0; - Standard_Real anAISViewEyeZ = 0.0; - anAISView->Eye (anAISViewEyeX, anAISViewEyeY, anAISViewEyeZ); - - theDi << "Scale of current view: " << anAISViewScale << "\n"; - theDi << "Proj on X : " << anAISViewProjX << "; on Y: " << anAISViewProjY << "; on Z: " << anAISViewProjZ << "\n"; - theDi << "Up on X : " << anAISViewUpX << "; on Y: " << anAISViewUpY << "; on Z: " << anAISViewUpZ << "\n"; - theDi << "At on X : " << anAISViewAtX << "; on Y: " << anAISViewAtY << "; on Z: " << anAISViewAtZ << "\n"; - theDi << "Eye on X : " << anAISViewEyeX << "; on Y: " << anAISViewEyeY << "; on Z: " << anAISViewEyeZ << "\n"; + char aText[4096]; + Sprintf (aText, + "Scale: %g\n" + "Proj: %12g %12g %12g\n" + "Up: %12g %12g %12g\n" + "At: %12g %12g %12g\n" + "Eye: %12g %12g %12g\n", + aViewScale, + aViewProj.X(), aViewProj.Y(), aViewProj.Z(), + aViewUp.X(), aViewUp.Y(), aViewUp.Z(), + aViewAt.X(), aViewAt.Y(), aViewAt.Z(), + aViewEye.X(), aViewEye.Y(), aViewEye.Z()); + theDi << aText; return 0; } - // ------------------------- - // Parse options and values - // ------------------------- - - NCollection_DataMap aMapOfKeysByValues; - TCollection_AsciiString aParseKey; - for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt) + ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView); + for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter) { - TCollection_AsciiString anArg (theArgVec [anArgIt]); - - if (anArg.Value (1) == '-' && !anArg.IsRealValue()) + TCollection_AsciiString anArg (theArgVec[anArgIter]); + anArg.LowerCase(); + if (anUpdateTool.parseRedrawMode (anArg)) { - aParseKey = anArg; - aParseKey.Remove (1); - aParseKey.UpperCase(); - aMapOfKeysByValues.Bind (aParseKey, new TColStd_HSequenceOfAsciiString); continue; } - - if (aParseKey.IsEmpty()) + else if (anArg == "-cmd" + || anArg == "-command" + || anArg == "-args") { - std::cout << theArgVec[0] << ": values should be passed with key.\n"; - std::cout << "Type help for more information.\n"; - return 1; + char aText[4096]; + Sprintf (aText, + "-scale %g " + "-proj %g %g %g " + "-up %g %g %g " + "-at %g %g %g\n", + aViewScale, + aViewProj.X(), aViewProj.Y(), aViewProj.Z(), + aViewUp.X(), aViewUp.Y(), aViewUp.Z(), + aViewAt.X(), aViewAt.Y(), aViewAt.Z()); + theDi << aText; } - - aMapOfKeysByValues(aParseKey)->Append (anArg); - } - - // --------------------------------------------- - // Change or print parameters, order plays role - // --------------------------------------------- - - // Check arguments for validity - NCollection_DataMap::Iterator aMapIt (aMapOfKeysByValues); - for (; aMapIt.More(); aMapIt.Next()) - { - const TCollection_AsciiString& aKey = aMapIt.Key(); - const Handle(TColStd_HSequenceOfAsciiString)& aValues = aMapIt.Value(); - - if (!(aKey.IsEqual ("SCALE") && (aValues->Length() == 1 || aValues->IsEmpty())) - && !(aKey.IsEqual ("SIZE") && (aValues->Length() == 1 || aValues->IsEmpty())) - && !(aKey.IsEqual ("EYE") && (aValues->Length() == 3 || aValues->IsEmpty())) - && !(aKey.IsEqual ("AT") && (aValues->Length() == 3 || aValues->IsEmpty())) - && !(aKey.IsEqual ("UP") && (aValues->Length() == 3 || aValues->IsEmpty())) - && !(aKey.IsEqual ("PROJ") && (aValues->Length() == 3 || aValues->IsEmpty())) - && !(aKey.IsEqual ("CENTER") && aValues->Length() == 2)) + else if (anArg == "-scale" + || anArg == "-size") { - TCollection_AsciiString aLowerKey; - aLowerKey = "-"; - aLowerKey += aKey; - aLowerKey.LowerCase(); - std::cout << theArgVec[0] << ": " << aLowerKey << " is unknown option, or number of arguments is invalid.\n"; - std::cout << "Type help for more information.\n"; + if (anArgIter + 1 < theArgsNb + && *theArgVec[anArgIter + 1] != '-') + { + const TCollection_AsciiString aValueArg (theArgVec[anArgIter + 1]); + if (aValueArg.IsRealValue()) + { + ++anArgIter; + if (anArg == "-scale") + { + toSetScale = Standard_True; + aViewScale = aValueArg.RealValue(); + } + else if (anArg == "-size") + { + toSetSize = Standard_True; + aViewSize = aValueArg.RealValue(); + } + continue; + } + } + if (anArg == "-scale") + { + theDi << "Scale: " << aView->Scale() << "\n"; + } + else if (anArg == "-size") + { + Graphic3d_Vec2d aSizeXY; + aView->Size (aSizeXY.x(), aSizeXY.y()); + theDi << "Size: " << aSizeXY.x() << " " << aSizeXY.y() << "\n"; + } + } + else if (anArg == "-eye" + || anArg == "-at" + || anArg == "-up" + || anArg == "-proj") + { + if (anArgIter + 3 < theArgsNb) + { + gp_XYZ anXYZ; + if (parseXYZ (theArgVec + anArgIter + 1, anXYZ)) + { + anArgIter += 3; + if (anArg == "-eye") + { + toSetEye = Standard_True; + aViewEye = anXYZ; + } + else if (anArg == "-at") + { + toSetAt = Standard_True; + aViewAt = anXYZ; + } + else if (anArg == "-up") + { + toSetUp = Standard_True; + aViewUp = anXYZ; + } + else if (anArg == "-proj") + { + toSetProj = Standard_True; + aViewProj = anXYZ; + } + continue; + } + } + + if (anArg == "-eye") + { + theDi << "Eye: " << aViewEye.X() << " " << aViewEye.Y() << " " << aViewEye.Z() << "\n"; + } + else if (anArg == "-at") + { + theDi << "At: " << aViewAt.X() << " " << aViewAt.Y() << " " << aViewAt.Z() << "\n"; + } + else if (anArg == "-up") + { + theDi << "Up: " << aViewUp.X() << " " << aViewUp.Y() << " " << aViewUp.Z() << "\n"; + } + else if (anArg == "-proj") + { + theDi << "Proj: " << aViewProj.X() << " " << aViewProj.Y() << " " << aViewProj.Z() << "\n"; + } + } + else if (anArg == "-center") + { + if (anArgIter + 2 < theArgsNb) + { + const TCollection_AsciiString anX (theArgVec[anArgIter + 1]); + const TCollection_AsciiString anY (theArgVec[anArgIter + 2]); + if (anX.IsIntegerValue() + && anY.IsIntegerValue()) + { + toSetCenter2d = Standard_True; + aCenter2d = Graphic3d_Vec2i (anX.IntegerValue(), anY.IntegerValue()); + } + } + } + else + { + std::cout << "Syntax error at '" << anArg << "'\n"; return 1; } } - Handle(TColStd_HSequenceOfAsciiString) aValues; - - // Change view parameters in proper order - if (aMapOfKeysByValues.Find ("SCALE", aValues)) + // change view parameters in proper order + if (toSetScale) { - if (aValues->IsEmpty()) - { - theDi << "Scale: " << anAISView->Scale() << "\n"; - } - else - { - anAISView->SetScale (aValues->Value(1).RealValue()); - } + aView->SetScale (aViewScale); } - if (aMapOfKeysByValues.Find ("SIZE", aValues)) + if (toSetSize) { - if (aValues->IsEmpty()) - { - Standard_Real aSizeX = 0.0; - Standard_Real aSizeY = 0.0; - anAISView->Size (aSizeX, aSizeY); - theDi << "Size X: " << aSizeX << " Y: " << aSizeY << "\n"; - } - else - { - anAISView->SetSize (aValues->Value(1).RealValue()); - } + aView->SetSize (aViewSize); } - if (aMapOfKeysByValues.Find ("EYE", aValues)) + if (toSetEye) { - if (aValues->IsEmpty()) - { - Standard_Real anEyeX = 0.0; - Standard_Real anEyeY = 0.0; - Standard_Real anEyeZ = 0.0; - anAISView->Eye (anEyeX, anEyeY, anEyeZ); - theDi << "Eye X: " << anEyeX << " Y: " << anEyeY << " Z: " << anEyeZ << "\n"; - } - else - { - anAISView->SetEye (aValues->Value(1).RealValue(), aValues->Value(2).RealValue(), aValues->Value(3).RealValue()); - } + aView->SetEye (aViewEye.X(), aViewEye.Y(), aViewEye.Z()); } - if (aMapOfKeysByValues.Find ("AT", aValues)) + if (toSetAt) { - if (aValues->IsEmpty()) - { - Standard_Real anAtX = 0.0; - Standard_Real anAtY = 0.0; - Standard_Real anAtZ = 0.0; - anAISView->At (anAtX, anAtY, anAtZ); - theDi << "At X: " << anAtX << " Y: " << anAtY << " Z: " << anAtZ << "\n"; - } - else - { - anAISView->SetAt (aValues->Value(1).RealValue(), aValues->Value(2).RealValue(), aValues->Value(3).RealValue()); - } + aView->SetAt (aViewAt.X(), aViewAt.Y(), aViewAt.Z()); } - if (aMapOfKeysByValues.Find ("PROJ", aValues)) + if (toSetProj) { - if (aValues->IsEmpty()) - { - Standard_Real aProjX = 0.0; - Standard_Real aProjY = 0.0; - Standard_Real aProjZ = 0.0; - anAISView->Proj (aProjX, aProjY, aProjZ); - theDi << "Proj X: " << aProjX << " Y: " << aProjY << " Z: " << aProjZ << "\n"; - } - else - { - anAISView->SetProj (aValues->Value(1).RealValue(), aValues->Value(2).RealValue(), aValues->Value(3).RealValue()); - } + aView->SetProj (aViewProj.X(), aViewProj.Y(), aViewProj.Z()); } - if (aMapOfKeysByValues.Find ("UP", aValues)) + if (toSetUp) { - if (aValues->IsEmpty()) - { - Standard_Real anUpX = 0.0; - Standard_Real anUpY = 0.0; - Standard_Real anUpZ = 0.0; - anAISView->Up (anUpX, anUpY, anUpZ); - theDi << "Up X: " << anUpX << " Y: " << anUpY << " Z: " << anUpZ << "\n"; - } - else - { - anAISView->SetUp (aValues->Value(1).RealValue(), aValues->Value(2).RealValue(), aValues->Value(3).RealValue()); - } + aView->SetUp (aViewUp.X(), aViewUp.Y(), aViewUp.Z()); } - if (aMapOfKeysByValues.Find ("CENTER", aValues)) + if (toSetCenter2d) { - anAISView->SetCenter (aValues->Value(1).IntegerValue(), aValues->Value(2).IntegerValue()); + aView->SetCenter (aCenter2d.x(), aCenter2d.y()); } return 0; } +//============================================================================== +//function : VAnimation +//purpose : +//============================================================================== +static Standard_Integer VAnimation (Draw_Interpretor& theDI, + Standard_Integer theArgNb, + const char** theArgVec) +{ + Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext(); + if (theArgNb < 2) + { + for (NCollection_DataMap::Iterator + anAnimIter (ViewerTest_AnimationTimelineMap); anAnimIter.More(); anAnimIter.Next()) + { + theDI << anAnimIter.Key() << " " << anAnimIter.Value()->Duration() << " sec\n"; + } + return 0; + } + if (aCtx.IsNull()) + { + std::cout << "Error: no active view\n"; + return 1; + } + + Standard_Integer anArgIter = 1; + TCollection_AsciiString aNameArg (theArgVec[anArgIter++]); + if (aNameArg.IsEmpty()) + { + std::cout << "Syntax error: animation name is not defined.\n"; + return 1; + } + + TCollection_AsciiString aNameArgLower = aNameArg; + aNameArgLower.LowerCase(); + if (aNameArgLower == "-reset" + || aNameArgLower == "-clear") + { + ViewerTest_AnimationTimelineMap.Clear(); + return 0; + } + else if (aNameArg.Value (1) == '-') + { + std::cout << "Syntax error: invalid animation name '" << aNameArg << "'.\n"; + return 1; + } + + const char* aNameSplitter = "/"; + Standard_Integer aSplitPos = aNameArg.Search (aNameSplitter); + if (aSplitPos == -1) + { + aNameSplitter = "."; + aSplitPos = aNameArg.Search (aNameSplitter); + } + + // find existing or create a new animation by specified name within syntax "parent.child". + Handle(AIS_Animation) aRootAnimation, aParentAnimation, anAnimation; + for (; !aNameArg.IsEmpty();) + { + TCollection_AsciiString aNameParent; + if (aSplitPos != -1) + { + if (aSplitPos == aNameArg.Length()) + { + std::cout << "Syntax error: animation name is not defined.\n"; + return 1; + } + + aNameParent = aNameArg.SubString ( 1, aSplitPos - 1); + aNameArg = aNameArg.SubString (aSplitPos + 1, aNameArg.Length()); + + aSplitPos = aNameArg.Search (aNameSplitter); + } + else + { + aNameParent = aNameArg; + aNameArg.Clear(); + } + + if (anAnimation.IsNull()) + { + if (!ViewerTest_AnimationTimelineMap.Find (aNameParent, anAnimation)) + { + anAnimation = new AIS_Animation (aNameParent); + ViewerTest_AnimationTimelineMap.Bind (aNameParent, anAnimation); + } + aRootAnimation = anAnimation; + } + else + { + aParentAnimation = anAnimation; + anAnimation = aParentAnimation->Find (aNameParent); + if (anAnimation.IsNull()) + { + anAnimation = new AIS_Animation (aNameParent); + aParentAnimation->Add (anAnimation); + } + } + } + + if (anArgIter >= theArgNb) + { + // just print the list of children + for (NCollection_Sequence::Iterator anAnimIter (anAnimation->Children()); anAnimIter.More(); anAnimIter.Next()) + { + theDI << anAnimIter.Value()->Name() << " " << anAnimIter.Value()->Duration() << " sec\n"; + } + return 0; + } + + Standard_Boolean toPlay = Standard_False; + Standard_Real aPlaySpeed = 1.0; + Standard_Real aPlayStartTime = anAnimation->StartPts(); + Standard_Real aPlayDuration = anAnimation->Duration(); + Standard_Real aPlayFrameRate = 0.0; + Standard_Boolean isFreeCamera = Standard_False; + Standard_Boolean isLockLoop = Standard_False; + Handle(V3d_View) aView = ViewerTest::CurrentView(); + for (; anArgIter < theArgNb; ++anArgIter) + { + TCollection_AsciiString anArg (theArgVec[anArgIter]); + anArg.LowerCase(); + if (anArg == "-reset" + || anArg == "-clear") + { + anAnimation->Clear(); + } + else if (anArg == "-remove" + || anArg == "-del" + || anArg == "-delete") + { + if (!aParentAnimation.IsNull()) + { + ViewerTest_AnimationTimelineMap.UnBind (anAnimation->Name()); + } + else + { + aParentAnimation->Remove (anAnimation); + } + } + else if (anArg == "-play") + { + toPlay = Standard_True; + if (++anArgIter < theArgNb) + { + if (*theArgVec[anArgIter] == '-') + { + --anArgIter; + continue; + } + aPlayStartTime = Draw::Atof (theArgVec[anArgIter]); + + if (++anArgIter < theArgNb) + { + if (*theArgVec[anArgIter] == '-') + { + --anArgIter; + continue; + } + aPlayDuration = Draw::Atof (theArgVec[anArgIter]); + } + } + } + else if (anArg == "-resume") + { + toPlay = Standard_True; + aPlayStartTime = anAnimation->ElapsedTime(); + if (++anArgIter < theArgNb) + { + if (*theArgVec[anArgIter] == '-') + { + --anArgIter; + continue; + } + + aPlayDuration = Draw::Atof (theArgVec[anArgIter]); + } + } + else if (anArg == "-playspeed" + || anArg == "-speed") + { + if (++anArgIter >= theArgNb) + { + std::cout << "Syntax error at " << anArg << ".\n"; + return 1; + } + aPlaySpeed = Draw::Atof (theArgVec[anArgIter]); + } + else if (anArg == "-lock" + || anArg == "-lockloop" + || anArg == "-playlockloop") + { + isLockLoop = Standard_True; + } + else if (anArg == "-freecamera" + || anArg == "-playfreecamera" + || anArg == "-freelook") + { + isFreeCamera = Standard_True; + } + else if (anArg == "-fps") + { + if (++anArgIter >= theArgNb) + { + std::cout << "Syntax error at " << anArg << ".\n"; + return 1; + } + aPlayFrameRate = Draw::Atof (theArgVec[anArgIter]); + } + else if (anArg == "-start" + || anArg == "-starttime" + || anArg == "-startpts") + { + if (++anArgIter >= theArgNb) + { + std::cout << "Syntax error at " << anArg << ".\n"; + return 1; + } + + anAnimation->SetStartPts (Draw::Atof (theArgVec[anArgIter])); + aRootAnimation->UpdateTotalDuration(); + } + else if (anArg == "-end" + || anArg == "-endtime" + || anArg == "-endpts") + { + if (++anArgIter >= theArgNb) + { + std::cout << "Syntax error at " << anArg << ".\n"; + return 1; + } + + anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]) - anAnimation->StartPts()); + aRootAnimation->UpdateTotalDuration(); + } + else if (anArg == "-dur" + || anArg == "-duration") + { + if (++anArgIter >= theArgNb) + { + std::cout << "Syntax error at " << anArg << ".\n"; + return 1; + } + + anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter])); + aRootAnimation->UpdateTotalDuration(); + } + else if (anArg == "-command" + || anArg == "-cmd" + || anArg == "-invoke" + || anArg == "-eval" + || anArg == "-proc") + { + if (++anArgIter >= theArgNb) + { + std::cout << "Syntax error at " << anArg << ".\n"; + return 1; + } + + Handle(ViewerTest_AnimationProc) aCmdAnimation = new ViewerTest_AnimationProc (anAnimation->Name(), &theDI, theArgVec[anArgIter]); + replaceAnimation (aParentAnimation, anAnimation, aCmdAnimation); + } + else if (anArg == "-objecttrsf" + || anArg == "-objectransformation" + || anArg == "-objtransformation" + || anArg == "-objtrsf" + || anArg == "-object" + || anArg == "-obj") + { + if (++anArgIter >= theArgNb) + { + std::cout << "Syntax error at " << anArg << ".\n"; + return 1; + } + + TCollection_AsciiString anObjName (theArgVec[anArgIter]); + const ViewerTest_DoubleMapOfInteractiveAndName& aMapOfAIS = GetMapOfAIS(); + if (!aMapOfAIS.IsBound2 (anObjName)) + { + std::cout << "Syntax error: wrong object name at " << anArg << "\n"; + return 1; + } + + Handle(AIS_InteractiveObject) anObject = Handle(AIS_InteractiveObject)::DownCast (aMapOfAIS.Find2 (anObjName)); + gp_Trsf aTrsfs [2] = { anObject->LocalTransformation(), anObject->LocalTransformation() }; + gp_Quaternion aRotQuats[2] = { aTrsfs[0].GetRotation(), aTrsfs[1].GetRotation() }; + gp_XYZ aLocPnts [2] = { aTrsfs[0].TranslationPart(), aTrsfs[1].TranslationPart() }; + Standard_Real aScales [2] = { aTrsfs[0].ScaleFactor(), aTrsfs[1].ScaleFactor() }; + Standard_Boolean isTrsfSet = Standard_False; + Standard_Integer aTrsfArgIter = anArgIter + 1; + for (; aTrsfArgIter < theArgNb; ++aTrsfArgIter) + { + TCollection_AsciiString aTrsfArg (theArgVec[aTrsfArgIter]); + aTrsfArg.LowerCase(); + const Standard_Integer anIndex = aTrsfArg.EndsWith ("1") ? 0 : 1; + if (aTrsfArg.StartsWith ("-rotation") + || aTrsfArg.StartsWith ("-rot")) + { + isTrsfSet = Standard_True; + if (aTrsfArgIter + 4 >= theArgNb + || !parseQuaternion (theArgVec + aTrsfArgIter + 1, aRotQuats[anIndex])) + { + std::cout << "Syntax error at " << aTrsfArg << ".\n"; + return 1; + } + aTrsfArgIter += 4; + } + else if (aTrsfArg.StartsWith ("-location") + || aTrsfArg.StartsWith ("-loc")) + { + isTrsfSet = Standard_True; + if (aTrsfArgIter + 3 >= theArgNb + || !parseXYZ (theArgVec + aTrsfArgIter + 1, aLocPnts[anIndex])) + { + std::cout << "Syntax error at " << aTrsfArg << ".\n"; + return 1; + } + aTrsfArgIter += 3; + } + else if (aTrsfArg.StartsWith ("-scale")) + { + isTrsfSet = Standard_True; + if (++aTrsfArgIter >= theArgNb) + { + std::cout << "Syntax error at " << aTrsfArg << ".\n"; + return 1; + } + + const TCollection_AsciiString aScaleStr (theArgVec[aTrsfArgIter]); + if (!aScaleStr.IsRealValue()) + { + std::cout << "Syntax error at " << aTrsfArg << ".\n"; + return 1; + } + aScales[anIndex] = aScaleStr.RealValue(); + } + else + { + anArgIter = aTrsfArgIter - 1; + break; + } + } + if (!isTrsfSet) + { + std::cout << "Syntax error at " << anArg << ".\n"; + return 1; + } + else if (aTrsfArgIter >= theArgNb) + { + anArgIter = theArgNb; + } + + aTrsfs[0].SetRotation (aRotQuats[0]); + aTrsfs[1].SetRotation (aRotQuats[1]); + aTrsfs[0].SetTranslationPart (aLocPnts[0]); + aTrsfs[1].SetTranslationPart (aLocPnts[1]); + aTrsfs[0].SetScaleFactor (aScales[0]); + aTrsfs[1].SetScaleFactor (aScales[1]); + + Handle(AIS_AnimationObject) anObjAnimation = new AIS_AnimationObject (anAnimation->Name(), aCtx, anObject, aTrsfs[0], aTrsfs[1]); + replaceAnimation (aParentAnimation, anAnimation, anObjAnimation); + } + else if (anArg == "-viewtrsf" + || anArg == "-view") + { + Handle(AIS_AnimationCamera) aCamAnimation = Handle(AIS_AnimationCamera)::DownCast (anAnimation); + if (aCamAnimation.IsNull()) + { + aCamAnimation = new AIS_AnimationCamera (anAnimation->Name(), aView); + replaceAnimation (aParentAnimation, anAnimation, aCamAnimation); + } + + Handle(Graphic3d_Camera) aCams[2] = + { + new Graphic3d_Camera (aCamAnimation->View()->Camera()), + new Graphic3d_Camera (aCamAnimation->View()->Camera()) + }; + + Standard_Boolean isTrsfSet = Standard_False; + Standard_Integer aViewArgIter = anArgIter + 1; + for (; aViewArgIter < theArgNb; ++aViewArgIter) + { + TCollection_AsciiString aViewArg (theArgVec[aViewArgIter]); + aViewArg.LowerCase(); + const Standard_Integer anIndex = aViewArg.EndsWith("1") ? 0 : 1; + if (aViewArg.StartsWith ("-scale")) + { + isTrsfSet = Standard_True; + if (++aViewArgIter >= theArgNb) + { + std::cout << "Syntax error at " << anArg << ".\n"; + return 1; + } + + const TCollection_AsciiString aScaleStr (theArgVec[aViewArgIter]); + if (!aScaleStr.IsRealValue()) + { + std::cout << "Syntax error at " << aViewArg << ".\n"; + return 1; + } + Standard_Real aScale = aScaleStr.RealValue(); + aScale = aCamAnimation->View()->DefaultCamera()->Scale() / aScale; + aCams[anIndex]->SetScale (aScale); + } + else if (aViewArg.StartsWith ("-eye") + || aViewArg.StartsWith ("-center") + || aViewArg.StartsWith ("-at") + || aViewArg.StartsWith ("-up")) + { + isTrsfSet = Standard_True; + gp_XYZ anXYZ; + if (aViewArgIter + 3 >= theArgNb + || !parseXYZ (theArgVec + aViewArgIter + 1, anXYZ)) + { + std::cout << "Syntax error at " << aViewArg << ".\n"; + return 1; + } + aViewArgIter += 3; + + if (aViewArg.StartsWith ("-eye")) + { + aCams[anIndex]->SetEye (anXYZ); + } + else if (aViewArg.StartsWith ("-center") + || aViewArg.StartsWith ("-at")) + { + aCams[anIndex]->SetCenter (anXYZ); + } + else if (aViewArg.StartsWith ("-up")) + { + aCams[anIndex]->SetUp (anXYZ); + } + } + else + { + anArgIter = aViewArgIter - 1; + break; + } + } + if (!isTrsfSet) + { + std::cout << "Syntax error at " << anArg << ".\n"; + return 1; + } + else if (aViewArgIter >= theArgNb) + { + anArgIter = theArgNb; + } + + aCamAnimation->SetCameraStart(aCams[0]); + aCamAnimation->SetCameraEnd (aCams[1]); + } + else + { + std::cout << "Syntax error at " << anArg << ".\n"; + return 1; + } + } + + if (!toPlay) + { + return 0; + } + + // Start animation timeline and process frame updating. + TheIsAnimating = Standard_True; + const Standard_Boolean wasImmediateUpdate = aView->SetImmediateUpdate (Standard_False); + Handle(Graphic3d_Camera) aCameraBack = new Graphic3d_Camera (aView->Camera()); + anAnimation->StartTimer (aPlayStartTime, aPlaySpeed, Standard_True); + if (isFreeCamera) + { + aView->Camera()->Copy (aCameraBack); + } + + const Standard_Real anUpperPts = aPlayStartTime + aPlayDuration; + if (aPlayFrameRate < Precision::Confusion()) + { + while (!anAnimation->IsStopped()) + { + aCameraBack->Copy (aView->Camera()); + const Standard_Real aPts = anAnimation->UpdateTimer(); + if (isFreeCamera) + { + aView->Camera()->Copy (aCameraBack); + } + + if (aPts >= anUpperPts) + { + anAnimation->Pause(); + break; + } + + if (aView->IsInvalidated()) + { + aView->Redraw(); + } + else + { + aView->RedrawImmediate(); + } + + if (!isLockLoop) + { + // handle user events + theDI.Eval ("after 1 set waiter 1"); + theDI.Eval ("vwait waiter"); + } + if (!TheIsAnimating) + { + anAnimation->Pause(); + theDI << aPts; + break; + } + } + + if (aView->IsInvalidated()) + { + aView->Redraw(); + } + else + { + aView->RedrawImmediate(); + } + } + else + { + Standard_Real aMaxFPS = 0.0; + + // Manage frame-rated animation here + Standard_Real aPts = aPlayStartTime; + while (aPts <= anUpperPts) + { + if (!anAnimation->Update (aPts)) + { + break; + } + + Standard_Real aProgress = anAnimation->ElapsedTime(); + Standard_Real aNextRatedPts = aPts + 1.0 / aPlayFrameRate; + Standard_Real aPrevPts = aPts; + aPts = aNextRatedPts < aProgress ? aNextRatedPts : aProgress; + Standard_Real aCurrentFPS = 1.0 / (aPts - aPrevPts); + if (aMaxFPS < aCurrentFPS) + { + aMaxFPS = aCurrentFPS; + } + } + + if (aView->IsInvalidated()) + { + aView->Redraw(); + } + else + { + aView->RedrawImmediate(); + } + anAnimation->Stop(); + theDI << aMaxFPS; + } + + aView->SetImmediateUpdate (wasImmediateUpdate); + TheIsAnimating = Standard_False; + return 0; +} + + //======================================================================= //function : VChangeSelected //purpose : Adds the shape to selection or remove one from it @@ -9411,8 +10133,8 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands) theCommands.Add("vpick" , "vpick : vpick X Y Z [shape subshape] ( all variables as string )", VPick,group); - theCommands.Add("vfit" , - "vfit or [-selected]" + theCommands.Add("vfit", + "vfit or [-selected] [-noupdate]" "\n\t\t: [-selected] fits the scene according to bounding box of currently selected objects", __FILE__,VFit,group); theCommands.Add ("vfitarea", @@ -9662,22 +10384,73 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands) "vmoveto x y" "- emulates cursor movement to pixel postion (x,y)", __FILE__, VMoveTo, group); - theCommands.Add ("vviewparams", "vviewparams usage:\n" - "- vviewparams\n" - "- vviewparams [-scale [s]] [-eye [x y z]] [-at [x y z]] [-up [x y z]]\n" - " [-proj [x y z]] [-center x y] [-size sx]\n" - "- Gets or sets current view parameters.\n" - "- If called without arguments, all view parameters are printed.\n" - "- The options are:\n" - " -scale [s] : prints or sets viewport relative scale.\n" - " -eye [x y z] : prints or sets eye location.\n" - " -at [x y z] : prints or sets center of look.\n" - " -up [x y z] : prints or sets direction of up vector.\n" - " -proj [x y z] : prints or sets direction of look.\n" - " -center x y : sets location of center of the screen in pixels.\n" - " -size [sx] : prints viewport projection width and height sizes\n" - " : or changes the size of its maximum dimension.\n", + theCommands.Add ("vviewparams", + "vviewparams [-args] [-scale [s]]" + "\n\t\t: [-eye [x y z]] [-at [x y z]] [-up [x y z]]" + "\n\t\t: [-proj [x y z]] [-center x y] [-size sx]" + "\n\t\t: Manage current view parameters or prints all" + "\n\t\t: current values when called without argument." + "\n\t\t: -scale [s] prints or sets viewport relative scale" + "\n\t\t: -eye [x y z] prints or sets eye location" + "\n\t\t: -at [x y z] prints or sets center of look" + "\n\t\t: -up [x y z] prints or sets direction of up vector" + "\n\t\t: -proj [x y z] prints or sets direction of look" + "\n\t\t: -center x y sets location of center of the screen in pixels" + "\n\t\t: -size [sx] prints viewport projection width and height sizes" + "\n\t\t: or changes the size of its maximum dimension" + "\n\t\t: -args prints vviewparams arguments for restoring current view", __FILE__, VViewParams, group); + + theCommands.Add("vanimation", "Alias for vanim", + __FILE__, VAnimation, group); + + theCommands.Add("vanim", + "List existing animations:" + "\n\t\t: vanim" + "\n\t\t: Animation playback:" + "\n\t\t: vanim name -play|-resume [playFrom [playDuration]]" + "\n\t\t: [-speed Coeff] [-freeLook] [-lockLoop]" + "\n\t\t: -speed playback speed (1.0 is normal speed)" + "\n\t\t: -freeLook skip camera animations" + "\n\t\t: -lockLoop disable any interactions" + "\n\t\t:" + "\n\t\t: Animation definition:" + "\n\t\t: vanim Name/sub/name [-clear] [-delete]" + "\n\t\t: [start TimeSec] [duration TimeSec]" + "\n\t\t:" + "\n\t\t: Animation name defined in path-style (anim/name or anim.name)" + "\n\t\t: specifies nested animations." + "\n\t\t: There is no syntax to explicitly add new animation," + "\n\t\t: and all non-existing animations within the name will be" + "\n\t\t: implicitly created on first use (including parents)." + "\n\t\t:" + "\n\t\t: Each animation might define the SINGLE action (see below)," + "\n\t\t: like camera transition, object transformation or custom callback." + "\n\t\t: Child animations can be used for defining concurrent actions." + "\n\t\t:" + "\n\t\t: Camera animation:" + "\n\t\t: vanim name -view [-eye1 X Y Z] [-eye2 X Y Z]" + "\n\t\t: [-at1 X Y Z] [-at2 X Y Z]" + "\n\t\t: [-up1 X Y Z] [-up2 X Y Z]" + "\n\t\t: [-scale1 Scale] [-scale2 Scale]" + "\n\t\t: -eyeX camera Eye positions pair (start and end)" + "\n\t\t: -atX camera Center positions pair" + "\n\t\t: -upX camera Up directions pair" + "\n\t\t: -scaleX camera Scale factors pair" + "\n\t\t: Object animation:" + "\n\t\t: vanim name -object [-loc1 X Y Z] [-loc2 X Y Z]" + "\n\t\t: [-rot1 QX QY QZ QW] [-rot2 QX QY QZ QW]" + "\n\t\t: [-scale1 Scale] [-scale2 Scale]" + "\n\t\t: -locX object Location points pair (translation)" + "\n\t\t: -rotX object Orientations pair (quaternions)" + "\n\t\t: -scaleX object Scale factors pair (quaternions)" + "\n\t\t: Custom callback:" + "\n\t\t: vanim name -invoke \"Command Arg1 Arg2 %Pts %LocalPts %Normalized ArgN\"" + "\n\t\t: %Pts overall animation presentation timestamp" + "\n\t\t: %LocalPts local animation timestamp" + "\n\t\t: %Normalized local animation normalized value in range 0..1" + __FILE__, VAnimation, group); + theCommands.Add("vchangeselected", "vchangeselected shape" "- adds to shape to selection or remove one from it", diff --git a/src/gp/FILES b/src/gp/FILES index 859d37ae17..b715338b1c 100644 --- a/src/gp/FILES +++ b/src/gp/FILES @@ -98,6 +98,7 @@ gp_Trsf2d.cxx gp_Trsf2d.hxx gp_Trsf2d.lxx gp_TrsfForm.hxx +gp_TrsfNLerp.hxx gp_Vec.cxx gp_Vec.hxx gp_Vec.lxx diff --git a/src/gp/gp_QuaternionNLerp.hxx b/src/gp/gp_QuaternionNLerp.hxx index 00924e9a05..42be79206d 100644 --- a/src/gp/gp_QuaternionNLerp.hxx +++ b/src/gp/gp_QuaternionNLerp.hxx @@ -16,27 +16,45 @@ #include -/** - * Class perform linear interpolation (approximate rotation interpolation), - * result quaternion nonunit, its length lay between. sqrt(2)/2 and 1.0 - */ +//! Class perform linear interpolation (approximate rotation interpolation), +//! result quaternion nonunit, its length lay between. sqrt(2)/2 and 1.0 class gp_QuaternionNLerp { +public: + + //! Compute interpolated quaternion between two quaternions. + //! @param theStart first quaternion + //! @param theEnd second quaternion + //! @param theT normalized interpolation coefficient within 0..1 range, + //! with 0 pointing to theStart and 1 to theEnd. + static gp_Quaternion Interpolate (const gp_Quaternion& theQStart, + const gp_Quaternion& theQEnd, + Standard_Real theT) + { + gp_Quaternion aResult; + gp_QuaternionNLerp aLerp (theQStart, theQEnd); + aLerp.Interpolate (theT, aResult); + return aResult; + } public: + //! Empty constructor, gp_QuaternionNLerp() {} + //! Constructor with initialization. gp_QuaternionNLerp (const gp_Quaternion& theQStart, const gp_Quaternion& theQEnd) { Init (theQStart, theQEnd); } + //! Initialize the tool with Start and End values. void Init (const gp_Quaternion& theQStart, const gp_Quaternion& theQEnd) { InitFromUnit (theQStart.Normalized(), theQEnd.Normalized()); } + //! Initialize the tool with Start and End unit quaternions. void InitFromUnit (const gp_Quaternion& theQStart, const gp_Quaternion& theQEnd) { myQStart = theQStart; @@ -55,16 +73,6 @@ public: theResultQ = myQStart + myQEnd * theT; } - static gp_Quaternion Interpolate (const gp_Quaternion& theQStart, - const gp_Quaternion& theQEnd, - Standard_Real theT) - { - gp_Quaternion aResultQ; - gp_QuaternionNLerp aNLerp (theQStart, theQEnd); - aNLerp.Interpolate (theT, aResultQ); - return aResultQ; - } - private: gp_Quaternion myQStart; diff --git a/src/gp/gp_QuaternionSLerp.hxx b/src/gp/gp_QuaternionSLerp.hxx index efe6534838..9893f78d58 100644 --- a/src/gp/gp_QuaternionSLerp.hxx +++ b/src/gp/gp_QuaternionSLerp.hxx @@ -16,27 +16,45 @@ #include -/** - * Perform Spherical Linear Interpolation of the quaternions, - * return unit length quaternion. - */ +//! Perform Spherical Linear Interpolation of the quaternions, +//! return unit length quaternion. class gp_QuaternionSLerp { +public: + + //! Compute interpolated quaternion between two quaternions. + //! @param theStart first quaternion + //! @param theEnd second quaternion + //! @param theT normalized interpolation coefficient within 0..1 range, + //! with 0 pointing to theStart and 1 to theEnd. + static gp_Quaternion Interpolate (const gp_Quaternion& theQStart, + const gp_Quaternion& theQEnd, + Standard_Real theT) + { + gp_Quaternion aResult; + gp_QuaternionSLerp aLerp (theQStart, theQEnd); + aLerp.Interpolate (theT, aResult); + return aResult; + } public: + //! Empty constructor, gp_QuaternionSLerp() {} + //! Constructor with initialization. gp_QuaternionSLerp (const gp_Quaternion& theQStart, const gp_Quaternion& theQEnd) { Init (theQStart, theQEnd); } + //! Initialize the tool with Start and End values. void Init (const gp_Quaternion& theQStart, const gp_Quaternion& theQEnd) { InitFromUnit (theQStart.Normalized(), theQEnd.Normalized()); } + //! Initialize the tool with Start and End unit quaternions. void InitFromUnit (const gp_Quaternion& theQStart, const gp_Quaternion& theQEnd) { myQStart = theQStart; diff --git a/src/gp/gp_TrsfNLerp.hxx b/src/gp/gp_TrsfNLerp.hxx new file mode 100644 index 0000000000..dcf26b13ff --- /dev/null +++ b/src/gp/gp_TrsfNLerp.hxx @@ -0,0 +1,93 @@ +// Copyright (c) 2016 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _gp_TrsfNLerp_HeaderFile +#define _gp_TrsfNLerp_HeaderFile + +#include +#include +#include +#include + +//! Linear interpolation tool for transformation defined by gp_Trsf. +//! +//! In general case, there is a no well-defined interpolation between arbitrary transformations, +//! because desired transient values might vary depending on application needs. +//! +//! This tool performs independent interpolation of three logical +//! transformation parts - rotation (using gp_QuaternionNLerp), translation and scale factor. +//! Result of such interpolation might be not what application expects, +//! thus this tool might be considered for simple cases or for interpolating between small intervals. +template<> class NCollection_Lerp +{ +public: + + //! Empty constructor + NCollection_Lerp() {} + + //! Main constructor. + NCollection_Lerp (const gp_Trsf& theStart, const gp_Trsf& theEnd) + { + Init (theStart, theEnd); + } + + //! Initialize values. + void Init (const gp_Trsf& theStart, const gp_Trsf& theEnd) + { + myTrsfStart = theStart; + myTrsfEnd = theEnd; + myLocLerp .Init (theStart.TranslationPart(), theEnd.TranslationPart()); + myRotLerp .Init (theStart.GetRotation(), theEnd.GetRotation()); + myScaleLerp.Init (theStart.ScaleFactor(), theEnd.ScaleFactor()); + } + + //! Compute interpolated value between two values. + //! @param theT normalized interpolation coefficient within [0, 1] range, + //! with 0 pointing to first value and 1 to the second value. + //! @param theResult [out] interpolated value + void Interpolate (double theT, gp_Trsf& theResult) const + { + if (Abs (theT - 0.0) < Precision::Confusion()) + { + theResult = myTrsfStart; + return; + } + else if (Abs (theT - 1.0) < Precision::Confusion()) + { + theResult = myTrsfEnd; + return; + } + + gp_XYZ aLoc; + gp_Quaternion aRot; + Standard_Real aScale = 1.0; + myLocLerp .Interpolate (theT, aLoc); + myRotLerp .Interpolate (theT, aRot); + myScaleLerp.Interpolate (theT, aScale); + theResult = gp_Trsf(); + theResult.SetRotation (aRot); + theResult.SetTranslationPart (aLoc); + theResult.SetScaleFactor (aScale); + } + +private: + NCollection_Lerp myLocLerp; + NCollection_Lerp myScaleLerp; + gp_QuaternionNLerp myRotLerp; + gp_Trsf myTrsfStart; + gp_Trsf myTrsfEnd; +}; + +typedef NCollection_Lerp gp_TrsfNLerp; + +#endif // _gp_TrsfNLerp_HeaderFile diff --git a/tests/bugs/vis/bug24623_3 b/tests/bugs/vis/bug24623_3 index 451488e55a..f74eef4cae 100644 --- a/tests/bugs/vis/bug24623_3 +++ b/tests/bugs/vis/bug24623_3 @@ -23,7 +23,7 @@ set aNb 1000 # display as copies eval compound [lrepeat $aNb s] ss explode ss -for {set i 1} {$i <= $aNb} {incr i} { vloadselection ss_${i}; vsetlocation -noupdate ss_${i} 0 0 s } +for {set i 1} {$i <= $aNb} {incr i} { vloadselection ss_${i}; vsetlocation -noupdate ss_${i} ${i} 0 0 } vfit set aMemSel1 [meminfo h] vclear diff --git a/tests/bugs/vis/bug25276 b/tests/bugs/vis/bug25276 index 20c19db6df..85c14da691 100644 --- a/tests/bugs/vis/bug25276 +++ b/tests/bugs/vis/bug25276 @@ -14,27 +14,27 @@ vdisplay b1 vconnectto b2 6 0 0 b1 box b3 7 1 1 vdisplay b3 -vloctranslate b3 0 4 0 +vlocation b3 -translate 0 4 0 vconnect z 0 0 0 b1 b2 b3 vconnect z1 0 0 0 z -vloctranslate z1 10 0 0 +vlocation z1 -translate 10 0 0 vconnect z2 0 10 0 z -vlocrotate z2 0 0 0 1 0 0 90 +vlocation z2 -rotate 0 0 0 1 0 0 90 vconnect z3 -10 0 0 z -vlocscale z3 0 0 0 0.5 +vlocation z3 -scale 0 0 0 0.5 vconnect z4 0 0 0 z -vlocmove z4 z3 +vlocation z4 -copyFrom z3 psphere sp 3 vdisplay sp -vlocmove sp z3 -vlocreset sp +vlocation sp -copyFrom z3 +vlocation sp -reset -vlocmirror z 0 -0.5 0 0 1 0 +vlocation z -mirror 0 -0.5 0 0 1 0 vfit vdump $imagedir/${casename}.png diff --git a/tests/bugs/vis/bug25532 b/tests/bugs/vis/bug25532 index 8b1bbbe169..31e3367dfc 100644 --- a/tests/bugs/vis/bug25532 +++ b/tests/bugs/vis/bug25532 @@ -27,7 +27,7 @@ set aNb 1000 # display as copies eval compound [lrepeat $aNb s] ss explode ss -for {set i 1} {$i <= $aNb} {incr i} { vdisplay -noupdate ss_${i}; vsetlocation -noupdate ss_${i} 0 0 s } +for {set i 1} {$i <= $aNb} {incr i} { vdisplay -noupdate ss_${i}; vsetlocation -noupdate ss_${i} ${i} 0 0 } vfit set aMemDisp1 [meminfo h] vclear diff --git a/tests/bugs/vis/bug26599 b/tests/bugs/vis/bug26599 index 36ea93dbd5..8854b47e3a 100755 --- a/tests/bugs/vis/bug26599 +++ b/tests/bugs/vis/bug26599 @@ -19,7 +19,7 @@ vdisplay b vfit -vlocrotate b 0 0 0 0 0 1 50 +vlocation b -rotate 0 0 0 0 0 1 50 vmoveto 380 50 checkcolor 380 50 0.87450981140136719 0 0.12156862765550613 diff --git a/tests/v3d/anim/objects b/tests/v3d/anim/objects new file mode 100644 index 0000000000..92a5f0c0bd --- /dev/null +++ b/tests/v3d/anim/objects @@ -0,0 +1,34 @@ +puts "==================================" +puts "Viewer animation - animate object moving" +puts "==================================" + +pload MODELING VISUALIZATION + +vclear +vinit View1 +vaxo + +psphere s 50 +box b1 -50 -50 0 100 100 100 +vdisplay -dispMode 1 b1 s + +vviewparams -scale 2.499 -proj 0.546611 -0.600024 -0.584114 -up -0.411832 0.414728 -0.811415 -at -5.3425 -2.983 49.216 + +vanimation anim -clear +vanimation anim/obj1 -objectTrsf b1 -loc1 0 0 0 -loc2 -100 0 -100 -start 0 -duration 2 +vanimation anim/obj2 -objectTrsf s -loc1 0 0 0 -loc2 100 0 100 -start 1 -duration 2 + +vanimation anim -play 0.0 0.0 +vdump $imagedir/${casename}_0.png + +vanimation anim -play 1.0 0.0 +vdump $imagedir/${casename}_1.png + +vanimation anim -play 2.0 0.0 +vdump $imagedir/${casename}_2.png + +if {[vreadpixel 270 20 rgb name] != "DARKGOLDENROD3"} { puts "Error: Box moving result is wrong!" } +if {[vreadpixel 120 255 rgb name] != "DARKGOLDENROD4"} { puts "Error: Sphere moving result is wrong!" } + +puts "Put the following command to start interactive animation:" +puts " vanimation anim -play" diff --git a/tests/v3d/anim/propeller b/tests/v3d/anim/propeller new file mode 100644 index 0000000000..dfbe491b0b --- /dev/null +++ b/tests/v3d/anim/propeller @@ -0,0 +1,116 @@ +puts "==================================" +puts "Viewer animation - Propeller animation" +puts "Regressions should be detected visually" +puts "==================================" + +pload MODELING VISUALIZATION +restore [locate_data_file occ/CrankArm.rle] a +restore [locate_data_file occ/CylinderHead.rle] h +restore [locate_data_file occ/Propeller.rle] p +restore [locate_data_file occ/EngineBlock.rle] e + +vclear +vinit name=View1 width=912 height=512 +vzbufftrihedron +vcamera -persp -fovy 60 +vdisplay -dispMode 1 -mutable a h p e +vfit +vsetcolor p GREEN +vsetcolor e RED +vsetcolor h PURPLE + +vanimation anim -clear + +# custom callback +proc drawAnimLabels {thePts} { vdrawtext lab "Current PTS: $thePts sec" -2d -persPos -1 1 30 -noupdate } +#proc drawAnimPropeller {theLocalPts} { set aVal 0.0; if { $theLocalPts >= 1.0 && $theLocalPts <= 1.5 } { set aVal 0.9 }; vaspects -noupdate p -setTransparency $aVal } +proc drawAnimProp1 {theNormalized} { vaspects -noupdate p -setTransparency [expr $theNormalized * 0.9] } +proc drawAnimProp2 {theNormalized} { vaspects -noupdate p -setTransparency [expr (1.0 - $theNormalized) * 0.9] } +vanimation anim/cmd/1 -start 0 -dur 2.0 -cmd "drawAnimLabels %pts" +#vanimation anim/cmd/2 -start 0 -dur 2.0 -cmd "drawAnimPropeller %localPts" +vanimation anim/cmd/2 -start 1.0 -dur 0.1 -cmd "drawAnimProp1 %localNormalized" +vanimation anim/cmd/3 -start 1.5 -dur 0.1 -cmd "drawAnimProp2 %localNormalized" + +# camera animation +vanimation anim/cam/1 -start 0 -dur 0.5 -view -up1 -0.408248 0.408248 0.816497 -up2 -0.70394 0.70394 -0.094542 -at1 0 0 -52.5 -at2 0 0 -52.5 -eye1 718.333 -718.333 665.833 -eye2 -83.1757 83.1757 1186.12 -scale1 0.736953 -scale2 1.3 +vanimation anim/cam/2 -start 0.5 -dur 0.5 -view -up1 -0.70394 0.70394 -0.094542 -up2 -0.0582751 -0.996311 0.0629907 -at1 0 0 -52.5 -at2 0 0 -52.5 -eye1 -83.1757 83.1757 1186.12 -eye2 -83.1757 83.1757 1186.12 -scale1 1.3 -scale2 2.5 +vanimation anim/cam/3 -start 1.0 -dur 0.5 -view -up1 -0.0582751 -0.996311 0.0629907 -up2 -0.0757833 -0.103462 0.991742 -at1 0 0 -52.5 -at2 0 0 -52.5 -eye1 -83.1757 83.1757 1186.12 -eye2 57.3134 1235.7 80.7922 -scale1 2.5 -scale2 5.0 +vanimation anim/cam/4 -start 1.5 -dur 0.5 -view -up1 -0.0757833 -0.103462 0.991742 -up2 -0.0757833 -0.103462 0.991742 -at1 0 0 -52.5 -at2 85.6748 -3.38673 -57.9416 -eye1 57.3134 1235.7 80.7922 -eye2 142.989 1232.32 75.3506 -scale1 5.0 -scale2 2.0 + +# propeller animation +vanimation anim/p/1 -start 0 -dur 0.5 -objectTrsf p -rot1 0 0 0 1 -rot2 0 0 0.707107 0.707107 +vanimation anim/p/2 -start 0.5 -dur 0.5 -objectTrsf p -rot1 0 0 0.707107 0.707107 -rot2 0 0 1 6.12323e-17 +vanimation anim/p/3 -start 1.0 -dur 0.5 -objectTrsf p -rot1 0 0 1 6.12323e-17 -rot2 0 0 -0.707107 0.707107 +vanimation anim/p/4 -start 1.5 -dur 0.5 -objectTrsf p -rot1 0 0 -0.707107 0.707107 -rot2 0 0 0 1 + +# arm animation +vanimation anim/a/1 -start 0 -dur 0.03125 -objectTrsf a -rot1 0 0 0 1 -rot2 0 0 -0.0183813 0.999831 -loc1 0 0 0 -loc2 -0.186279 6.06481 -0 +vanimation anim/a/2 -start 0.03125 -dur 0.03125 -objectTrsf a -rot1 0 0 -0.0183813 0.999831 -rot2 0 0 -0.036604 0.99933 -loc1 -0.186279 6.06481 -0 -loc2 -0.744076 12.0712 -0 +vanimation anim/a/3 -start 0.0625 -dur 0.03125 -objectTrsf a -rot1 0 0 -0.036604 0.99933 -rot2 0 0 -0.0545094 0.998513 -loc1 -0.744076 12.0712 -0 -loc2 -1.67027 17.9614 -0 +vanimation anim/a/4 -start 0.09375 -dur 0.03125 -objectTrsf a -rot1 0 0 -0.0545094 0.998513 -rot2 0 0 -0.0719395 0.997409 -loc1 -1.67027 17.9614 -0 -loc2 -2.95964 23.6785 -0 +vanimation anim/a/5 -start 0.125 -dur 0.03125 -objectTrsf a -rot1 0 0 -0.0719395 0.997409 -rot2 0 0 -0.0887369 0.996055 -loc1 -2.95964 23.6785 -0 -loc2 -4.60486 29.1677 -0 +vanimation anim/a/6 -start 0.15625 -dur 0.03125 -objectTrsf a -rot1 0 0 -0.0887369 0.996055 -rot2 0 0 -0.104746 0.994499 -loc1 -4.60486 29.1677 -0 -loc2 -6.59642 34.3759 -0 +vanimation anim/a/7 -start 0.1875 -dur 0.03125 -objectTrsf a -rot1 0 0 -0.104746 0.994499 -rot2 0 0 -0.119812 0.992797 -loc1 -6.59642 34.3759 -0 -loc2 -8.92259 39.2531 -0 +vanimation anim/a/8 -start 0.21875 -dur 0.03125 -objectTrsf a -rot1 0 0 -0.119812 0.992797 -rot2 0 0 -0.133785 0.99101 -loc1 -8.92259 39.2531 -0 -loc2 -11.5693 43.7522 -0 +vanimation anim/a/9 -start 0.25 -dur 0.03125 -objectTrsf a -rot1 0 0 -0.133785 0.99101 -rot2 0 0 -0.146521 0.989208 -loc1 -11.5693 43.7522 -0 -loc2 -14.5202 47.83 -0 +vanimation anim/a/10 -start 0.28125 -dur 0.03125 -objectTrsf a -rot1 0 0 -0.146521 0.989208 -rot2 0 0 -0.157881 0.987458 -loc1 -14.5202 47.83 -0 -loc2 -17.756 51.4472 -0 +vanimation anim/a/11 -start 0.3125 -dur 0.03125 -objectTrsf a -rot1 0 0 -0.157881 0.987458 -rot2 0 0 -0.167737 0.985832 -loc1 -17.756 51.4472 -0 -loc2 -21.2549 54.5689 -0 +vanimation anim/a/12 -start 0.34375 -dur 0.03125 -objectTrsf a -rot1 0 0 -0.167737 0.985832 -rot2 0 0 -0.175973 0.984395 -loc1 -21.2549 54.5689 -0 -loc2 -24.9922 57.165 -0 +vanimation anim/a/13 -start 0.375 -dur 0.03125 -objectTrsf a -rot1 0 0 -0.175973 0.984395 -rot2 0 0 -0.182491 0.983208 -loc1 -24.9922 57.165 -0 -loc2 -28.9399 59.2107 -0 +vanimation anim/a/14 -start 0.40625 -dur 0.03125 -objectTrsf a -rot1 0 0 -0.182491 0.983208 -rot2 0 0 -0.187207 0.98232 -loc1 -28.9399 59.2107 -0 -loc2 -33.0668 60.6861 -0 +vanimation anim/a/15 -start 0.4375 -dur 0.03125 -objectTrsf a -rot1 0 0 -0.187207 0.98232 -rot2 0 0 -0.190062 0.981772 -loc1 -33.0668 60.6861 -0 -loc2 -37.3381 61.5771 -0 +vanimation anim/a/16 -start 0.46875 -dur 0.03125 -objectTrsf a -rot1 0 0 -0.190062 0.981772 -rot2 0 0 -0.191017 0.981587 -loc1 -37.3381 61.5771 -0 -loc2 -41.7161 61.875 -0 +vanimation anim/a/17 -start 0.5 -dur 0.03125 -objectTrsf a -rot1 0 0 -0.191017 0.981587 -rot2 0 0 -0.190062 0.981772 -loc1 -41.7161 61.875 -0 -loc2 -46.1597 61.5771 -0 +vanimation anim/a/18 -start 0.53125 -dur 0.03125 -objectTrsf a -rot1 0 0 -0.190062 0.981772 -rot2 0 0 -0.187207 0.98232 -loc1 -46.1597 61.5771 -0 -loc2 -50.6249 60.6861 -0 +vanimation anim/a/19 -start 0.5625 -dur 0.03125 -objectTrsf a -rot1 0 0 -0.187207 0.98232 -rot2 0 0 -0.182491 0.983208 -loc1 -50.6249 60.6861 -0 -loc2 -55.0656 59.2107 -0 +vanimation anim/a/20 -start 0.59375 -dur 0.03125 -objectTrsf a -rot1 0 0 -0.182491 0.983208 -rot2 0 0 -0.175973 0.984395 -loc1 -55.0656 59.2107 -0 -loc2 -59.4338 57.165 -0 +vanimation anim/a/21 -start 0.625 -dur 0.03125 -objectTrsf a -rot1 0 0 -0.175973 0.984395 -rot2 0 0 -0.167737 0.985832 -loc1 -59.4338 57.165 -0 -loc2 -63.6806 54.5689 -0 +vanimation anim/a/22 -start 0.65625 -dur 0.03125 -objectTrsf a -rot1 0 0 -0.167737 0.985832 -rot2 0 0 -0.157881 0.987458 -loc1 -63.6806 54.5689 -0 -loc2 -67.7573 51.4472 -0 +vanimation anim/a/23 -start 0.6875 -dur 0.03125 -objectTrsf a -rot1 0 0 -0.157881 0.987458 -rot2 0 0 -0.146521 0.989208 -loc1 -67.7573 51.4472 -0 -loc2 -71.6155 47.83 -0 +vanimation anim/a/24 -start 0.71875 -dur 0.03125 -objectTrsf a -rot1 0 0 -0.146521 0.989208 -rot2 0 0 -0.133785 0.99101 -loc1 -71.6155 47.83 -0 -loc2 -75.2089 43.7522 -0 +vanimation anim/a/25 -start 0.75 -dur 0.03125 -objectTrsf a -rot1 0 0 -0.133785 0.99101 -rot2 0 0 -0.119812 0.992797 -loc1 -75.2089 43.7522 -0 -loc2 -78.4935 39.2531 -0 +vanimation anim/a/26 -start 0.78125 -dur 0.03125 -objectTrsf a -rot1 0 0 -0.119812 0.992797 -rot2 0 0 -0.104746 0.994499 -loc1 -78.4935 39.2531 -0 -loc2 -81.4287 34.3759 -0 +vanimation anim/a/27 -start 0.8125 -dur 0.03125 -objectTrsf a -rot1 0 0 -0.104746 0.994499 -rot2 0 0 -0.0887369 0.996055 -loc1 -81.4287 34.3759 -0 -loc2 -83.9778 29.1677 -0 +vanimation anim/a/28 -start 0.84375 -dur 0.03125 -objectTrsf a -rot1 0 0 -0.0887369 0.996055 -rot2 0 0 -0.0719395 0.997409 -loc1 -83.9778 29.1677 -0 -loc2 -86.1088 23.6785 -0 +vanimation anim/a/29 -start 0.875 -dur 0.03125 -objectTrsf a -rot1 0 0 -0.0719395 0.997409 -rot2 0 0 -0.0545094 0.998513 -loc1 -86.1088 23.6785 -0 -loc2 -87.7949 17.9614 -0 +vanimation anim/a/30 -start 0.90625 -dur 0.03125 -objectTrsf a -rot1 0 0 -0.0545094 0.998513 -rot2 0 0 -0.036604 0.99933 -loc1 -87.7949 17.9614 -0 -loc2 -89.0148 12.0712 -0 +vanimation anim/a/31 -start 0.9375 -dur 0.03125 -objectTrsf a -rot1 0 0 -0.036604 0.99933 -rot2 0 0 -0.0183813 0.999831 -loc1 -89.0148 12.0712 -0 -loc2 -89.7529 6.06481 -0 +vanimation anim/a/32 -start 0.96875 -dur 0.03125 -objectTrsf a -rot1 0 0 -0.0183813 0.999831 -rot2 0 0 -2.29621e-17 1 -loc1 -89.7529 6.06481 -0 -loc2 -90 7.5775e-15 -0 +vanimation anim/a/33 -start 1 -dur 0.03125 -objectTrsf a -rot1 0 0 -2.29621e-17 1 -rot2 0 0 0.0183813 0.999831 -loc1 -90 7.5775e-15 -0 -loc2 -89.7529 -6.06481 -0 +vanimation anim/a/34 -start 1.03125 -dur 0.03125 -objectTrsf a -rot1 0 0 0.0183813 0.999831 -rot2 0 0 0.036604 0.99933 -loc1 -89.7529 -6.06481 -0 -loc2 -89.0148 -12.0712 -0 +vanimation anim/a/35 -start 1.0625 -dur 0.03125 -objectTrsf a -rot1 0 0 0.036604 0.99933 -rot2 0 0 0.0545094 0.998513 -loc1 -89.0148 -12.0712 -0 -loc2 -87.7949 -17.9614 -0 +vanimation anim/a/36 -start 1.09375 -dur 0.03125 -objectTrsf a -rot1 0 0 0.0545094 0.998513 -rot2 0 0 0.0719395 0.997409 -loc1 -87.7949 -17.9614 -0 -loc2 -86.1088 -23.6785 -0 +vanimation anim/a/37 -start 1.125 -dur 0.03125 -objectTrsf a -rot1 0 0 0.0719395 0.997409 -rot2 0 0 0.0887369 0.996055 -loc1 -86.1088 -23.6785 -0 -loc2 -83.9778 -29.1677 -0 +vanimation anim/a/38 -start 1.15625 -dur 0.03125 -objectTrsf a -rot1 0 0 0.0887369 0.996055 -rot2 0 0 0.104746 0.994499 -loc1 -83.9778 -29.1677 -0 -loc2 -81.4287 -34.3759 -0 +vanimation anim/a/39 -start 1.1875 -dur 0.03125 -objectTrsf a -rot1 0 0 0.104746 0.994499 -rot2 0 0 0.119812 0.992797 -loc1 -81.4287 -34.3759 -0 -loc2 -78.4935 -39.2531 -0 +vanimation anim/a/40 -start 1.21875 -dur 0.03125 -objectTrsf a -rot1 0 0 0.119812 0.992797 -rot2 0 0 0.133785 0.99101 -loc1 -78.4935 -39.2531 -0 -loc2 -75.2089 -43.7522 -0 +vanimation anim/a/41 -start 1.25 -dur 0.03125 -objectTrsf a -rot1 0 0 0.133785 0.99101 -rot2 0 0 0.146521 0.989208 -loc1 -75.2089 -43.7522 -0 -loc2 -71.6155 -47.83 -0 +vanimation anim/a/42 -start 1.28125 -dur 0.03125 -objectTrsf a -rot1 0 0 0.146521 0.989208 -rot2 0 0 0.157881 0.987458 -loc1 -71.6155 -47.83 -0 -loc2 -67.7573 -51.4472 -0 +vanimation anim/a/43 -start 1.3125 -dur 0.03125 -objectTrsf a -rot1 0 0 0.157881 0.987458 -rot2 0 0 0.167737 0.985832 -loc1 -67.7573 -51.4472 -0 -loc2 -63.6806 -54.5689 -0 +vanimation anim/a/44 -start 1.34375 -dur 0.03125 -objectTrsf a -rot1 0 0 0.167737 0.985832 -rot2 0 0 0.175973 0.984395 -loc1 -63.6806 -54.5689 -0 -loc2 -59.4338 -57.165 -0 +vanimation anim/a/45 -start 1.375 -dur 0.03125 -objectTrsf a -rot1 0 0 0.175973 0.984395 -rot2 0 0 0.182491 0.983208 -loc1 -59.4338 -57.165 -0 -loc2 -55.0656 -59.2107 -0 +vanimation anim/a/46 -start 1.40625 -dur 0.03125 -objectTrsf a -rot1 0 0 0.182491 0.983208 -rot2 0 0 0.187207 0.98232 -loc1 -55.0656 -59.2107 -0 -loc2 -50.6249 -60.6861 -0 +vanimation anim/a/47 -start 1.4375 -dur 0.03125 -objectTrsf a -rot1 0 0 0.187207 0.98232 -rot2 0 0 0.190062 0.981772 -loc1 -50.6249 -60.6861 -0 -loc2 -46.1597 -61.5771 -0 +vanimation anim/a/48 -start 1.46875 -dur 0.03125 -objectTrsf a -rot1 0 0 0.190062 0.981772 -rot2 0 0 0.191017 0.981587 -loc1 -46.1597 -61.5771 -0 -loc2 -41.7161 -61.875 -0 +vanimation anim/a/49 -start 1.5 -dur 0.03125 -objectTrsf a -rot1 0 0 0.191017 0.981587 -rot2 0 0 0.190062 0.981772 -loc1 -41.7161 -61.875 -0 -loc2 -37.3381 -61.5771 -0 +vanimation anim/a/50 -start 1.53125 -dur 0.03125 -objectTrsf a -rot1 0 0 0.190062 0.981772 -rot2 0 0 0.187207 0.98232 -loc1 -37.3381 -61.5771 -0 -loc2 -33.0668 -60.6861 -0 +vanimation anim/a/51 -start 1.5625 -dur 0.03125 -objectTrsf a -rot1 0 0 0.187207 0.98232 -rot2 0 0 0.182491 0.983208 -loc1 -33.0668 -60.6861 -0 -loc2 -28.9399 -59.2107 -0 +vanimation anim/a/52 -start 1.59375 -dur 0.03125 -objectTrsf a -rot1 0 0 0.182491 0.983208 -rot2 0 0 0.175973 0.984395 -loc1 -28.9399 -59.2107 -0 -loc2 -24.9922 -57.165 -0 +vanimation anim/a/53 -start 1.625 -dur 0.03125 -objectTrsf a -rot1 0 0 0.175973 0.984395 -rot2 0 0 0.167737 0.985832 -loc1 -24.9922 -57.165 -0 -loc2 -21.2549 -54.5689 -0 +vanimation anim/a/54 -start 1.65625 -dur 0.03125 -objectTrsf a -rot1 0 0 0.167737 0.985832 -rot2 0 0 0.157881 0.987458 -loc1 -21.2549 -54.5689 -0 -loc2 -17.756 -51.4472 -0 +vanimation anim/a/55 -start 1.6875 -dur 0.03125 -objectTrsf a -rot1 0 0 0.157881 0.987458 -rot2 0 0 0.146521 0.989208 -loc1 -17.756 -51.4472 -0 -loc2 -14.5202 -47.83 -0 +vanimation anim/a/56 -start 1.71875 -dur 0.03125 -objectTrsf a -rot1 0 0 0.146521 0.989208 -rot2 0 0 0.133785 0.99101 -loc1 -14.5202 -47.83 -0 -loc2 -11.5693 -43.7522 -0 +vanimation anim/a/57 -start 1.75 -dur 0.03125 -objectTrsf a -rot1 0 0 0.133785 0.99101 -rot2 0 0 0.119812 0.992797 -loc1 -11.5693 -43.7522 -0 -loc2 -8.92259 -39.2531 -0 +vanimation anim/a/58 -start 1.78125 -dur 0.03125 -objectTrsf a -rot1 0 0 0.119812 0.992797 -rot2 0 0 0.104746 0.994499 -loc1 -8.92259 -39.2531 -0 -loc2 -6.59642 -34.3759 -0 +vanimation anim/a/59 -start 1.8125 -dur 0.03125 -objectTrsf a -rot1 0 0 0.104746 0.994499 -rot2 0 0 0.0887369 0.996055 -loc1 -6.59642 -34.3759 -0 -loc2 -4.60486 -29.1677 -0 +vanimation anim/a/60 -start 1.84375 -dur 0.03125 -objectTrsf a -rot1 0 0 0.0887369 0.996055 -rot2 0 0 0.0719395 0.997409 -loc1 -4.60486 -29.1677 -0 -loc2 -2.95964 -23.6785 -0 +vanimation anim/a/61 -start 1.875 -dur 0.03125 -objectTrsf a -rot1 0 0 0.0719395 0.997409 -rot2 0 0 0.0545094 0.998513 -loc1 -2.95964 -23.6785 -0 -loc2 -1.67027 -17.9614 -0 +vanimation anim/a/62 -start 1.90625 -dur 0.03125 -objectTrsf a -rot1 0 0 0.0545094 0.998513 -rot2 0 0 0.036604 0.99933 -loc1 -1.67027 -17.9614 -0 -loc2 -0.744076 -12.0712 -0 +vanimation anim/a/63 -start 1.9375 -dur 0.03125 -objectTrsf a -rot1 0 0 0.036604 0.99933 -rot2 0 0 0.0183813 0.999831 -loc1 -0.744076 -12.0712 -0 -loc2 -0.186279 -6.06481 -0 +vanimation anim/a/64 -start 1.96875 -dur 0.03125 -objectTrsf a -rot1 0 0 0.0183813 0.999831 -rot2 0 0 4.59243e-17 1 -loc1 -0.186279 -6.06481 -0 -loc2 3.79627e-31 -1.5155e-14 -0 + +# take screenshots in non-interactive mode +for {set i 0} {$i <= 10} {incr i} { vanimation anim -play [expr 2.0 * $i / 10] 0; set anIndex [format "%02d" $i]; vdump $imagedir/${casename}_$anIndex.png } + +puts "Put the following command to start interactive animation:" +puts " vanimation anim -play -playSpeed 0.2" diff --git a/tests/v3d/anim/rotate b/tests/v3d/anim/rotate new file mode 100644 index 0000000000..ab16eb6ab0 --- /dev/null +++ b/tests/v3d/anim/rotate @@ -0,0 +1,34 @@ +puts "==================================" +puts "Viewer animation - rotate the view camera" +puts "==================================" + +pload MODELING VISUALIZATION + +vclear +vinit View1 +vaxo +vzbufftrihedron + +box b1 -50 -50 0 100 100 100 +vdisplay -noupdate -dispMode 1 b1 +vfit -noupdate + +# Animation simulates the following rotation: +# vrotate 2 0 0 +vanimation anim -clear +vanimation anim/movecam -view -at1 0 0 50 -at2 0 0 50 -eye1 100 -100 150 -eye2 -153 -70 8 -duration 3 + +vanimation anim -play 0.0 0.0 +if {[vreadpixel 306 280 rgb name] != "DARKGOLDENROD3" || [vreadpixel 325 280 rgb name] != "DARKGOLDENROD3"} { puts "Error: Camera rotate result is wrong!" } +vdump $imagedir/${casename}_0.png + +vanimation anim -play 1.0 0.0 +if {[vreadpixel 306 280 rgb name] != "DARKORANGE4" || [vreadpixel 325 280 rgb name] != "BLACK"} { puts "Error: Camera rotate result is wrong!" } +vdump $imagedir/${casename}_1.png + +vanimation anim -play 2.0 0.0 +if {[vreadpixel 306 280 rgb name] != "GOLDENROD2" || [vreadpixel 325 280 rgb name] != "GOLDENROD2"} { puts "Error: Camera rotate result is wrong!" } +vdump $imagedir/${casename}_2.png + +puts "Put the following command to start interactive animation:" +puts " vanimation anim -play" diff --git a/tests/v3d/anim/scale b/tests/v3d/anim/scale new file mode 100644 index 0000000000..5037f82c1e --- /dev/null +++ b/tests/v3d/anim/scale @@ -0,0 +1,33 @@ +puts "==================================" +puts "Viewer animation - scale the view camera" +puts "==================================" + +pload MODELING VISUALIZATION + +vclear +vinit View1 +vaxo +vzbufftrihedron + +box b1 -50 -50 0 100 100 100 +vdisplay -noupdate -dispMode 1 b1 +vfit -noupdate +vzoom 0.2 + +vanimation anim -clear +vanimation anim/zoom -view -scale1 1.2 -scale2 4.8 -duration 2 + +vanimation anim -play 0.0 0.0 +if {[vreadpixel 230 220 rgb name] != "DARKGOLDENROD3" || [vreadpixel 250 220 rgb name] != "BLACK"} { puts "Error: Camera scale result is wrong!" } +vdump $imagedir/${casename}_0.png + +vanimation anim -play 1.0 0.0 +if {[vreadpixel 250 220 rgb name] != "DARKGOLDENROD3" || [vreadpixel 270 220 rgb name] != "BLACK"} { puts "Error: Camera scale result is wrong!" } +vdump $imagedir/${casename}_1.png + +vanimation anim -play 2.0 0.0 +if {[vreadpixel 334 220 rgb name] != "DARKGOLDENROD3" || [vreadpixel 350 220 rgb name] != "BLACK"} { puts "Error: Camera scale result is wrong!" } +vdump $imagedir/${casename}_2.png + +puts "Put the following command to start interactive animation:" +puts " vanimation anim -play" diff --git a/tests/v3d/anim/translate b/tests/v3d/anim/translate new file mode 100644 index 0000000000..34caf670d0 --- /dev/null +++ b/tests/v3d/anim/translate @@ -0,0 +1,35 @@ +puts "==================================" +puts "Viewer animation - translate the view camera" +puts "==================================" + +pload MODELING VISUALIZATION + +vclear +vinit View1 +vaxo +vzbufftrihedron -position right_lower + +box b1 -50 -50 0 100 100 100 +vdisplay -noupdate -dispMode 1 b1 +vviewparams -scale 1.156 -up -0.3588 0.3458 0.867 -at 116 355 327 -eye 225 253 413 + +# Animation simulates the following panning: +# vpan 200 0 +# vviewparams -scale 1.156 -up -0.3588 0.3458 0.867 -at -174 47 330 -eye -65 -55 415 +vanimation anim -clear +vanimation anim/movecam -view -at1 116 355 327 -at2 -174 47 330 -eye1 225 253 413 -eye2 -65 -55 415 -duration 2 + +vanimation anim -play 0.0 0.0 +if {[vreadpixel 60 360 rgb name] != "GOLDENROD3"} { puts "Error: Camera translation result is wrong!" } +vdump $imagedir/${casename}_0.png + +vanimation anim -play 1.0 0.0 +if {[vreadpixel 160 360 rgb name] != "GOLDENROD3"} { puts "Error: Camera translation result is wrong!" } +vdump $imagedir/${casename}_1.png + +vanimation anim -play 2.0 0.0 +if {[vreadpixel 260 360 rgb name] != "GOLDENROD3"} { puts "Error: Camera translation result is wrong!" } +vdump $imagedir/${casename}_2.png + +puts "Put the following command to start interactive animation:" +puts " vanimation anim -play" diff --git a/tests/v3d/end b/tests/v3d/end index 3fbd32339d..ec78119b1c 100755 --- a/tests/v3d/end +++ b/tests/v3d/end @@ -1,4 +1,6 @@ -catch { vfit } +if { [info exists subgroup] && $subgroup != "motion" && $subgroup != "ivtk" } { + catch { vfit } +} if { [info exists subgroup] && $subgroup == "raytrace" } { # dump final image for raytraced visualization tests diff --git a/tests/v3d/grids.list b/tests/v3d/grids.list index bb50862310..778d7df34c 100644 --- a/tests/v3d/grids.list +++ b/tests/v3d/grids.list @@ -16,3 +16,4 @@ 017 mesh 018 point_cloud 019 manipulator +020 anim diff --git a/tests/v3d/raytrace/bug26070 b/tests/v3d/raytrace/bug26070 index fed4e920a0..74f54fbc05 100755 --- a/tests/v3d/raytrace/bug26070 +++ b/tests/v3d/raytrace/bug26070 @@ -66,5 +66,5 @@ vsetdispmode 1 vfit vrenderparams -rayTrace -reflections -vlocrotate res 0 0 0 0 0 1 180 +vlocation res -rotate 0 0 0 0 0 1 180 vfit