diff --git a/toonz/sources/tnztools/assistants/assistantellipse.cpp b/toonz/sources/tnztools/assistants/assistantellipse.cpp index 31a8965..dbca015 100644 --- a/toonz/sources/tnztools/assistants/assistantellipse.cpp +++ b/toonz/sources/tnztools/assistants/assistantellipse.cpp @@ -406,11 +406,27 @@ void TAssistantEllipse::drawParallelGrid( const TAffine &ellipseMatrix, const TPointD &grid0, const TPointD &grid1, + const TPointD *bound0, + const TPointD *bound1, bool perspective, bool perspectiveDepth, bool repeat, double alpha ) { + struct { + const bool repeat; + const TAffine ellipseMatrixInv; + double convert(const TPointD &p) { + TPointD pp = ellipseMatrixInv*p; + if (repeat) + pp.x -= round(pp.x/2)*2; + if (!(fabs(pp.x) < 1 - TConsts::epsilon)) + return pp.y < 0 ? -INFINITY : INFINITY; + return pp.y/sqrt(1 - pp.x*pp.x); + } + } helper = { repeat, ellipseMatrix.inv() }; + + TAffine4 modelview, projection; glGetDoublev(GL_MODELVIEW_MATRIX, modelview.a); glGetDoublev(GL_PROJECTION_MATRIX, projection.a); @@ -419,26 +435,42 @@ void TAssistantEllipse::drawParallelGrid( double pixelSize = sqrt(tglGetPixelSize2()); double minStep = (perspective ? 5 : 10)*pixelSize; - TAffine ellipseMatrixInv = ellipseMatrix.inv(); const TAffine &em = ellipseMatrix; double r = sqrt(0.5*(norm2(TPointD(em.a11, em.a21)) + norm2(TPointD(em.a12, em.a22)))); double actualMinStep = minStep/r; - TPointD g0 = ellipseMatrixInv*grid0; - TPointD g1 = ellipseMatrixInv*grid1; - if (repeat) - { g0.x -= round(0.5*g0.x)*2.0; g1.x -= round(0.5*g1.x)*2.0; } - if (fabs(g0.x) >= 1.0 - TConsts::epsilon) return; - if (fabs(g1.x) >= 1.0 - TConsts::epsilon) return; - double gs0 = g0.y/sqrt(1.0 - g0.x*g0.x); - double gs1 = g1.y/sqrt(1.0 - g1.x*g1.x); - if (fabs(gs0) >= 1.0 - TConsts::epsilon) return; - if (fabs(gs1) >= 1.0 - TConsts::epsilon) return; - + + // convert grid + double gs0 = helper.convert(grid0); + double gs1 = helper.convert(grid1); + if (!(fabs(gs0) < 1 - TConsts::epsilon)) return; + if (!(fabs(gs1) < 1 - TConsts::epsilon)) return; + + // convert bounds + double bs0 = -INFINITY, bs1 = INFINITY; + if (bound0 && bound1) { + bs0 = helper.convert(*bound0); + bs1 = helper.convert(*bound1); + } else + if (bound0) { + bs0 = helper.convert(*bound0); + if (bs0 < 0) bs1 = -INFINITY; + } else + if (bound1) { + bs1 = helper.convert(*bound1); + if (bs1 < 0) bs0 = INFINITY; + } + + if (bs0 > bs1) std::swap(bs0, bs1); + bs0 -= TConsts::epsilon; + bs1 += TConsts::epsilon; + + // prepare ranges TAngleRangeSet ranges; ranges.add( TAngleRangeSet::fromDouble(0.0), TAngleRangeSet::fromDouble(M_PI) ); if (perspectiveDepth) { + // draw perspective depth if (!( fabs(gs0) > TConsts::epsilon && fabs(gs1) > TConsts::epsilon && fabs(gs0) < 1 - TConsts::epsilon @@ -461,10 +493,13 @@ void TAssistantEllipse::drawParallelGrid( double curAlpha = (curStep - actualMinStep)/actualMinStep; if (curAlpha < 0) { if (i == i0) continue; else break; } if (curAlpha > 1) curAlpha = 1; - + + x *= sign; + if (x < bs0 || bs1 < x) continue; + drawEllipseRanges( ranges, - ellipseMatrix*TAffine::scale(sign, x*sign), + ellipseMatrix*TAffine::scale(sign, x), screenMatrixInv, pixelSize, alpha * curAlpha ); @@ -494,6 +529,7 @@ void TAssistantEllipse::drawParallelGrid( if (curAlpha < 0) { if (i == i0) continue; else break; } if (curAlpha > 1) curAlpha = 1; } + if (x < bs0 || bs1 < x) continue; drawEllipseRanges( ranges, @@ -506,13 +542,15 @@ void TAssistantEllipse::drawParallelGrid( // draw linear double dx = fabs(gs1 - gs0); if (dx < actualMinStep) return; - for(double x = gs0 + ceil((-1.0 - gs0)/dx)*dx; x < 1.0; x += dx) + for(double x = gs0 + ceil((-1.0 - gs0)/dx)*dx; x < 1.0; x += dx) { + if (x < bs0 || bs1 < x) continue; drawEllipseRanges( ranges, ellipseMatrix*TAffine::scale(x < 0.0 ? -1.0 : 1.0, x), screenMatrixInv, pixelSize, alpha ); + } } } @@ -566,6 +604,8 @@ void TAssistantEllipse::draw( ellipseMatrix, m_grid0.position, m_grid1.position, + nullptr, + nullptr, getPerspective(), getPerspectiveDepth(), getRepeat(), diff --git a/toonz/sources/tnztools/assistants/assistantellipse.h b/toonz/sources/tnztools/assistants/assistantellipse.h index 0838cf2..394ea96 100644 --- a/toonz/sources/tnztools/assistants/assistantellipse.h +++ b/toonz/sources/tnztools/assistants/assistantellipse.h @@ -110,6 +110,8 @@ public: const TAffine &ellipseMatrix, const TPointD &grid0, const TPointD &grid1, + const TPointD *bound0, + const TPointD *bound1, bool perspective, bool perspectiveDepth, bool repeat, diff --git a/toonz/sources/tnztools/assistants/assistantfisheye.cpp b/toonz/sources/tnztools/assistants/assistantfisheye.cpp index d91fca4..6ebfe5f 100644 --- a/toonz/sources/tnztools/assistants/assistantfisheye.cpp +++ b/toonz/sources/tnztools/assistants/assistantfisheye.cpp @@ -24,6 +24,7 @@ public: const TStringId m_idCircle; const TStringId m_idGrid; const TStringId m_idGridDepth; + const TStringId m_idFlipGrids; protected: TAssistantPoint &m_center; @@ -40,6 +41,7 @@ public: m_idCircle("circle"), m_idGrid("grid"), m_idGridDepth("gridDepth"), + m_idFlipGrids("flipGrids"), m_center( addPoint("center", TAssistantPoint::CircleCross) ), m_a( addPoint("a", TAssistantPoint::CircleFill, TPointD(200, 0)) ), m_b( addPoint("b", TAssistantPoint::Circle, TPointD( 0, 200)) ), @@ -51,6 +53,7 @@ public: addProperty( new TBoolProperty(m_idCircle.str(), getCircle()) ); addProperty( new TBoolProperty(m_idGrid.str(), getGrid()) ); addProperty( new TBoolProperty(m_idGridDepth.str(), getGridDepth()) ); + addProperty( new TBoolProperty(m_idFlipGrids.str(), getFlipGrids()) ); } static QString getLocalName() @@ -61,6 +64,7 @@ public: setTranslation(m_idCircle, tr("Circle")); setTranslation(m_idGrid, tr("Grid")); setTranslation(m_idGridDepth, tr("Depth Grid")); + setTranslation(m_idFlipGrids, tr("Flip Grids")); } inline bool getCircle() const @@ -69,6 +73,8 @@ public: { return data()[m_idGrid].getBool(); } inline bool getGridDepth() const { return data()[m_idGridDepth].getBool(); } + inline bool getFlipGrids() const + { return data()[m_idFlipGrids].getBool(); } void onDataChanged(const TVariant &value) override { TAssistant::onDataChanged(value); @@ -120,6 +126,17 @@ private: m_gridD1.position = dgD1*da0/la0*da1 + dgD1*db0/lb0*db1 + center; } + void fixGridD1() { + TAffine em = calcEllipseMatrix(); + TAffine emi = em.inv(); + TPointD d0 = emi*m_gridD0.position; + TPointD d1 = emi*m_gridD1.position; + double l0 = norm2(d0); + double l1 = norm2(d1); + if ( l0 > TConsts::epsilon*TConsts::epsilon + && l1 > TConsts::epsilon*TConsts::epsilon ) + m_gridD1.position = em*( d0*sqrt(l1/l0) ); + } public: void onMovePoint(TAssistantPoint &point, const TPointD &position) override { @@ -138,6 +155,9 @@ public: } else if (&point == &m_a || &point == &m_b) { fixBAndGrid(prevCenter, prevA, prevB); + } else + if (&point == &m_gridD0 || &point == &m_gridD1) { + fixGridD1(); } } @@ -204,9 +224,13 @@ public: } public: - void draw(TToolViewer *viewer, bool enabled) const override { + void draw(TToolViewer*, bool enabled) const override { TAffine ellipseMatrix = calcEllipseMatrix(); if (ellipseMatrix.isZero()) return; + + TAffine ellipseMatrix2 = ellipseMatrix; + std::swap(ellipseMatrix.a11, ellipseMatrix.a12); + std::swap(ellipseMatrix.a21, ellipseMatrix.a22); // common data about viewport const TRectD oneBox(-1.0, -1.0, 1.0, 1.0); @@ -219,6 +243,7 @@ public: double pixelSize = sqrt(tglGetPixelSize2()); const double crossSize = 0.1; double alpha = getDrawingAlpha(enabled); + double gridAlpha = getDrawingGridAlpha(); drawSegment( ellipseMatrix*TPointD(-crossSize, 0.0), ellipseMatrix*TPointD( crossSize, 0.0), pixelSize, alpha); @@ -226,50 +251,57 @@ public: ellipseMatrix*TPointD(0.0, crossSize), pixelSize, alpha); TAssistantEllipse::drawEllipse(ellipseMatrix, matrixInv, pixelSize, alpha); + const TPointD *bound = getGrid() && getGridDepth() ? &m_gridD0.position : nullptr; + const TPointD *boundA = nullptr; + const TPointD *boundB = bound; + if (getFlipGrids()) std::swap(boundA, boundB); + if (getGrid()) { TAssistantEllipse::drawParallelGrid( - ellipseMatrix, - m_grid0.position, - m_grid1.position, - true, - false, - false, - getDrawingGridAlpha() ); - - std::swap(ellipseMatrix.a11, ellipseMatrix.a12); - std::swap(ellipseMatrix.a21, ellipseMatrix.a22); - + ellipseMatrix, m_grid0.position, m_grid1.position, + boundA, boundB, true, false, false, gridAlpha ); TAssistantEllipse::drawParallelGrid( - ellipseMatrix, - m_grid0.position, - m_grid1.position, - true, - false, - false, - getDrawingGridAlpha() ); + ellipseMatrix2, m_grid0.position, m_grid1.position, + boundA, boundB, true, false, false, gridAlpha ); } if (getGridDepth()) { TAssistantEllipse::drawParallelGrid( - ellipseMatrix, - m_gridD0.position, - m_gridD1.position, - false, - true, - false, - getDrawingGridAlpha() ); - - std::swap(ellipseMatrix.a11, ellipseMatrix.a12); - std::swap(ellipseMatrix.a21, ellipseMatrix.a22); - + ellipseMatrix, m_gridD0.position, m_gridD1.position, + boundB, boundA, false, true, false, gridAlpha ); TAssistantEllipse::drawParallelGrid( - ellipseMatrix, - m_gridD0.position, - m_gridD1.position, - false, - true, - false, - getDrawingGridAlpha() ); + ellipseMatrix2, m_gridD0.position, m_gridD1.position, + boundB, boundA, false, true, false, gridAlpha ); + } + + if (bound) { + TPointD b = ellipseMatrix.inv()*(*bound); + double r = norm2(b); + if (r < 1 - TConsts::epsilon) { + double bx = b.x/sqrt(1 - b.y*b.y); + double by = b.y/sqrt(1 - b.x*b.x); + + TAngleRangeSet ranges; + ranges.add( TAngleRangeSet::fromDouble(-M_PI/2), TAngleRangeSet::fromDouble(M_PI/2) ); + TAssistantEllipse::drawEllipseRanges( + ranges, + ellipseMatrix*TAffine::scale(bx, 1), + matrixInv, + pixelSize, + alpha ); + + ranges.clear(); + ranges.add( TAngleRangeSet::fromDouble(0.0), TAngleRangeSet::fromDouble(M_PI) ); + TAssistantEllipse::drawEllipseRanges( + ranges, + ellipseMatrix*TAffine::scale(1, by), + matrixInv, + pixelSize, + alpha ); + + TPointD bb = bound == boundA ? TPointD(0, 0) : b/sqrt(r); + drawSegment( ellipseMatrix*b, ellipseMatrix*bb, pixelSize, alpha ); + } } } };