diff options
author | Markus Mohrhard <markus.mohrhard@collabora.co.uk> | 2014-01-22 05:46:32 +0100 |
---|---|---|
committer | Markus Mohrhard <markus.mohrhard@googlemail.com> | 2014-01-29 08:09:55 +0100 |
commit | 093fa2a359a7a25644e3983e6c525296d6bfe05c (patch) | |
tree | 8861803ae33ab6db68ca9517b136c3845c4f5dae /chart2/source | |
parent | 82ed9053e7353fe784cebac4d249cad5ed4a2bf4 (diff) |
use a direct method for pie segment crastion
Change-Id: I4b42ebe994b4e498acd32d08a063e4626b3c97d8
Diffstat (limited to 'chart2/source')
-rw-r--r-- | chart2/source/view/main/DummyXShape.cxx | 183 | ||||
-rwxr-xr-x | chart2/source/view/main/OpenGLRender.cxx | 54 | ||||
-rwxr-xr-x | chart2/source/view/main/OpenGLRender.hxx | 4 |
3 files changed, 45 insertions, 196 deletions
diff --git a/chart2/source/view/main/DummyXShape.cxx b/chart2/source/view/main/DummyXShape.cxx index 70d94c11ffdc..4788390c114c 100644 --- a/chart2/source/view/main/DummyXShape.cxx +++ b/chart2/source/view/main/DummyXShape.cxx @@ -324,168 +324,6 @@ DummyCone::DummyCone(const drawing::Position3D& rPos, const drawing::Direction3D setPosition(Position3DToAWTPoint(rPos)); setSize(Direction3DToAWTSize(rSize)); } -void appendAndCloseBezierCoords( drawing::PolyPolygonBezierCoords& rReturn, const drawing::PolyPolygonBezierCoords& rAdd, sal_Bool bAppendInverse ) -{ - if(!rAdd.Coordinates.getLength()) - return; - sal_Int32 nAddCount = rAdd.Coordinates[0].getLength(); - if(!nAddCount) - return; - - sal_Int32 nOldCount = rReturn.Coordinates[0].getLength(); - - rReturn.Coordinates[0].realloc(nOldCount+nAddCount+1); - rReturn.Flags[0].realloc(nOldCount+nAddCount+1); - - for(sal_Int32 nN=0;nN<nAddCount; nN++ ) - { - sal_Int32 nAdd = bAppendInverse ? (nAddCount-1-nN) : nN; - rReturn.Coordinates[0][nOldCount+nN] = rAdd.Coordinates[0][nAdd]; - rReturn.Flags[0][nOldCount+nN] = rAdd.Flags[0][nAdd]; - } - - //close - rReturn.Coordinates[0][nOldCount+nAddCount] = rReturn.Coordinates[0][0]; - rReturn.Flags[0][nOldCount+nAddCount] = rReturn.Flags[0][0]; -} - -drawing::PolyPolygonBezierCoords getCircularArcBezierCoords( - double fStartAngleRadian, double fWidthAngleRadian, double fUnitRadius - , const ::basegfx::B2DHomMatrix& rTransformationFromUnitCircle - , const double fAngleSubdivisionRadian ) -{ - //at least one polygon is created using two normal and two control points - //if the angle is larger it is separated into multiple sub angles - - drawing::PolyPolygonBezierCoords aReturn = drawing::PolyPolygonBezierCoords(); - sal_Int32 nSegmentCount = static_cast< sal_Int32 >( fWidthAngleRadian/fAngleSubdivisionRadian ); - if( fWidthAngleRadian > fAngleSubdivisionRadian*nSegmentCount ) - nSegmentCount++; - - double fFirstSegmentAngle = fAngleSubdivisionRadian; - double fLastSegmentAngle = fAngleSubdivisionRadian; - if(nSegmentCount==1) - { - fFirstSegmentAngle = fWidthAngleRadian; - fLastSegmentAngle = 0.0; - } - else - { - double fFirstAngleOnSubDevision = (static_cast<sal_Int32>(fStartAngleRadian/fAngleSubdivisionRadian)+1)*fAngleSubdivisionRadian; - if( !::rtl::math::approxEqual( fStartAngleRadian, fFirstAngleOnSubDevision ) ) - fFirstSegmentAngle = fFirstAngleOnSubDevision-fStartAngleRadian; - - if(nSegmentCount>1) - { - fLastSegmentAngle = fWidthAngleRadian-fFirstSegmentAngle-fAngleSubdivisionRadian*(nSegmentCount-2); - if( fLastSegmentAngle<0 ) - nSegmentCount--; - if( fLastSegmentAngle>fAngleSubdivisionRadian ) - { - fLastSegmentAngle-=fAngleSubdivisionRadian; - nSegmentCount++; - } - } - } - - sal_Int32 nPointCount = 1 + 3*nSegmentCount; //first point of next segment equals last point of former segment - - aReturn.Coordinates = drawing::PointSequenceSequence(1); - aReturn.Flags = drawing::FlagSequenceSequence(1); - - drawing::PointSequence aPoints(nPointCount); - drawing::FlagSequence aFlags(nPointCount); - - // - - //!! applying matrix to vector does ignore translation, so it is important to use a B2DPoint here instead of B2DVector - ::basegfx::B2DPoint P0,P1,P2,P3; - - sal_Int32 nPoint=0; - double fCurrentRotateAngle = fStartAngleRadian; - for(sal_Int32 nSegment=0; nSegment<nSegmentCount; nSegment++) - { - double fCurrentSegmentAngle = fAngleSubdivisionRadian; - if(nSegment==0)//first segment gets only a smaller peace until the next subdevision - fCurrentSegmentAngle = fFirstSegmentAngle; - else if(nSegment==(nSegmentCount-1)) //the last segment gets the rest angle that does not fit into equal pieces - fCurrentSegmentAngle = fLastSegmentAngle; - - //first create untransformed points for a unit circle arc: - const double fCos = cos(fCurrentSegmentAngle/2.0); - const double fSin = sin(fCurrentSegmentAngle/2.0); - P0.setX(fCos); - P3.setX(fCos); - P0.setY(-fSin); - P3.setY(-P0.getY()); - - P1.setX((4.0-fCos)/3.0); - P2.setX(P1.getX()); - P1.setY((1.0-fCos)*(fCos-3.0)/(3.0*fSin)); - P2.setY(-P1.getY()); - //transform thus startangle equals NULL - ::basegfx::B2DHomMatrix aStart; - aStart.rotate(fCurrentSegmentAngle/2.0 + fCurrentRotateAngle ); - fCurrentRotateAngle+=fCurrentSegmentAngle; - - aStart.scale( fUnitRadius, fUnitRadius ); - - //apply given transformation to get final points - P0 = rTransformationFromUnitCircle*(aStart*P0); - P1 = rTransformationFromUnitCircle*(aStart*P1); - P2 = rTransformationFromUnitCircle*(aStart*P2); - P3 = rTransformationFromUnitCircle*(aStart*P3); - - aPoints[nPoint].X = static_cast< sal_Int32 >( P0.getX()); - aPoints[nPoint].Y = static_cast< sal_Int32 >( P0.getY()); - aFlags [nPoint++] = drawing::PolygonFlags_NORMAL; - - aPoints[nPoint].X = static_cast< sal_Int32 >( P1.getX()); - aPoints[nPoint].Y = static_cast< sal_Int32 >( P1.getY()); - aFlags[nPoint++] = drawing::PolygonFlags_CONTROL; - - aPoints[nPoint].X = static_cast< sal_Int32 >( P2.getX()); - aPoints[nPoint].Y = static_cast< sal_Int32 >( P2.getY()); - aFlags [nPoint++] = drawing::PolygonFlags_CONTROL; - - if(nSegment==(nSegmentCount-1)) - { - aPoints[nPoint].X = static_cast< sal_Int32 >( P3.getX()); - aPoints[nPoint].Y = static_cast< sal_Int32 >( P3.getY()); - aFlags [nPoint++] = drawing::PolygonFlags_NORMAL; - } - } - - aReturn.Coordinates[0] = aPoints; - aReturn.Flags[0] = aFlags; - - return aReturn; -} - - -drawing::PolyPolygonBezierCoords getRingBezierCoords( - double fUnitCircleInnerRadius - , double fUnitCircleOuterRadius - , double fStartAngleRadian, double fWidthAngleRadian - , ::basegfx::B2DHomMatrix aTransformationFromUnitCircle - , const double fAngleSubdivisionRadian ) -{ - drawing::PolyPolygonBezierCoords aReturn = drawing::PolyPolygonBezierCoords(); - - aReturn.Coordinates = drawing::PointSequenceSequence(1); - aReturn.Flags = drawing::FlagSequenceSequence(1); - - drawing::PolyPolygonBezierCoords aOuterArc = getCircularArcBezierCoords( - fStartAngleRadian, fWidthAngleRadian, fUnitCircleOuterRadius, aTransformationFromUnitCircle, fAngleSubdivisionRadian ); - aReturn.Coordinates[0] = aOuterArc.Coordinates[0]; - aReturn.Flags[0] = aOuterArc.Flags[0]; - - drawing::PolyPolygonBezierCoords aInnerArc = getCircularArcBezierCoords( - fStartAngleRadian, fWidthAngleRadian, fUnitCircleInnerRadius, aTransformationFromUnitCircle, fAngleSubdivisionRadian ); - appendAndCloseBezierCoords( aReturn, aInnerArc, sal_True ); - - return aReturn; -} DummyPieSegment2D::DummyPieSegment2D(double fUnitCircleStartAngleDegree, double fUnitCircleWidthAngleDegree, double fUnitCircleInnerRadius, double fUnitCircleOuterRadius, @@ -506,21 +344,9 @@ void DummyPieSegment2D::render() mfUnitCircleWidthAngleDegree -= 360.0; while(mfUnitCircleWidthAngleDegree<0) mfUnitCircleWidthAngleDegree += 360.0; - ::basegfx::B2DHomMatrix aTransformationFromUnitCircle( IgnoreZ( HomogenMatrixToB3DHomMatrix(maUnitCircleToScene) ) ); - aTransformationFromUnitCircle.translate(maOffset.DirectionX,maOffset.DirectionY); - const double fAngleSubdivisionRadian = F_PI/30.0; - drawing::PolyPolygonBezierCoords aCoords = getRingBezierCoords( - mfUnitCircleInnerRadius, mfUnitCircleOuterRadius - , mfUnitCircleStartAngleDegree*F_PI/180.0, mfUnitCircleWidthAngleDegree*F_PI/180.0 - , aTransformationFromUnitCircle, fAngleSubdivisionRadian ); - - sal_Int32 pointCount = aCoords.Coordinates[0].getLength(); - for (sal_Int32 i = 0; i < pointCount; i++) - { - com::sun::star::awt::Point p = aCoords.Coordinates[0][i]; - pChart->m_GLRender.SetPieSegment2DShapePoint((float)p.X, (float)p.Y, pointCount); - } + pChart->m_GLRender.GeneratePieSegment2D(mfUnitCircleInnerRadius, mfUnitCircleOuterRadius, + mfUnitCircleStartAngleDegree, mfUnitCircleWidthAngleDegree); std::map<OUString, uno::Any>::const_iterator itr = maProperties.find(UNO_NAME_FILLCOLOR); if(itr != maProperties.end()) @@ -528,14 +354,17 @@ void DummyPieSegment2D::render() sal_Int32 nColor = itr->second.get<sal_Int32>(); pChart->m_GLRender.SetColor(nColor); } + /* itr = maProperties.find(UNO_NAME_FILL_TRANSPARENCE); if(itr != maProperties.end()) { sal_Int32 transparency = itr->second.get<sal_Int32>(); pChart->m_GLRender.SetTransparency(transparency&(0xFF)); } + */ - pChart->m_GLRender.RenderPieSegment2DShape(); + float nSize = std::max<float>(maUnitCircleToScene.Line1.Column1, maUnitCircleToScene.Line2.Column2); + pChart->m_GLRender.RenderPieSegment2DShape(nSize, maUnitCircleToScene.Line1.Column4, maUnitCircleToScene.Line2.Column4); } diff --git a/chart2/source/view/main/OpenGLRender.cxx b/chart2/source/view/main/OpenGLRender.cxx index 0419a5777916..35f33e43b6b7 100755 --- a/chart2/source/view/main/OpenGLRender.cxx +++ b/chart2/source/view/main/OpenGLRender.cxx @@ -1726,32 +1726,51 @@ void OpenGLRender::SetChartTransparencyGradient(long transparencyGradient) m_BackgroundColor[15] = 0.0; } } -int OpenGLRender::SetPieSegment2DShapePoint(float x, float y, int listLength) + +void OpenGLRender::GeneratePieSegment2D(double fInnerRadius, double fOutterRadius, double nAngleStart, double nAngleWidth) { - if (m_PieSegment2DPointList.empty()) + double nAngleStep = 1; + PieSegment2DPointList aPointList; + // TODO: moggi: GL_TRIANGLE_FAN seems not to work + bool bInnerRadiusNotZero = true; //!rtl::math::approxEqual(0.0, fInnerRadius); + size_t nVectorSize = 3*(nAngleWidth/nAngleStep); + if(bInnerRadiusNotZero) + nVectorSize *= 2; + + aPointList.reserve(nVectorSize); + // if inner radius = 0 generate a normal pie segment (triangle fan) + // if inner radius != 0 generate a pie segment - inner pie (triangle strip) + if(!bInnerRadiusNotZero) { - m_PieSegment2DPointList.reserve(listLength); + aPointList.push_back(0); + aPointList.push_back(0); + aPointList.push_back(m_fZStep); } - float actualX = (x / OPENGL_SCALE_VALUE); - float actualY = (y / OPENGL_SCALE_VALUE); - m_PieSegment2DPointList.push_back(actualX); - m_PieSegment2DPointList.push_back(actualY); - m_PieSegment2DPointList.push_back(m_fZStep); - - if (m_PieSegment2DPointList.size() == size_t(listLength * 3)) + for(double nAngle = nAngleStart; nAngle <= nAngleStart + nAngleWidth; nAngle += nAngleStep) { - m_PieSegment2DShapePointList.push_back(m_PieSegment2DPointList); - m_PieSegment2DPointList.clear(); + float xVal = sin(nAngle/360*2*GL_PI); + float yVal = cos(nAngle/360*2*GL_PI); + aPointList.push_back(fOutterRadius * xVal); + aPointList.push_back(fOutterRadius * yVal); + aPointList.push_back(m_fZStep); + + if(bInnerRadiusNotZero) + { + aPointList.push_back(fInnerRadius * xVal); + aPointList.push_back(fInnerRadius * yVal); + aPointList.push_back(m_fZStep); + } } - return 0; + + m_PieSegment2DShapePointList.push_back(aPointList); } -int OpenGLRender::RenderPieSegment2DShape() +int OpenGLRender::RenderPieSegment2DShape(float fSize, float fPosX, float fPosY) { int listNum = m_PieSegment2DShapePointList.size(); - PosVecf3 trans = {0.0f, 0.0f, 0.0f}; + PosVecf3 trans = {fPosX/OPENGL_SCALE_VALUE, fPosY/OPENGL_SCALE_VALUE, 0.0f}; PosVecf3 angle = {0.0f, 0.0f, 0.0f}; - PosVecf3 scale = {1.0f, 1.0f, 1.0f}; + PosVecf3 scale = {fSize/OPENGL_SCALE_VALUE, fSize/OPENGL_SCALE_VALUE, 1.0f}; MoveModelf(trans, angle, scale); m_MVP = m_Projection * m_View * m_Model; @@ -1779,10 +1798,11 @@ int OpenGLRender::RenderPieSegment2DShape() 0, // stride (void*)0 // array buffer offset ); - glDrawArrays(GL_POLYGON, 0, pointList.size() / 3); // 12*3 indices starting at 0 -> 12 triangles + glDrawArrays(GL_TRIANGLE_STRIP, 0, pointList.size() / 3); // 12*3 indices starting at 0 -> 12 triangles glDisableVertexAttribArray(m_2DVertexID); glUseProgram(0); m_PieSegment2DShapePointList.pop_back(); + CHECK_GL_ERROR(); } glEnable(GL_MULTISAMPLE); diff --git a/chart2/source/view/main/OpenGLRender.hxx b/chart2/source/view/main/OpenGLRender.hxx index 6f2a8d91e953..9e07c928d848 100755 --- a/chart2/source/view/main/OpenGLRender.hxx +++ b/chart2/source/view/main/OpenGLRender.hxx @@ -176,8 +176,8 @@ public: int RenderArea2DShape(); void SetChartTransparencyGradient(long transparencyGradient); - int SetPieSegment2DShapePoint(float x, float y, int listLength); - int RenderPieSegment2DShape(); + void GeneratePieSegment2D(double, double, double, double); + int RenderPieSegment2DShape(float, float, float); #if DEBUG_POSITIONING void renderDebug(); #endif |