StelPainter.cpp   StelPainter.cpp 
skipping to change at line 401 skipping to change at line 401
x = rad[i]*cos_sin_theta_p[0]; x = rad[i]*cos_sin_theta_p[0];
y = rad[i]*cos_sin_theta_p[1]; y = rad[i]*cos_sin_theta_p[1];
texCoordArr << 0.5f+x/radius << 0.5f+y/radius; texCoordArr << 0.5f+x/radius << 0.5f+y/radius;
vertexArr << x << y << 0; vertexArr << x << y << 0;
} }
} }
// draw the inner polygon // draw the inner polygon
slices_step>>=1; slices_step>>=1;
cos_sin_theta_p=cos_sin_theta; cos_sin_theta_p=cos_sin_theta;
x = rad[0]*cos_sin_theta_p[0];
y = rad[0]*cos_sin_theta_p[1]; if (slices==1)
texCoordArr << 0.5f+x/radius << 0.5f+y/radius; {
vertexArr << x << y << 0; x = rad[0]*cos_sin_theta_p[0];
cos_sin_theta_p+=2*slices_step; y = rad[0]*cos_sin_theta_p[1];
x = rad[0]*cos_sin_theta_p[0]; texCoordArr << 0.5f+x/radius << 0.5f+y/radius;
y = rad[0]*cos_sin_theta_p[1]; vertexArr << x << y << 0;
texCoordArr << 0.5f+x/radius << 0.5f+y/radius; cos_sin_theta_p+=2*slices_step;
vertexArr << x << y << 0; x = rad[0]*cos_sin_theta_p[0];
cos_sin_theta_p+=2*slices_step; y = rad[0]*cos_sin_theta_p[1];
x = rad[0]*cos_sin_theta_p[0]; texCoordArr << 0.5f+x/radius << 0.5f+y/radius;
y = rad[0]*cos_sin_theta_p[1]; vertexArr << x << y << 0;
texCoordArr << 0.5f+x/radius << 0.5f+y/radius; cos_sin_theta_p+=2*slices_step;
vertexArr << x << y << 0; x = rad[0]*cos_sin_theta_p[0];
y = rad[0]*cos_sin_theta_p[1];
texCoordArr << 0.5f+x/radius << 0.5f+y/radius;
vertexArr << x << y << 0;
}
else
{
j=0;
while (j<slices)
{
texCoordArr << 0.5f << 0.5f;
vertexArr << 0 << 0 << 0;
x = rad[0]*cos_sin_theta_p[0];
y = rad[0]*cos_sin_theta_p[1];
texCoordArr << 0.5f+x/radius << 0.5f+y/radius;
vertexArr << x << y << 0;
j+=slices_step;
cos_sin_theta_p+=2*slices_step;
x = rad[0]*cos_sin_theta_p[0];
y = rad[0]*cos_sin_theta_p[1];
texCoordArr << 0.5f+x/radius << 0.5f+y/radius;
vertexArr << x << y << 0;
}
}
} }
void StelPainter::sRing(float rMin, float rMax, int slices, int stacks, int orientInside) void StelPainter::sRing(float rMin, float rMax, int slices, int stacks, int orientInside)
{ {
float x,y; float x,y;
int j; int j;
static Vec3f lightPos3; static Vec3f lightPos3;
static Vec4f ambientLight; static Vec4f ambientLight;
skipping to change at line 575 skipping to change at line 598
z = cos_sin_rho_p[0]; z = cos_sin_rho_p[0];
sSphereMapTexCoordFast(rho, cos_sin_theta_p[ 0], -cos_sin_theta_p[1], texCoordArr); sSphereMapTexCoordFast(rho, cos_sin_theta_p[ 0], -cos_sin_theta_p[1], texCoordArr);
vertexArr << x*radius << y*radius << z*radiu s; vertexArr << x*radius << y*radius << z*radiu s;
} }
setArrays((Vec3d*)vertexArr.constData(), (Vec2f*)tex CoordArr.constData()); setArrays((Vec3d*)vertexArr.constData(), (Vec2f*)tex CoordArr.constData());
drawFromArray(TriangleStrip, vertexArr.size()/3); drawFromArray(TriangleStrip, vertexArr.size()/3);
} }
} }
} }
void StelPainter::drawTextGravity180(float x, float y, const QString& ws, f loat xshift, float yshift) const void StelPainter::drawTextGravity180(float x, float y, const QString& ws, f loat xshift, float yshift)
{ {
float dx, dy, d, theta, psi; float dx, dy, d, theta, psi;
dx = x - prj->viewportCenter[0]; dx = x - prj->viewportCenter[0];
dy = y - prj->viewportCenter[1]; dy = y - prj->viewportCenter[1];
d = std::sqrt(dx*dx + dy*dy); d = std::sqrt(dx*dx + dy*dy);
// If the text is too far away to be visible in the screen return // If the text is too far away to be visible in the screen return
if (d>qMax(prj->viewportXywh[3], prj->viewportXywh[2])*2) if (d>qMax(prj->viewportXywh[3], prj->viewportXywh[2])*2)
return; return;
theta = M_PI + std::atan2(dx, dy - 1); theta = M_PI + std::atan2(dx, dy - 1);
psi = std::atan2((float)qPainter->fontMetrics().width(ws)/ws.length( ),d + 1) * 180./M_PI; psi = std::atan2((float)qPainter->fontMetrics().width(ws)/ws.length( ),d + 1) * 180./M_PI;
if (psi>5) if (psi>5)
psi = 5; psi = 5;
if (qPainter->paintEngine()->type()==QPaintEngine::OpenGL2) const float cosr = std::cos(-theta * M_PI/180.);
{ const float sinr = std::sin(-theta * M_PI/180.);
qPainter->translate(x, prj->viewportXywh[3]-y);
qPainter->rotate(theta*180./M_PI); float initX = x + xshift*cosr - yshift*sinr;
qPainter->translate(xshift, -yshift); float initY = y + yshift*sinr + yshift*cosr;
}
else
{
qPainter->translate(x, y);
qPainter->rotate(-theta*180./M_PI);
qPainter->translate(xshift, yshift);
qPainter->scale(1, -1);
}
for (int i=0;i<ws.length();++i) for (int i=0;i<ws.length();++i)
{ {
qPainter->drawText(0,0,ws[i]); drawText(initX, initY, ws[i], -theta*180./M_PI+psi*i, 0., 0.
);
// with typeface need to manually advance xshift = (float)qPainter->fontMetrics().width(ws.mid(i,1)) *
// TODO, absolute rotation would be better than relative 1.05;
// TODO: would look better with kerning information... initX+=xshift*std::cos(-theta+psi*i * M_PI/180.);
qPainter->translate((float)qPainter->fontMetrics().width(ws. initY+=xshift*std::sin(-theta+psi*i * M_PI/180.);
mid(i,1)) * 1.05, 0);
qPainter->rotate(-psi);
} }
} }
void StelPainter::drawText(const Vec3d& v, const QString& str, float angleD eg, float xshift, float yshift, bool noGravity) const void StelPainter::drawText(const Vec3d& v, const QString& str, float angleD eg, float xshift, float yshift, bool noGravity)
{ {
Vec3d win; Vec3d win;
prj->project(v, win); prj->project(v, win);
drawText(win[0], win[1], str, angleDeg, xshift, yshift, noGravity); drawText(win[0], win[1], str, angleDeg, xshift, yshift, noGravity);
} }
/************************************************************************* /*************************************************************************
Draw the string at the given position and angle with the given font Draw the string at the given position and angle with the given font
*************************************************************************/ *************************************************************************/
void StelPainter::drawText(float x, float y, const QString& str, float angl
eDeg, float xshift, float yshift, bool noGravity) const
{
Q_ASSERT(qPainter);
float color[4];
#ifndef STELPAINTER_GL2
// Save openGL state
glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS);
glPushAttrib(GL_ALL_ATTRIB_BITS);
glMatrixMode(GL_TEXTURE);
glPushMatrix();
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glGetFloatv(GL_CURRENT_COLOR, color);
#else
color[0]=currentColor[0];
color[1]=currentColor[1];
color[2]=currentColor[2];
color[3]=currentColor[3];
#endif
qPainter->endNativePainting(); // Container for one cached string texture
struct StringTexture
{
GLuint texture;
int width;
int height;
qPainter->save(); StringTexture() : texture(0) {;}
qPainter->resetTransform(); ~StringTexture()
qPainter->resetMatrix(); {
qPainter->setRenderHints(QPainter::TextAntialiasing | QPainter::High if (texture != 0)
QualityAntialiasing); glDeleteTextures(1, &texture);
const QColor qCol=QColor::fromRgbF(qMax(qMin(1.f,color[0]),0.f), qMa }
x(qMin(1.f,color[1]),0.f), qMax(qMin(1.f,color[2]),0.f), qMax(qMin(1.f,colo };
r[3]),0.f));
qPainter->setPen(qCol);
void StelPainter::drawText(float x, float y, const QString& str, float angl
eDeg, float xshift, float yshift, bool noGravity)
{
Q_ASSERT(qPainter);
if (prj->gravityLabels && !noGravity) if (prj->gravityLabels && !noGravity)
{ {
drawTextGravity180(x, y, str, xshift, yshift); drawTextGravity180(x, y, str, xshift, yshift);
} }
else else
{ {
// There are 2 version here depending on the OpenGL engine static const int cacheLimitByte = 7000000;
// OpenGL 1 need to reverse the text vertically, not OpenGL static QCache<QByteArray,StringTexture> texCache(cacheLimitB
2... yte);
// This sounds like a Qt bug int pixelSize = qPainter->font().pixelSize();
if (qPainter->paintEngine()->type()==QPaintEngine::OpenGL2) QByteArray hash = str.toUtf8() + QByteArray::number(pixelSiz
{ e);
qPainter->translate(x, prj->viewportXywh[3]-y);
qPainter->rotate(-angleDeg); const StringTexture* cachedTex = texCache.object(hash);
qPainter->translate(xshift, -yshift); if (cachedTex == NULL) // need to create texture
{
// Create temp image and render text into it
QRect strRect = getFontMetrics().boundingRect(str);
QPixmap strImage(strRect.width()+1+(int)(0.02f*strR
ect.width()), strRect.height());
strImage.fill(Qt::transparent);
QPainter painter(&strImage);
painter.setFont(qPainter->font());
painter.setRenderHints(QPainter::TextAntialiasing);
painter.setPen(Qt::white);
painter.drawText(-strRect.x(), -strRect.y(), str);
// Create and bind texture, and add it to the list o
f cached textures
StringTexture* newTex = new StringTexture();
newTex->texture = StelPainter::glContext->bindTextur
e(strImage, GL_TEXTURE_2D, GL_RGBA, QGLContext::NoBindOption);
newTex->width = strImage.width();
newTex->height = strImage.height();
texCache.insert(hash, newTex, 3*newTex->width*newTex
->height);
cachedTex=newTex;
} }
else else
{ {
qPainter->translate(round(x), round(y)); // The texture was found in the cache
qPainter->scale(1, -1); glBindTexture(GL_TEXTURE_2D, cachedTex->texture);
qPainter->rotate(-angleDeg);
qPainter->translate(round(xshift), round(-yshift));
} }
qPainter->drawText(0, 0, str);
}
qPainter->restore();
qPainter->beginNativePainting(); // Translate/rotate
if (!noGravity)
angleDeg += prj->defautAngleForGravityText;
enableTexture2d(true);
static float vertexData[8];
static const float texCoordData[] = {0.,1., 1.,1., 0.,0., 1.
,0.};
// compute the vertex coordinates applying the translation a
nd the rotation
static const float vertexBase[] = {0., 0., 1., 0., 0., 1., 1
., 1.};
if (std::fabs(angleDeg)>1.f*M_PI/180.f)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER
, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER
, GL_LINEAR);
const float cosr = std::cos(angleDeg * M_PI/180.);
const float sinr = std::sin(angleDeg * M_PI/180.);
for (int i = 0; i < 8; i+=2)
{
vertexData[i] = int(x + (cachedTex->width*ve
rtexBase[i]+xshift) * cosr - (cachedTex->height*vertexBase[i+1]+yshift) * s
inr);
vertexData[i+1] = int(y + (cachedTex->width
*vertexBase[i]+xshift) * sinr + (cachedTex->height*vertexBase[i+1]+yshift)
* cosr);
}
}
else
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER
, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER
, GL_NEAREST);
for (int i = 0; i < 8; i+=2)
{
vertexData[i] = int(x + cachedTex->width*ver
texBase[i]+xshift);
vertexData[i+1] = int(y + cachedTex->height
*vertexBase[i+1]+yshift);
}
}
#ifndef STELPAINTER_GL2 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glMatrixMode(GL_TEXTURE); glEnable(GL_BLEND);
glPopMatrix(); enableClientStates(true, true);
glMatrixMode(GL_PROJECTION); setVertexPointer(2, GL_FLOAT, vertexData);
glPopMatrix(); setTexCoordPointer(2, GL_FLOAT, texCoordData);
glMatrixMode(GL_MODELVIEW); drawFromArray(TriangleStrip, 4, 0, false);
glPopMatrix(); enableClientStates(false);
glPopClientAttrib(); }
glPopAttrib();
#endif
} }
// Recursive method cutting a small circle in small segments // Recursive method cutting a small circle in small segments
inline void fIter(const StelProjectorP& prj, const Vec3d& p1, const Vec3d& p2, Vec3d& win1, Vec3d& win2, QLinkedList<Vec3d>& vertexList, const QLinked List<Vec3d>::iterator& iter, double radius, const Vec3d& center, int nbI=0, bool checkCrossDiscontinuity=true) inline void fIter(const StelProjectorP& prj, const Vec3d& p1, const Vec3d& p2, Vec3d& win1, Vec3d& win2, QLinkedList<Vec3d>& vertexList, const QLinked List<Vec3d>::iterator& iter, double radius, const Vec3d& center, int nbI=0, bool checkCrossDiscontinuity=true)
{ {
const bool crossDiscontinuity = checkCrossDiscontinuity && prj->inte rsectViewportDiscontinuity(p1+center, p2+center); const bool crossDiscontinuity = checkCrossDiscontinuity && prj->inte rsectViewportDiscontinuity(p1+center, p2+center);
if (crossDiscontinuity && nbI>=10) if (crossDiscontinuity && nbI>=10)
{ {
win1[2]=-2.; win1[2]=-2.;
win2[2]=-2.; win2[2]=-2.;
skipping to change at line 834 skipping to change at line 874
drawSmallCircleVertexArray(); drawSmallCircleVertexArray();
} }
} }
Q_ASSERT(smallCircleVertexArray.isEmpty()); Q_ASSERT(smallCircleVertexArray.isEmpty());
} }
// Project the passed triangle on the screen ensuring that it will look smo oth, even for non linear distortion // Project the passed triangle on the screen ensuring that it will look smo oth, even for non linear distortion
// by splitting it into subtriangles. // by splitting it into subtriangles.
void StelPainter::projectSphericalTriangle(const SphericalCap* clippingCap, const Vec3d* vertices, QVarLengthArray<Vec3f, 4096>* outVertices, void StelPainter::projectSphericalTriangle(const SphericalCap* clippingCap, const Vec3d* vertices, QVarLengthArray<Vec3f, 4096>* outVertices,
const Vec2f* texturePos, QVarLengthArray<Vec2f, 4096>* outTe xturePos, const Vec2f* texturePos, QVarLengthArray<Vec2f, 4096>* outTe xturePos,
int nbI, bool checkDisc1, bool checkDisc2, bool checkDisc3) const double maxSqDistortion, int nbI, bool checkDisc1, bool check Disc2, bool checkDisc3) const
{ {
Q_ASSERT(fabs(vertices[0].length()-1.)<0.00001); Q_ASSERT(fabs(vertices[0].length()-1.)<0.00001);
Q_ASSERT(fabs(vertices[1].length()-1.)<0.00001); Q_ASSERT(fabs(vertices[1].length()-1.)<0.00001);
Q_ASSERT(fabs(vertices[2].length()-1.)<0.00001); Q_ASSERT(fabs(vertices[2].length()-1.)<0.00001);
if (clippingCap && clippingCap->containsTriangle(vertices)) if (clippingCap && clippingCap->containsTriangle(vertices))
clippingCap = NULL; clippingCap = NULL;
if (clippingCap && !clippingCap->intersectsTriangle(vertices)) if (clippingCap && !clippingCap->intersectsTriangle(vertices))
return; return;
bool cDiscontinuity1 = checkDisc1 && prj->intersectViewportDiscontin uity(vertices[0], vertices[1]); bool cDiscontinuity1 = checkDisc1 && prj->intersectViewportDiscontin uity(vertices[0], vertices[1]);
bool cDiscontinuity2 = checkDisc2 && prj->intersectViewportDiscontin uity(vertices[1], vertices[2]); bool cDiscontinuity2 = checkDisc2 && prj->intersectViewportDiscontin uity(vertices[1], vertices[2]);
skipping to change at line 860 skipping to change at line 900
Vec3d e0=vertices[0]; Vec3d e0=vertices[0];
Vec3d e1=vertices[1]; Vec3d e1=vertices[1];
Vec3d e2=vertices[2]; Vec3d e2=vertices[2];
bool valid = prj->projectInPlace(e0); bool valid = prj->projectInPlace(e0);
valid = prj->projectInPlace(e1) || valid; valid = prj->projectInPlace(e1) || valid;
valid = prj->projectInPlace(e2) || valid; valid = prj->projectInPlace(e2) || valid;
// Clip polygons behind the viewer // Clip polygons behind the viewer
if (!valid) if (!valid)
return; return;
static const double maxSqDistortion = 5.;
if (checkDisc1 && cDiscontinuity1==false) if (checkDisc1 && cDiscontinuity1==false)
{ {
// If the distortion at segment e0,e1 is too big, flags it f or subdivision // If the distortion at segment e0,e1 is too big, flags it f or subdivision
Vec3d win3 = vertices[0]; win3+=vertices[1]; Vec3d win3 = vertices[0]; win3+=vertices[1];
prj->projectInPlace(win3); prj->projectInPlace(win3);
win3[0]-=(e0[0]+e1[0])*0.5; win3[1]-=(e0[1]+e1[1])*0.5; win3[0]-=(e0[0]+e1[0])*0.5; win3[1]-=(e0[1]+e1[1])*0.5;
cDiscontinuity1 = (win3[0]*win3[0]+win3[1]*win3[1])>maxSqDis tortion; cDiscontinuity1 = (win3[0]*win3[0]+win3[1]*win3[1])>maxSqDis tortion;
} }
if (checkDisc2 && cDiscontinuity2==false) if (checkDisc2 && cDiscontinuity2==false)
{ {
skipping to change at line 927 skipping to change at line 966
va[0]=vertices[0]; va[0]=vertices[0];
va[1]=vertices[0];va[1]+=vertices[1]; va[1]=vertices[0];va[1]+=vertices[1];
va[1].normalize(); va[1].normalize();
va[2]=vertices[2]; va[2]=vertices[2];
if (outTexturePos) if (outTexturePos)
{ {
ta[0]=texturePos[0]; ta[0]=texturePos[0];
ta[1]=(texturePos[0]+texturePos[1])*0.5; ta[1]=(texturePos[0]+texturePos[1])*0.5;
ta[2]=texturePos[2]; ta[2]=texturePos[2];
} }
projectSphericalTriangle(clippingCap, va, outVertices, ta, o utTexturePos, nbI+1, true, true, false); projectSphericalTriangle(clippingCap, va, outVertices, ta, o utTexturePos, maxSqDistortion, nbI+1, true, true, false);
//va[0]=vertices[0]+vertices[1]; //va[0]=vertices[0]+vertices[1];
//va[0].normalize(); //va[0].normalize();
va[0]=va[1]; va[0]=va[1];
va[1]=vertices[1]; va[1]=vertices[1];
va[2]=vertices[2]; va[2]=vertices[2];
if (outTexturePos) if (outTexturePos)
{ {
ta[0]=(texturePos[0]+texturePos[1])*0.5; ta[0]=(texturePos[0]+texturePos[1])*0.5;
ta[1]=texturePos[1]; ta[1]=texturePos[1];
ta[2]=texturePos[2]; ta[2]=texturePos[2];
} }
projectSphericalTriangle(clippingCap, va, outVertices, ta, o utTexturePos, nbI+1, true, false, true); projectSphericalTriangle(clippingCap, va, outVertices, ta, o utTexturePos, maxSqDistortion, nbI+1, true, false, true);
return; return;
} }
if (!cDiscontinuity1 && cDiscontinuity2 && !cDiscontinuity3) if (!cDiscontinuity1 && cDiscontinuity2 && !cDiscontinuity3)
{ {
va[0]=vertices[0]; va[0]=vertices[0];
va[1]=vertices[1]; va[1]=vertices[1];
va[2]=vertices[1];va[2]+=vertices[2]; va[2]=vertices[1];va[2]+=vertices[2];
va[2].normalize(); va[2].normalize();
if (outTexturePos) if (outTexturePos)
{ {
ta[0]=texturePos[0]; ta[0]=texturePos[0];
ta[1]=texturePos[1]; ta[1]=texturePos[1];
ta[2]=(texturePos[1]+texturePos[2])*0.5; ta[2]=(texturePos[1]+texturePos[2])*0.5;
} }
projectSphericalTriangle(clippingCap, va, outVertices, ta, o utTexturePos, nbI+1, false, true, true); projectSphericalTriangle(clippingCap, va, outVertices, ta, o utTexturePos, maxSqDistortion, nbI+1, false, true, true);
va[0]=vertices[0]; va[0]=vertices[0];
//va[1]=vertices[1]+vertices[2]; //va[1]=vertices[1]+vertices[2];
//va[1].normalize(); //va[1].normalize();
va[1]=va[2]; va[1]=va[2];
va[2]=vertices[2]; va[2]=vertices[2];
if (outTexturePos) if (outTexturePos)
{ {
ta[0]=texturePos[0]; ta[0]=texturePos[0];
ta[1]=(texturePos[1]+texturePos[2])*0.5; ta[1]=(texturePos[1]+texturePos[2])*0.5;
ta[2]=texturePos[2]; ta[2]=texturePos[2];
} }
projectSphericalTriangle(clippingCap, va, outVertices, ta, o utTexturePos, nbI+1, true, true, false); projectSphericalTriangle(clippingCap, va, outVertices, ta, o utTexturePos, maxSqDistortion, nbI+1, true, true, false);
return; return;
} }
if (!cDiscontinuity1 && !cDiscontinuity2 && cDiscontinuity3) if (!cDiscontinuity1 && !cDiscontinuity2 && cDiscontinuity3)
{ {
va[0]=vertices[0]; va[0]=vertices[0];
va[1]=vertices[1]; va[1]=vertices[1];
va[2]=vertices[0];va[2]+=vertices[2]; va[2]=vertices[0];va[2]+=vertices[2];
va[2].normalize(); va[2].normalize();
if (outTexturePos) if (outTexturePos)
{ {
ta[0]=texturePos[0]; ta[0]=texturePos[0];
ta[1]=texturePos[1]; ta[1]=texturePos[1];
ta[2]=(texturePos[0]+texturePos[2])*0.5; ta[2]=(texturePos[0]+texturePos[2])*0.5;
} }
projectSphericalTriangle(clippingCap, va, outVertices, ta, o utTexturePos, nbI+1, false, true, true); projectSphericalTriangle(clippingCap, va, outVertices, ta, o utTexturePos, maxSqDistortion, nbI+1, false, true, true);
//va[0]=vertices[0]+vertices[2]; //va[0]=vertices[0]+vertices[2];
//va[0].normalize(); //va[0].normalize();
va[0]=va[2]; va[0]=va[2];
va[1]=vertices[1]; va[1]=vertices[1];
va[2]=vertices[2]; va[2]=vertices[2];
if (outTexturePos) if (outTexturePos)
{ {
ta[0]=(texturePos[0]+texturePos[2])*0.5; ta[0]=(texturePos[0]+texturePos[2])*0.5;
ta[1]=texturePos[1]; ta[1]=texturePos[1];
ta[2]=texturePos[2]; ta[2]=texturePos[2];
} }
projectSphericalTriangle(clippingCap, va, outVertices, ta, o utTexturePos, nbI+1, true, false, true); projectSphericalTriangle(clippingCap, va, outVertices, ta, o utTexturePos, maxSqDistortion, nbI+1, true, false, true);
return; return;
} }
// 2 sides have to be split: split the triangle in 3 // 2 sides have to be split: split the triangle in 3
if (cDiscontinuity1 && cDiscontinuity2 && !cDiscontinuity3) if (cDiscontinuity1 && cDiscontinuity2 && !cDiscontinuity3)
{ {
va[0]=vertices[0]; va[0]=vertices[0];
va[1]=vertices[0];va[1]+=vertices[1]; va[1]=vertices[0];va[1]+=vertices[1];
va[1].normalize(); va[1].normalize();
va[2]=vertices[1];va[2]+=vertices[2]; va[2]=vertices[1];va[2]+=vertices[2];
va[2].normalize(); va[2].normalize();
if (outTexturePos) if (outTexturePos)
{ {
ta[0]=texturePos[0]; ta[0]=texturePos[0];
ta[1]=(texturePos[0]+texturePos[1])*0.5; ta[1]=(texturePos[0]+texturePos[1])*0.5;
ta[2]=(texturePos[1]+texturePos[2])*0.5; ta[2]=(texturePos[1]+texturePos[2])*0.5;
} }
projectSphericalTriangle(clippingCap, va, outVertices, ta, o utTexturePos, nbI+1); projectSphericalTriangle(clippingCap, va, outVertices, ta, o utTexturePos, maxSqDistortion, nbI+1);
//va[0]=vertices[0]+vertices[1]; //va[0]=vertices[0]+vertices[1];
//va[0].normalize(); //va[0].normalize();
va[0]=va[1]; va[0]=va[1];
va[1]=vertices[1]; va[1]=vertices[1];
//va[2]=vertices[1]+vertices[2]; //va[2]=vertices[1]+vertices[2];
//va[2].normalize(); //va[2].normalize();
if (outTexturePos) if (outTexturePos)
{ {
ta[0]=(texturePos[0]+texturePos[1])*0.5; ta[0]=(texturePos[0]+texturePos[1])*0.5;
ta[1]=texturePos[1]; ta[1]=texturePos[1];
ta[2]=(texturePos[1]+texturePos[2])*0.5; ta[2]=(texturePos[1]+texturePos[2])*0.5;
} }
projectSphericalTriangle(clippingCap, va, outVertices, ta, o utTexturePos, nbI+1); projectSphericalTriangle(clippingCap, va, outVertices, ta, o utTexturePos, maxSqDistortion, nbI+1);
va[0]=vertices[0]; va[0]=vertices[0];
//va[1]=vertices[1]+vertices[2]; //va[1]=vertices[1]+vertices[2];
//va[1].normalize(); //va[1].normalize();
va[1]=va[2]; va[1]=va[2];
va[2]=vertices[2]; va[2]=vertices[2];
if (outTexturePos) if (outTexturePos)
{ {
ta[0]=texturePos[0]; ta[0]=texturePos[0];
ta[1]=(texturePos[1]+texturePos[2])*0.5; ta[1]=(texturePos[1]+texturePos[2])*0.5;
ta[2]=texturePos[2]; ta[2]=texturePos[2];
} }
projectSphericalTriangle(clippingCap, va, outVertices, ta, o utTexturePos, nbI+1, true, true, false); projectSphericalTriangle(clippingCap, va, outVertices, ta, o utTexturePos, maxSqDistortion, nbI+1, true, true, false);
return; return;
} }
if (cDiscontinuity1 && !cDiscontinuity2 && cDiscontinuity3) if (cDiscontinuity1 && !cDiscontinuity2 && cDiscontinuity3)
{ {
va[0]=vertices[0]; va[0]=vertices[0];
va[1]=vertices[0];va[1]+=vertices[1]; va[1]=vertices[0];va[1]+=vertices[1];
va[1].normalize(); va[1].normalize();
va[2]=vertices[0];va[2]+=vertices[2]; va[2]=vertices[0];va[2]+=vertices[2];
va[2].normalize(); va[2].normalize();
if (outTexturePos) if (outTexturePos)
{ {
ta[0]=texturePos[0]; ta[0]=texturePos[0];
ta[1]=(texturePos[0]+texturePos[1])*0.5; ta[1]=(texturePos[0]+texturePos[1])*0.5;
ta[2]=(texturePos[0]+texturePos[2])*0.5; ta[2]=(texturePos[0]+texturePos[2])*0.5;
} }
projectSphericalTriangle(clippingCap, va, outVertices, ta, o utTexturePos, nbI+1); projectSphericalTriangle(clippingCap, va, outVertices, ta, o utTexturePos, maxSqDistortion, nbI+1);
//va[0]=vertices[0]+vertices[1]; //va[0]=vertices[0]+vertices[1];
//va[0].normalize(); //va[0].normalize();
va[0]=va[1]; va[0]=va[1];
va[1]=vertices[2]; va[1]=vertices[2];
//va[2]=vertices[0]+vertices[2]; //va[2]=vertices[0]+vertices[2];
//va[2].normalize(); //va[2].normalize();
if (outTexturePos) if (outTexturePos)
{ {
ta[0]=(texturePos[0]+texturePos[1])*0.5; ta[0]=(texturePos[0]+texturePos[1])*0.5;
ta[1]=texturePos[2]; ta[1]=texturePos[2];
ta[2]=(texturePos[0]+texturePos[2])*0.5; ta[2]=(texturePos[0]+texturePos[2])*0.5;
} }
projectSphericalTriangle(clippingCap, va, outVertices, ta, o utTexturePos, nbI+1); projectSphericalTriangle(clippingCap, va, outVertices, ta, o utTexturePos, maxSqDistortion, nbI+1);
//va[0]=vertices[0]+vertices[1]; //va[0]=vertices[0]+vertices[1];
//va[0].normalize(); //va[0].normalize();
va[1]=vertices[1]; va[1]=vertices[1];
va[2]=vertices[2]; va[2]=vertices[2];
if (outTexturePos) if (outTexturePos)
{ {
ta[0]=(texturePos[0]+texturePos[1])*0.5; ta[0]=(texturePos[0]+texturePos[1])*0.5;
ta[1]=texturePos[1]; ta[1]=texturePos[1];
ta[2]=texturePos[2]; ta[2]=texturePos[2];
} }
projectSphericalTriangle(clippingCap, va, outVertices, ta, o utTexturePos, nbI+1, true, false, true); projectSphericalTriangle(clippingCap, va, outVertices, ta, o utTexturePos, maxSqDistortion, nbI+1, true, false, true);
return; return;
} }
if (!cDiscontinuity1 && cDiscontinuity2 && cDiscontinuity3) if (!cDiscontinuity1 && cDiscontinuity2 && cDiscontinuity3)
{ {
va[0]=vertices[0]; va[0]=vertices[0];
va[1]=vertices[1]; va[1]=vertices[1];
va[2]=vertices[1];va[2]+=vertices[2]; va[2]=vertices[1];va[2]+=vertices[2];
va[2].normalize(); va[2].normalize();
if (outTexturePos) if (outTexturePos)
{ {
ta[0]=texturePos[0]; ta[0]=texturePos[0];
ta[1]=texturePos[1]; ta[1]=texturePos[1];
ta[2]=(texturePos[1]+texturePos[2])*0.5; ta[2]=(texturePos[1]+texturePos[2])*0.5;
} }
projectSphericalTriangle(clippingCap, va, outVertices, ta, o utTexturePos, nbI+1, false, true, true); projectSphericalTriangle(clippingCap, va, outVertices, ta, o utTexturePos, maxSqDistortion, nbI+1, false, true, true);
//va[0]=vertices[1]+vertices[2]; //va[0]=vertices[1]+vertices[2];
//va[0].normalize(); //va[0].normalize();
va[0]=va[2]; va[0]=va[2];
va[1]=vertices[2]; va[1]=vertices[2];
va[2]=vertices[0];va[2]+=vertices[2]; va[2]=vertices[0];va[2]+=vertices[2];
va[2].normalize(); va[2].normalize();
if (outTexturePos) if (outTexturePos)
{ {
ta[0]=(texturePos[1]+texturePos[2])*0.5; ta[0]=(texturePos[1]+texturePos[2])*0.5;
ta[1]=texturePos[2]; ta[1]=texturePos[2];
ta[2]=(texturePos[0]+texturePos[2])*0.5; ta[2]=(texturePos[0]+texturePos[2])*0.5;
} }
projectSphericalTriangle(clippingCap, va, outVertices, ta, o utTexturePos, nbI+1); projectSphericalTriangle(clippingCap, va, outVertices, ta, o utTexturePos, maxSqDistortion, nbI+1);
va[1]=va[0]; va[1]=va[0];
va[0]=vertices[0]; va[0]=vertices[0];
//va[1]=vertices[1]+vertices[2]; //va[1]=vertices[1]+vertices[2];
//va[1].normalize(); //va[1].normalize();
//va[2]=vertices[0]+vertices[2]; //va[2]=vertices[0]+vertices[2];
//va[2].normalize(); //va[2].normalize();
if (outTexturePos) if (outTexturePos)
{ {
ta[0]=texturePos[0]; ta[0]=texturePos[0];
ta[1]=(texturePos[1]+texturePos[2])*0.5; ta[1]=(texturePos[1]+texturePos[2])*0.5;
ta[2]=(texturePos[0]+texturePos[2])*0.5; ta[2]=(texturePos[0]+texturePos[2])*0.5;
} }
projectSphericalTriangle(clippingCap, va, outVertices, ta, o utTexturePos, nbI+1); projectSphericalTriangle(clippingCap, va, outVertices, ta, o utTexturePos, maxSqDistortion, nbI+1);
return; return;
} }
// Last case: the 3 sides have to be split: cut in 4 triangles a' la HTM // Last case: the 3 sides have to be split: cut in 4 triangles a' la HTM
va[0]=vertices[0];va[0]+=vertices[1]; va[0]=vertices[0];va[0]+=vertices[1];
va[0].normalize(); va[0].normalize();
va[1]=vertices[1];va[1]+=vertices[2]; va[1]=vertices[1];va[1]+=vertices[2];
va[1].normalize(); va[1].normalize();
va[2]=vertices[0];va[2]+=vertices[2]; va[2]=vertices[0];va[2]+=vertices[2];
va[2].normalize(); va[2].normalize();
if (outTexturePos) if (outTexturePos)
{ {
ta[0]=(texturePos[0]+texturePos[1])*0.5; ta[0]=(texturePos[0]+texturePos[1])*0.5;
ta[1]=(texturePos[1]+texturePos[2])*0.5; ta[1]=(texturePos[1]+texturePos[2])*0.5;
ta[2]=(texturePos[0]+texturePos[2])*0.5; ta[2]=(texturePos[0]+texturePos[2])*0.5;
} }
projectSphericalTriangle(clippingCap, va, outVertices, ta, outTextur ePos, nbI+1); projectSphericalTriangle(clippingCap, va, outVertices, ta, outTextur ePos, maxSqDistortion, nbI+1);
va[1]=va[0]; va[1]=va[0];
va[0]=vertices[0]; va[0]=vertices[0];
//va[1]=vertices[0]+vertices[1]; //va[1]=vertices[0]+vertices[1];
//va[1].normalize(); //va[1].normalize();
//va[2]=vertices[0]+vertices[2]; //va[2]=vertices[0]+vertices[2];
//va[2].normalize(); //va[2].normalize();
if (outTexturePos) if (outTexturePos)
{ {
ta[0]=texturePos[0]; ta[0]=texturePos[0];
ta[1]=(texturePos[0]+texturePos[1])*0.5; ta[1]=(texturePos[0]+texturePos[1])*0.5;
ta[2]=(texturePos[0]+texturePos[2])*0.5; ta[2]=(texturePos[0]+texturePos[2])*0.5;
} }
projectSphericalTriangle(clippingCap, va, outVertices, ta, outTextur ePos, nbI+1); projectSphericalTriangle(clippingCap, va, outVertices, ta, outTextur ePos, maxSqDistortion, nbI+1);
//va[0]=vertices[0]+vertices[1]; //va[0]=vertices[0]+vertices[1];
//va[0].normalize(); //va[0].normalize();
va[0]=va[1]; va[0]=va[1];
va[1]=vertices[1]; va[1]=vertices[1];
va[2]=vertices[1];va[2]+=vertices[2]; va[2]=vertices[1];va[2]+=vertices[2];
va[2].normalize(); va[2].normalize();
if (outTexturePos) if (outTexturePos)
{ {
ta[0]=(texturePos[0]+texturePos[1])*0.5; ta[0]=(texturePos[0]+texturePos[1])*0.5;
ta[1]=texturePos[1]; ta[1]=texturePos[1];
ta[2]=(texturePos[1]+texturePos[2])*0.5; ta[2]=(texturePos[1]+texturePos[2])*0.5;
} }
projectSphericalTriangle(clippingCap, va, outVertices, ta, outTextur ePos, nbI+1); projectSphericalTriangle(clippingCap, va, outVertices, ta, outTextur ePos, maxSqDistortion, nbI+1);
va[0]=vertices[0];va[0]+=vertices[2]; va[0]=vertices[0];va[0]+=vertices[2];
va[0].normalize(); va[0].normalize();
//va[1]=vertices[1]+vertices[2]; //va[1]=vertices[1]+vertices[2];
//va[1].normalize(); //va[1].normalize();
va[1]=va[2]; va[1]=va[2];
va[2]=vertices[2]; va[2]=vertices[2];
if (outTexturePos) if (outTexturePos)
{ {
ta[0]=(texturePos[0]+texturePos[2])*0.5; ta[0]=(texturePos[0]+texturePos[2])*0.5;
ta[1]=(texturePos[1]+texturePos[2])*0.5; ta[1]=(texturePos[1]+texturePos[2])*0.5;
ta[2]=texturePos[2]; ta[2]=texturePos[2];
} }
projectSphericalTriangle(clippingCap, va, outVertices, ta, outTextur ePos, nbI+1); projectSphericalTriangle(clippingCap, va, outVertices, ta, outTextur ePos, maxSqDistortion, nbI+1);
return; return;
} }
static QVarLengthArray<Vec3f, 4096> polygonVertexArray; static QVarLengthArray<Vec3f, 4096> polygonVertexArray;
static QVarLengthArray<Vec2f, 4096> polygonTextureCoordArray; static QVarLengthArray<Vec2f, 4096> polygonTextureCoordArray;
static QVarLengthArray<unsigned int, 4096> indexArray; static QVarLengthArray<unsigned int, 4096> indexArray;
void StelPainter::drawGreatCircleArcs(const StelVertexArray& va, const Sphe ricalCap* clippingCap) void StelPainter::drawGreatCircleArcs(const StelVertexArray& va, const Sphe ricalCap* clippingCap)
{ {
skipping to change at line 1231 skipping to change at line 1270
// The function object that we use as an interface between VertexArray::for eachTriangle and // The function object that we use as an interface between VertexArray::for eachTriangle and
// StelPainter::projectSphericalTriangle. // StelPainter::projectSphericalTriangle.
// //
// This is used by drawSphericalTriangles to project all the triangles coor dinates in a StelVertexArray into our global // This is used by drawSphericalTriangles to project all the triangles coor dinates in a StelVertexArray into our global
// vertex array buffer. // vertex array buffer.
class VertexArrayProjector class VertexArrayProjector
{ {
public: public:
VertexArrayProjector(const StelVertexArray& ar, StelPainter* apainte r, const SphericalCap* aclippingCap, VertexArrayProjector(const StelVertexArray& ar, StelPainter* apainte r, const SphericalCap* aclippingCap,
QVarLengthArray<Vec3f, 4096 >* aoutVertices, QVarLengthArray<Vec2f, 4096>* aoutTexturePos=NULL) QVarLengthArray<Vec3f, 4096 >* aoutVertices, QVarLengthArray<Vec2f, 4096>* aoutTexturePos=NULL, double amaxSqDistortion=5.)
: vertexArray(ar), painter(apainter), clippingCap(aclippi ngCap), outVertices(aoutVertices), : vertexArray(ar), painter(apainter), clippingCap(aclippi ngCap), outVertices(aoutVertices),
outTexturePos(aoutTexturePos) outTexturePos(aoutTexturePos), maxSqDistortion(amax SqDistortion)
{ {
} }
// Project a single triangle and add it into the output arrays // Project a single triangle and add it into the output arrays
inline void operator()(const Vec3d* v0, const Vec3d* v1, const Vec3d * v2, inline void operator()(const Vec3d* v0, const Vec3d* v1, const Vec3d * v2,
const Vec2f* t0, const Ve c2f* t1, const Vec2f* t2, const Vec2f* t0, const Ve c2f* t1, const Vec2f* t2,
unsigned int, unsigned in t, unsigned) unsigned int, unsigned in t, unsigned)
{ {
// XXX: we may optimize more by putting the declaration and the test outside of this method. // XXX: we may optimize more by putting the declaration and the test outside of this method.
const Vec3d tmpVertex[3] = {*v0, *v1, *v2}; const Vec3d tmpVertex[3] = {*v0, *v1, *v2};
if (outTexturePos) if (outTexturePos)
{ {
const Vec2f tmpTexture[3] = {*t0, *t1, *t2}; const Vec2f tmpTexture[3] = {*t0, *t1, *t2};
painter->projectSphericalTriangle(clippingCap, tmpVe rtex, outVertices, tmpTexture, outTexturePos); painter->projectSphericalTriangle(clippingCap, tmpVe rtex, outVertices, tmpTexture, outTexturePos, maxSqDistortion);
} }
else else
painter->projectSphericalTriangle(clippingCap, tmpVe rtex, outVertices, NULL, NULL); painter->projectSphericalTriangle(clippingCap, tmpVe rtex, outVertices, NULL, NULL, maxSqDistortion);
} }
// Draw the resulting arrays // Draw the resulting arrays
void drawResult() void drawResult()
{ {
painter->setVertexPointer(3, GL_FLOAT, outVertices->constDat a()); painter->setVertexPointer(3, GL_FLOAT, outVertices->constDat a());
if (outTexturePos) if (outTexturePos)
painter->setTexCoordPointer(2, GL_FLOAT, outTextureP os->constData()); painter->setTexCoordPointer(2, GL_FLOAT, outTextureP os->constData());
painter->enableClientStates(true, outTexturePos != NULL); painter->enableClientStates(true, outTexturePos != NULL);
painter->drawFromArray(StelPainter::Triangles, outVertices-> size(), 0, false); painter->drawFromArray(StelPainter::Triangles, outVertices-> size(), 0, false);
painter->enableClientStates(false); painter->enableClientStates(false);
} }
private: private:
const StelVertexArray& vertexArray; const StelVertexArray& vertexArray;
StelPainter* painter; StelPainter* painter;
const SphericalCap* clippingCap; const SphericalCap* clippingCap;
QVarLengthArray<Vec3f, 4096>* outVertices; QVarLengthArray<Vec3f, 4096>* outVertices;
QVarLengthArray<Vec2f, 4096>* outTexturePos; QVarLengthArray<Vec2f, 4096>* outTexturePos;
double maxSqDistortion;
}; };
void StelPainter::drawStelVertexArray(const StelVertexArray& arr) void StelPainter::drawStelVertexArray(const StelVertexArray& arr, bool chec kDiscontinuity)
{ {
if (checkDiscontinuity && prj->hasDiscontinuity())
{
// The projection has discontinuities, so we need to make su
re that no triangle is crossing them.
drawStelVertexArray(arr.removeDiscontinuousTriangles(this->g
etProjector().data()), false);
return;
}
setVertexPointer(3, GL_DOUBLE, arr.vertex.constData()); setVertexPointer(3, GL_DOUBLE, arr.vertex.constData());
if (arr.isTextured()) if (arr.isTextured())
{ {
setTexCoordPointer(2, GL_FLOAT, arr.texCoords.constData()); setTexCoordPointer(2, GL_FLOAT, arr.texCoords.constData());
enableClientStates(true, true); enableClientStates(true, true);
} }
else else
{ {
enableClientStates(true, false); enableClientStates(true, false);
} }
if (arr.isIndexed()) if (arr.isIndexed())
drawFromArray((StelPainter::DrawingMode)arr.primitiveType, a rr.indices.size(), 0, true, arr.indices.constData()); drawFromArray((StelPainter::DrawingMode)arr.primitiveType, a rr.indices.size(), 0, true, arr.indices.constData());
else else
drawFromArray((StelPainter::DrawingMode)arr.primitiveType, a rr.vertex.size()); drawFromArray((StelPainter::DrawingMode)arr.primitiveType, a rr.vertex.size());
enableClientStates(false); enableClientStates(false);
} }
void StelPainter::drawSphericalTriangles(const StelVertexArray& va, bool te xtured, const SphericalCap* clippingCap, bool doSubDivide) void StelPainter::drawSphericalTriangles(const StelVertexArray& va, bool te xtured, const SphericalCap* clippingCap, bool doSubDivide, double maxSqDist ortion)
{ {
if (va.vertex.isEmpty()) if (va.vertex.isEmpty())
return; return;
Q_ASSERT(va.vertex.size()>2); Q_ASSERT(va.vertex.size()>2);
#ifndef STELPAINTER_GL2 #ifndef STELPAINTER_GL2
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
#endif #endif
polygonVertexArray.clear(); polygonVertexArray.clear();
polygonTextureCoordArray.clear(); polygonTextureCoordArray.clear();
indexArray.clear(); indexArray.clear();
if (!doSubDivide) if (!doSubDivide)
{ {
if (prj->hasDiscontinuity()) // The simplest case, we don't need to iterate through the t
{ riangles at all.
// We don't want to subdivise the triangles, but the drawStelVertexArray(va);
projection has discontinuities,
// so we need to make sure that no triangle is cross
ing them.
const StelVertexArray& cleanVa = va.removeDiscontinu
ousTriangles(this->getProjector().data());
drawStelVertexArray(cleanVa);
}
else
{
// The simplest case, we don't need to iterate throu
gh the triangles at all.
drawStelVertexArray(va);
}
return; return;
} }
// the last case. It is the slowest, it process the triangles one b y one. // the last case. It is the slowest, it process the triangles one b y one.
{ {
// Project all the triangles of the VertexArray into our buf fer arrays. // Project all the triangles of the VertexArray into our buf fer arrays.
VertexArrayProjector result = va.foreachTriangle(VertexArray Projector(va, this, clippingCap, &polygonVertexArray, textured ? &polygonTe xtureCoordArray : NULL)); VertexArrayProjector result = va.foreachTriangle(VertexArray Projector(va, this, clippingCap, &polygonVertexArray, textured ? &polygonTe xtureCoordArray : NULL, maxSqDistortion));
result.drawResult(); result.drawResult();
return; return;
} }
} }
// Draw the given SphericalPolygon. // Draw the given SphericalPolygon.
void StelPainter::drawSphericalRegion(const SphericalRegion* poly, Spherica lPolygonDrawMode drawMode, const SphericalCap* clippingCap, bool doSubDivis e) void StelPainter::drawSphericalRegion(const SphericalRegion* poly, Spherica lPolygonDrawMode drawMode, const SphericalCap* clippingCap, bool doSubDivis e, double maxSqDistortion)
{ {
if (!prj->getBoundingCap().intersects(poly->getBoundingCap())) if (!prj->getBoundingCap().intersects(poly->getBoundingCap()))
return; return;
switch (drawMode) switch (drawMode)
{ {
case SphericalPolygonDrawModeBoundary: case SphericalPolygonDrawModeBoundary:
if (doSubDivise || prj->intersectViewportDiscontinui ty(poly->getBoundingCap())) if (doSubDivise || prj->intersectViewportDiscontinui ty(poly->getBoundingCap()))
drawGreatCircleArcs(poly->getOutlineVertexAr ray(), clippingCap); drawGreatCircleArcs(poly->getOutlineVertexAr ray(), clippingCap);
else else
drawStelVertexArray(poly->getOutlineVertexAr ray()); drawStelVertexArray(poly->getOutlineVertexAr ray(), false);
break; break;
case SphericalPolygonDrawModeFill: case SphericalPolygonDrawModeFill:
case SphericalPolygonDrawModeTextureFill: case SphericalPolygonDrawModeTextureFill:
glEnable(GL_CULL_FACE); glEnable(GL_CULL_FACE);
// The polygon is already tesselated as triangles // The polygon is already tesselated as triangles
if (doSubDivise || prj->intersectViewportDiscontinui ty(poly->getBoundingCap())) if (doSubDivise || prj->intersectViewportDiscontinui ty(poly->getBoundingCap()))
drawSphericalTriangles(poly->getFillVertexAr ray(), drawMode==SphericalPolygonDrawModeTextureFill, clippingCap, doSubDiv ise); drawSphericalTriangles(poly->getFillVertexAr ray(), drawMode==SphericalPolygonDrawModeTextureFill, clippingCap, doSubDiv ise, maxSqDistortion);
else else
drawStelVertexArray(poly->getFillVertexArray ()); drawStelVertexArray(poly->getFillVertexArray (), false);
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);
break; break;
default: default:
Q_ASSERT(0); Q_ASSERT(0);
} }
} }
/************************************************************************* /*************************************************************************
draw a simple circle, 2d viewport coordinates in pixel draw a simple circle, 2d viewport coordinates in pixel
 End of changes. 49 change blocks. 
145 lines changed or deleted 197 lines changed or added

This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/