summaryrefslogtreecommitdiff
path: root/chart2/source
diff options
context:
space:
mode:
authorPeilin <peilin@multicorewareinc.com>2014-01-20 14:47:19 +0800
committerMarkus Mohrhard <markus.mohrhard@googlemail.com>2014-01-29 08:09:55 +0100
commit82ed9053e7353fe784cebac4d249cad5ed4a2bf4 (patch)
tree55fd329f6eb6e93064bf2246ed2ac18623d768d7 /chart2/source
parent84778c9eb090a6141f2248d0ac8dc2526dcb5080 (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.hxx2
-rw-r--r--chart2/source/view/main/DummyXShape.cxx205
-rwxr-xr-xchart2/source/view/main/OpenGLRender.cxx66
-rwxr-xr-xchart2/source/view/main/OpenGLRender.hxx6
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;