Kaydet (Commit) 82ed9053 authored tarafından Peilin's avatar Peilin Kaydeden (comit) Markus Mohrhard

piesegment2d gl rendering && mov coords operation to dummy shape

Change-Id: Ic709fe37554cf29b4a644cabdc618c15959593d7
üst 84778c9e
......@@ -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;
......
......@@ -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,
......
......@@ -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: */
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment