diff --git a/common/camera.cpp b/common/camera.cpp index 105c3db9..f1e14b02 100644 --- a/common/camera.cpp +++ b/common/camera.cpp @@ -425,6 +425,38 @@ void lcCamera::MoveRelative(const lcVector3& Distance, lcStep Step, bool AddKey) UpdatePosition(Step); } +void lcCamera::Rotate(lcStep Step, bool AddKey, const lcMatrix33& RotationMatrix, const lcVector3& Center, const lcMatrix33& RotationFrame) +{ + if (GetFocusSection() != LC_CAMERA_SECTION_POSITION && GetFocusSection() != LC_CAMERA_SECTION_INVALID) + return; + + const lcMatrix33 LocalToWorldMatrix = lcMatrix33(mWorldView); + + const lcMatrix33 LocalToFocusMatrix = lcMul(LocalToWorldMatrix, RotationFrame); + lcMatrix33 NewLocalToWorldMatrix = lcMul(LocalToFocusMatrix, RotationMatrix); + + const lcMatrix33 WorldToLocalMatrix = lcMatrix33AffineInverse(LocalToWorldMatrix); + + lcVector3 Distance = mPosition - Center; + Distance = lcMul(Distance, WorldToLocalMatrix); + Distance = lcMul(Distance, NewLocalToWorldMatrix); + + SetPosition(Center + Distance, Step, AddKey); + + Distance = mTargetPosition - Center; + Distance = lcMul(Distance, WorldToLocalMatrix); + Distance = lcMul(Distance, NewLocalToWorldMatrix); + + SetTargetPosition(Center + Distance, Step, AddKey); + + lcVector3 UpVector = mUpVector; + + UpVector = lcMul(UpVector, WorldToLocalMatrix); + UpVector = lcMul(UpVector, NewLocalToWorldMatrix); + + SetUpVector(UpVector, Step, AddKey); +} + void lcCamera::UpdatePosition(lcStep Step) { mPosition.Update(Step); diff --git a/common/camera.h b/common/camera.h index 23b3e88e..64ca322e 100644 --- a/common/camera.h +++ b/common/camera.h @@ -35,9 +35,10 @@ enum class lcCameraType Count }; -enum lcCameraSection +enum lcCameraSection : quint32 { - LC_CAMERA_SECTION_POSITION, + LC_CAMERA_SECTION_INVALID = ~0U, + LC_CAMERA_SECTION_POSITION = 0, LC_CAMERA_SECTION_TARGET, LC_CAMERA_SECTION_UPVECTOR }; @@ -212,7 +213,7 @@ public: if (mState & LC_CAMERA_UPVECTOR_FOCUSED) return LC_CAMERA_SECTION_UPVECTOR; - return ~0U; + return LC_CAMERA_SECTION_INVALID; } quint32 GetAllowedTransforms() const override @@ -237,6 +238,30 @@ public: return lcVector3(0.0f, 0.0f, 0.0f); } + lcMatrix33 GetRelativeRotation() const + { + const quint32 Section = GetFocusSection(); + + if (Section == LC_CAMERA_SECTION_POSITION) + return lcMatrix33(mWorldView); + else + return lcMatrix33Identity(); + } + + lcVector3 GetRotationCenter() const + { + const quint32 Section = GetFocusSection(); + + if (Section != LC_CAMERA_SECTION_TARGET) + { + return mPosition; + } + else + { + return mTargetPosition; + } + } + void SaveLDraw(QTextStream& Stream) const; bool ParseLDrawLine(QTextStream& Stream); @@ -311,6 +336,7 @@ public: void Center(const lcVector3& NewCenter, lcStep Step, bool AddKey); void MoveSelected(lcStep Step, bool AddKey, const lcVector3& Distance); void MoveRelative(const lcVector3& Distance, lcStep Step, bool AddKey); + void Rotate(lcStep Step, bool AddKey, const lcMatrix33& RotationMatrix, const lcVector3& Center, const lcMatrix33& RotationFrame); void SetViewpoint(lcViewpoint Viewpoint); void SetViewpoint(const lcVector3& Position); void SetViewpoint(const lcVector3& Position, const lcVector3& Target, const lcVector3& Up); diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 98f9673d..5e5209e1 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -3092,6 +3092,14 @@ void lcModel::RotateSelectedObjects(const lcVector3& Angles, bool Relative, bool Piece->UpdatePosition(mCurrentStep); Rotated = true; } + else if (Object->IsCamera()) + { + lcCamera* Camera = (lcCamera*)Object; + + Camera->Rotate(mCurrentStep, gMainWindow->GetAddKeys(), RotationMatrix, Center, WorldToFocusMatrix); + Camera->UpdatePosition(mCurrentStep); + Rotated = true; + } else if (Object->IsLight()) { lcLight* Light = (lcLight*)Object; @@ -3130,6 +3138,30 @@ void lcModel::RotateSelectedObjects(const lcVector3& Angles, bool Relative, bool Piece->UpdatePosition(mCurrentStep); Rotated = true; } + else if (Object->IsCamera()) + { + lcCamera* Camera = (lcCamera*)Object; + + const lcVector3 Center = Camera->GetRotationCenter(); + lcMatrix33 WorldToFocusMatrix; + lcMatrix33 RelativeRotationMatrix; + + if (Relative) + { + const lcMatrix33 RelativeRotation = Camera->GetRelativeRotation(); + WorldToFocusMatrix = lcMatrix33AffineInverse(RelativeRotation); + RelativeRotationMatrix = lcMul(RotationMatrix, RelativeRotation); + } + else + { + WorldToFocusMatrix = lcMatrix33Identity(); + RelativeRotationMatrix = RotationMatrix; + } + + Camera->Rotate(mCurrentStep, gMainWindow->GetAddKeys(), RotationMatrix, Center, WorldToFocusMatrix); + Camera->UpdatePosition(mCurrentStep); + Rotated = true; + } else if (Object->IsLight()) { lcLight* Light = (lcLight*)Object; @@ -4609,8 +4641,8 @@ void lcModel::UpdateFreeMoveTool(lcPiece* MousePiece, const lcMatrix44& StartTra Camera->MoveSelected(mCurrentStep, gMainWindow->GetAddKeys(), Distance); Camera->UpdatePosition(mCurrentStep); -// Camera->Rotate(mCurrentStep, gMainWindow->GetAddKeys(), RotationMatrix, Center, WorldToFocusMatrix); -// Camera->UpdatePosition(mCurrentStep); + Camera->Rotate(mCurrentStep, gMainWindow->GetAddKeys(), RotationMatrix, Center, WorldToFocusMatrix); + Camera->UpdatePosition(mCurrentStep); } else if (Object->IsLight()) {