diff --git a/common/camera.cpp b/common/camera.cpp index dfb71309..30912eba 100644 --- a/common/camera.cpp +++ b/common/camera.cpp @@ -739,7 +739,7 @@ void lcCamera::ZoomExtents(float Aspect, const lcVector3& Center, const lcVector { lcVector3 Position(mPosition + Center - mTargetPosition); - lcMatrix44 Projection = lcMatrix44Perspective(m_fovy, Aspect, m_zNear, m_zFar); + lcMatrix44 Projection = lcMatrix44Perspective(m_fovy, Aspect, m_zNear, m_zFar); // todo: doesn't work on ortho cameras, and review all places where lcMatrix44Perspective is called mPosition = lcZoomExtents(Position, mWorldView, Projection, Points, NumPoints); mTargetPosition = Center; @@ -754,23 +754,14 @@ void lcCamera::ZoomExtents(float Aspect, const lcVector3& Center, const lcVector UpdatePosition(Step); } -void lcCamera::ZoomRegion(const lcVector3* Points, float RatioX, float RatioY, lcStep Step, bool AddKey) +void lcCamera::ZoomRegion(const lcMatrix44& ProjectionMatrix, const lcVector3& Position, const lcVector3& TargetPosition, const lcVector3* Corners, lcStep Step, bool AddKey) { - // Center camera. - lcVector3 Eye = mPosition; - Eye = Eye + (Points[0] - Points[1]); + lcMatrix44 WorldView = lcMatrix44LookAt(Position, TargetPosition, mUpVector); - lcVector3 Target = mTargetPosition; - Target = Target + (Points[0] - Points[1]); + mPosition = lcZoomExtents(Position, WorldView, ProjectionMatrix, Corners, 2); + mTargetPosition = TargetPosition; + mOrthoTarget = TargetPosition; - // Zoom in/out. - float ZoomFactor = -lcMax(RatioX, RatioY) + 0.75f; - - lcVector3 Dir = Points[1] - Points[2]; - mPosition = Eye + Dir * ZoomFactor; - mTargetPosition = Target + Dir * ZoomFactor; - - // Change the camera and redraw. if (IsSimple()) AddKey = false; diff --git a/common/camera.h b/common/camera.h index 50f6d876..20c447e5 100644 --- a/common/camera.h +++ b/common/camera.h @@ -263,7 +263,7 @@ public: void CopyPosition(const lcCamera* camera); void ZoomExtents(float Aspect, const lcVector3& Center, const lcVector3* Points, int NumPoints, lcStep Step, bool AddKey); - void ZoomRegion(const lcVector3* Points, float RatioX, float RatioY, lcStep Step, bool AddKey); + void ZoomRegion(const lcMatrix44& ProjectionMatrix, const lcVector3& Position, const lcVector3& TargetPosition, const lcVector3* Corners, lcStep Step, bool AddKey); void Zoom(float Distance, lcStep Step, bool AddKey); void Pan(const lcVector3& Distance, lcStep Step, bool AddKey); void Orbit(float DistanceX, float DistanceY, const lcVector3& CenterPosition, lcStep Step, bool AddKey); diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 80f65576..e90659fd 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -2473,6 +2473,23 @@ lcVector3 lcModel::GetFocusOrSelectionCenter() const return Center; } +lcVector3 lcModel::GetSelectionOrModelCenter() const +{ + lcVector3 Center; + + if (!GetSelectionCenter(Center)) + { + float BoundingBox[6]; + + if (GetPiecesBoundingBox(BoundingBox)) + Center = lcVector3((BoundingBox[0] + BoundingBox[3]) / 2, (BoundingBox[1] + BoundingBox[4]) / 2, (BoundingBox[2] + BoundingBox[5]) / 2); + else + Center = lcVector3(0.0f, 0.0f, 0.0f); + } + + return Center; +} + bool lcModel::GetFocusPosition(lcVector3& Position) const { lcObject* FocusObject = GetFocusObject(); @@ -3250,9 +3267,9 @@ void lcModel::UpdateRollTool(lcCamera* Camera, float Mouse) gMainWindow->UpdateAllViews(); } -void lcModel::ZoomRegionToolClicked(lcCamera* Camera, const lcVector3* Points, float RatioX, float RatioY) +void lcModel::ZoomRegionToolClicked(lcCamera* Camera, const lcMatrix44& ProjectionMatrix, const lcVector3& Position, const lcVector3& TargetPosition, const lcVector3* Corners) { - Camera->ZoomRegion(Points, RatioX, RatioY, mCurrentStep, gMainWindow->GetAddKeys()); + Camera->ZoomRegion(ProjectionMatrix, Position, TargetPosition, Corners, mCurrentStep, gMainWindow->GetAddKeys()); gMainWindow->UpdateFocusObject(GetFocusObject()); gMainWindow->UpdateAllViews(); diff --git a/common/lc_model.h b/common/lc_model.h index 4a654b24..612f2c65 100644 --- a/common/lc_model.h +++ b/common/lc_model.h @@ -232,6 +232,7 @@ public: bool GetPieceFocusOrSelectionCenter(lcVector3& Center) const; bool GetFocusOrSelectionCenter(lcVector3& Center) const; lcVector3 GetFocusOrSelectionCenter() const; + lcVector3 GetSelectionOrModelCenter() const; bool GetFocusPosition(lcVector3& Position) const; lcObject* GetFocusObject() const; bool GetSelectionCenter(lcVector3& Center) const; @@ -284,7 +285,7 @@ public: void UpdatePanTool(lcCamera* Camera, const lcVector3& Distance); void UpdateOrbitTool(lcCamera* Camera, float MouseX, float MouseY); void UpdateRollTool(lcCamera* Camera, float Mouse); - void ZoomRegionToolClicked(lcCamera* Camera, const lcVector3* Points, float RatioX, float RatioY); + void ZoomRegionToolClicked(lcCamera* Camera, const lcMatrix44& ProjectionMatrix, const lcVector3& Position, const lcVector3& TargetPosition, const lcVector3* Corners); void LookAt(lcCamera* Camera); void ZoomExtents(lcCamera* Camera, float Aspect); void Zoom(lcCamera* Camera, float Amount); diff --git a/common/view.cpp b/common/view.cpp index bb94d995..2448ccfd 100644 --- a/common/view.cpp +++ b/common/view.cpp @@ -1922,19 +1922,29 @@ void View::StopTracking(bool Accept) case LC_TOOL_ZOOM_REGION: { - lcVector3 Points[3] = + if (mInputState.x == mMouseDownX || mInputState.y == mMouseDownY) + break; + + lcVector3 Points[6] = { - lcVector3((mMouseDownX + lcMin(mInputState.x, mWidth - 1)) / 2, (mMouseDownY + lcMin(mInputState.y, mHeight - 1)) / 2, 0.9f), - lcVector3((float)mWidth / 2.0f, (float)mHeight / 2.0f, 0.9f), - lcVector3((float)mWidth / 2.0f, (float)mHeight / 2.0f, 0.1f), + lcVector3((mMouseDownX + lcMin(mInputState.x, mWidth - 1)) / 2, (mMouseDownY + lcMin(mInputState.y, mHeight - 1)) / 2, 0.0f), + lcVector3((mMouseDownX + lcMin(mInputState.x, mWidth - 1)) / 2, (mMouseDownY + lcMin(mInputState.y, mHeight - 1)) / 2, 1.0f), + lcVector3((float)mInputState.x, (float)mInputState.y, 0.0f), + lcVector3((float)mInputState.x, (float)mInputState.y, 1.0f), + lcVector3(mMouseDownX, mMouseDownY, 0.0f), + lcVector3(mMouseDownX, mMouseDownY, 1.0f) }; - UnprojectPoints(Points, 3); + UnprojectPoints(Points, 5); - float RatioX = (mMouseDownX - mInputState.x) / mWidth; - float RatioY = (mMouseDownY - mInputState.y) / mHeight; + lcVector3 Center = mModel->GetSelectionOrModelCenter(); - mModel->ZoomRegionToolClicked(mCamera, Points, fabsf(RatioX), fabsf(RatioY)); + lcVector3 PlaneNormal(mCamera->mPosition - mCamera->mTargetPosition); + lcVector4 Plane(PlaneNormal, -lcDot(PlaneNormal, Center)); + lcVector3 Target, Corners[2]; + + if (lcLinePlaneIntersection(&Target, Points[0], Points[1], Plane) && lcLinePlaneIntersection(&Corners[0], Points[2], Points[3], Plane) && lcLinePlaneIntersection(&Corners[1], Points[3], Points[4], Plane)) + mModel->ZoomRegionToolClicked(mCamera, GetProjectionMatrix(), Points[0], Target, Corners); } break; } @@ -2405,7 +2415,7 @@ void View::OnMouseMove() const lcVector3& CurrentEnd = Points[1]; const lcVector3& MouseDownStart = Points[2]; const lcVector3& MouseDownEnd = Points[3]; - lcVector3 Center = mModel->GetFocusOrSelectionCenter(); + lcVector3 Center = mModel->GetSelectionOrModelCenter(); lcVector3 PlaneNormal(mCamera->mPosition - mCamera->mTargetPosition); lcVector4 Plane(PlaneNormal, -lcDot(PlaneNormal, Center));