2013-08-14 10 views
0

У меня есть следующий код, чтобы нарисовать произвольную дугу:Как нарисовать суженную дугу (кривая с уменьшающейся толщиной) в OpenGL?

void CenteredArc::drawPolygonArc(float radius, float thickness, float startAngle, float arcAngle) { 
    float num_segments = 360.0; 

    float radiusOuter = radius + thickness/2; 
    float radiusInner = radius - thickness/2; 
    float theta = arcAngle/num_segments; 
    float tangetial_factor = tanf(theta);//calculate the tangential factor 

    float radial_factor = cosf(theta);//calculate the radial factor 

    float xxOuter = radiusOuter * cosf(startAngle); 
    float yyOuter = radiusOuter * sinf(startAngle); 
    float xxInner = radiusInner * cosf(startAngle); 
    float yyInner = radiusInner * sinf(startAngle); 

    float prevXXOuter = -1; 
    float prevYYOuter = -1; 
    float prevXXInner = -1; 
    float prevYYInner = -1; 

    glPolygonMode(GL_FRONT, GL_FILL); 
    for(int ii = 0; ii < num_segments; ii++) 
    { 
     if (prevXXOuter != -1) { 
      glBegin(GL_POLYGON); 
       glVertex2f(prevXXOuter, prevYYOuter); 
       glVertex2f(xxOuter,  yyOuter); 
       glVertex2f(xxInner,  yyInner); 
       glVertex2f(prevXXInner, prevYYInner); 
      glEnd(); 
     } 

     //calculate the tangential vector 
     //remember, the radial vector is (x, y) 
     //to get the tangential vector we flip those coordinates and negate one of them 

     float txOuter = -yyOuter; 
     float tyOuter = xxOuter; 
     float txInner = -yyInner; 
     float tyInner = xxInner; 

     //add the tangential vector 

     prevXXOuter = xxOuter; 
     prevYYOuter = yyOuter; 
     prevXXInner = xxInner; 
     prevYYInner = yyInner; 

     xxOuter += txOuter * tangetial_factor; 
     yyOuter += tyOuter * tangetial_factor; 
     xxInner += txInner * tangetial_factor; 
     yyInner += tyInner * tangetial_factor; 

     //correct using the radial factor 
     xxOuter *= radial_factor; 
     yyOuter *= radial_factor; 
     xxInner *= radial_factor; 
     yyInner *= radial_factor; 
    } 
} 

Тем не менее, я хотел бы, дугу, чтобы начать с заданной толщиной на одном конце, и постепенно уменьшает до толщины нуля на другом конце , Какие-либо предложения?

Edit: Я не использую GL_LINE_STRIP потому, что я пытаюсь избежать перекрывающихся линий и пробелов, как так:

enter image description here

ответ

0

Я хотел бы использовать line strip с уменьшением glLineWidth.

Это моя реализация, она не градиентно уменьшает lineWidth, но ее можно было бы изменить, чтобы сделать это. Извините за дополнительные вещи, это из моего игрового движка.

for(int i=0;i<arcs().size();i++) 
{ 
     Entities::Arc temp = arcs().at(i); 
     glLineWidth(temp.LW.value); // change LWidth 

     glColor3f(temp.CL.R, temp.CL.G, temp.CL.B); 

     // theta is now calculated from the arc angle instead, the 
     // - 1 part comes from the fact that the arc is open 
     float theta = temp.A.value*DEG2RAD/float(WW_SPLINE_ACCURACY - 1); 

     float tan = tanf(theta); 
     float cos = cosf(theta); 

     // we are now at the starting angle 
     double x = temp.R.value * cosf(temp.A.value*DEG2RAD); 
     double y = temp.R.value * sinf(temp.A.value*DEG2RAD); 

     // since the arc is not a closed curve, this is a strip now 
     glBegin(GL_LINE_STRIP); 
     for(int ii = 0; ii < WW_SPLINE_ACCURACY; ii++) 
     { 
      glVertex2d(x + temp.C.X, y + temp.C.Y); 
      double tx = -y; 
      double ty = x; 
      x += tx * tan; 
      y += ty * tan; 
      x *= cos; 
      y *= cos; //y = (y + (ty*tan))*cos; 
     } 
    glEnd(); 
    glLineWidth(WW_DEFAULT_LWIDTH); // reset LWidth 
} 

Я также использовал эти значения

#define WW_SPLINE_ACCURACY 72 // 72 for extra smooth arcs/circles, 32 minimum 
#define WW_BEZIER_ACCURACY 20 

/* Math stuff */ 
#define DEG2RAD 3.14159/180 
#define PI 3.1415926535897932384626433832795; 

... 

glDisable(GL_TEXTURE_2D); 
glDisable(GL_DEPTH_TEST); 
glDisable(GL_COLOR_MATERIAL); 
glEnable (GL_LINE_SMOOTH); 
glEnable (GL_BLEND); 
//glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 
glHint (GL_LINE_SMOOTH_HINT, GL_DONT_CARE); 
glEnable(GL_POLYGON_SMOOTH); 
glClearColor(0.188f, 0.169f, 0.329f, 1.0f); //#302b54 

Я не позволил выпустить полный исходный код, так как я написал это для компании, но разделяя часть или два не ушибет кто-нибудь: D

+0

Что такое 'WW_SPLINE_ACCURACY'? – carmenism

+0

@vulpix это константа, контролирующая, сколько вершин будет использовано для каждой дуги! –

+0

Причина, по которой я не использовал 'GL_LINE_STRIP', а рисовал полигоны, заключается в том, что рендеринг не выглядел так хорошо за пределами толщины 5 пикселей. На внешнем краю вы могли видеть отсутствующие слайды. – carmenism