diff options
author | Peilin <peilin@multicorewareinc.com> | 2014-01-20 14:47:19 +0800 |
---|---|---|
committer | Markus Mohrhard <markus.mohrhard@googlemail.com> | 2014-01-29 08:09:55 +0100 |
commit | 82ed9053e7353fe784cebac4d249cad5ed4a2bf4 (patch) | |
tree | 55fd329f6eb6e93064bf2246ed2ac18623d768d7 /chart2/source | |
parent | 84778c9eb090a6141f2248d0ac8dc2526dcb5080 (diff) |
piesegment2d gl rendering && mov coords operation to dummy shape
Change-Id: Ic709fe37554cf29b4a644cabdc618c15959593d7
Diffstat (limited to 'chart2/source')
-rw-r--r-- | chart2/source/view/inc/DummyXShape.hxx | 2 | ||||
-rw-r--r-- | chart2/source/view/main/DummyXShape.cxx | 205 | ||||
-rwxr-xr-x | chart2/source/view/main/OpenGLRender.cxx | 66 | ||||
-rwxr-xr-x | chart2/source/view/main/OpenGLRender.hxx | 6 |
4 files changed, 278 insertions, 1 deletions
diff --git a/chart2/source/view/inc/DummyXShape.hxx b/chart2/source/view/inc/DummyXShape.hxx index 7112ac7fc1ae..9b3eed2a5fe5 100644 --- a/chart2/source/view/inc/DummyXShape.hxx +++ b/chart2/source/view/inc/DummyXShape.hxx @@ -239,7 +239,7 @@ public: DummyPieSegment2D(double fUnitCircleStartAngleDegree, double fUnitCircleWidthAngleDegree, double fUnitCircleInnerRadius, double fUnitCircleOuterRadius, const drawing::Direction3D& rOffset, const drawing::HomogenMatrix& rUnitCircleToScene); - + void render(); private: double mfUnitCircleStartAngleDegree; double mfUnitCircleWidthAngleDegree; diff --git a/chart2/source/view/main/DummyXShape.cxx b/chart2/source/view/main/DummyXShape.cxx index 1ec63b91576f..70d94c11ffdc 100644 --- a/chart2/source/view/main/DummyXShape.cxx +++ b/chart2/source/view/main/DummyXShape.cxx @@ -30,6 +30,9 @@ #include <algorithm> +#include <basegfx/point/b2dpoint.hxx> +#include <basegfx/matrix/b3dhommatrix.hxx> + #define ENABLE_DEBUG_PROPERTIES 0 using namespace com::sun::star; @@ -321,6 +324,168 @@ 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, @@ -333,6 +498,46 @@ DummyPieSegment2D::DummyPieSegment2D(double fUnitCircleStartAngleDegree, double maUnitCircleToScene(rUnitCircleToScene) { } +void DummyPieSegment2D::render() +{ + DummyChart* pChart = getRootShape(); + + while(mfUnitCircleWidthAngleDegree>360) + 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); + } + + std::map<OUString, uno::Any>::const_iterator itr = maProperties.find(UNO_NAME_FILLCOLOR); + if(itr != maProperties.end()) + { + 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(); + +} DummyPieSegment::DummyPieSegment(double fUnitCircleStartAngleDegree, double fUnitCircleWidthAngleDegree, double fUnitCircleInnerRadius, double fUnitCircleOuterRadius, diff --git a/chart2/source/view/main/OpenGLRender.cxx b/chart2/source/view/main/OpenGLRender.cxx index d96b2190ffa1..0419a5777916 100755 --- a/chart2/source/view/main/OpenGLRender.cxx +++ b/chart2/source/view/main/OpenGLRender.cxx @@ -1726,4 +1726,70 @@ void OpenGLRender::SetChartTransparencyGradient(long transparencyGradient) m_BackgroundColor[15] = 0.0; } } +int OpenGLRender::SetPieSegment2DShapePoint(float x, float y, int listLength) +{ + if (m_PieSegment2DPointList.empty()) + { + m_PieSegment2DPointList.reserve(listLength); + } + 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)) + { + m_PieSegment2DShapePointList.push_back(m_PieSegment2DPointList); + m_PieSegment2DPointList.clear(); + } + return 0; +} + +int OpenGLRender::RenderPieSegment2DShape() +{ + int listNum = m_PieSegment2DShapePointList.size(); + PosVecf3 trans = {0.0f, 0.0f, 0.0f}; + PosVecf3 angle = {0.0f, 0.0f, 0.0f}; + PosVecf3 scale = {1.0f, 1.0f, 1.0f}; + MoveModelf(trans, angle, scale); + m_MVP = m_Projection * m_View * m_Model; + + for (int i = 0; i < listNum; i++) + { + PieSegment2DPointList &pointList = m_PieSegment2DShapePointList.back(); + //fill vertex buffer + glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer); + glBufferData(GL_ARRAY_BUFFER, pointList.size() * sizeof(float), &pointList[0] , GL_STATIC_DRAW); + // Use our shader + glUseProgram(m_CommonProID); + + glUniform4fv(m_2DColorID, 1, &m_2DColor[0]); + + glUniformMatrix4fv(m_MatrixID, 1, GL_FALSE, &m_MVP[0][0]); + + // 1rst attribute buffer : vertices + glEnableVertexAttribArray(m_2DVertexID); + glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer); + glVertexAttribPointer( + m_2DVertexID, // attribute. No particular reason for 0, but must match the layout in the shader. + 3, // size + GL_FLOAT, // type + GL_FALSE, // normalized? + 0, // stride + (void*)0 // array buffer offset + ); + glDrawArrays(GL_POLYGON, 0, pointList.size() / 3); // 12*3 indices starting at 0 -> 12 triangles + glDisableVertexAttribArray(m_2DVertexID); + glUseProgram(0); + m_PieSegment2DShapePointList.pop_back(); + + } + glEnable(GL_MULTISAMPLE); + m_fZStep += 0.01f; + + CHECK_GL_ERROR(); + return 0; +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/source/view/main/OpenGLRender.hxx b/chart2/source/view/main/OpenGLRender.hxx index 435e76dbfa40..6f2a8d91e953 100755 --- a/chart2/source/view/main/OpenGLRender.hxx +++ b/chart2/source/view/main/OpenGLRender.hxx @@ -100,6 +100,7 @@ typedef struct TextInfo }TextInfo; typedef std::vector<GLfloat> Area2DPointList; +typedef std::vector<GLfloat> PieSegment2DPointList; /// Holds the information of our new child window struct GLWindow @@ -175,6 +176,8 @@ public: int RenderArea2DShape(); void SetChartTransparencyGradient(long transparencyGradient); + int SetPieSegment2DShapePoint(float x, float y, int listLength); + int RenderPieSegment2DShape(); #if DEBUG_POSITIONING void renderDebug(); #endif @@ -295,6 +298,9 @@ private: float m_BackgroundColor[16]; glm::vec4 m_ClearColor; + PieSegment2DPointList m_PieSegment2DPointList; + std::list <PieSegment2DPointList> m_PieSegment2DShapePointList; + #if DEBUG_POSITIONING GLuint m_DebugProID; GLuint m_DebugVertexID; |