2013-12-11 242 views
1

下面是我正在做的一些截图。目前,我从绘制弯曲的边框到这个矩形卡住了。从弧形边缘画一条曲线

naah

我的第一个解决方案是:绘制矩形落后四分的圆,但如果我调整形状的透明度,你可以看到,四分圆获得展示。

neeh

我知道这是你们很基本的,但我不是在数学真的很好。

我的确尝试重新使用弧的计算边并添加边框的大小,但是我得到了这个结果。

niih

我也在想Bezier曲线作为替代,但我认为这是更有效的只是重用计算顶点并添加所有缺少的。另外,我不知道如何计算曲线点贝塞尔曲线并找到合适的数量t将是非常昂贵的计算,所以我没有实现它。

下面是我如何绘制内部四分之一圆,我想我可以重用它。

void drawArc(int x, int y, 
      int startAngle, int endAngle, 
      uint32_t radiusX, uint32_t radiusY, 
      int border_x, int border_y, 
      const rgb color, 
      const rgb bcX, const rgb bcY, 
      uint8_t opacity) 
{ 
    if (radiusX <= 0 || radiusY <= 0) return; 

    static constexpr float DTR = 3.14159/180; 

    float cx, cy; 
    int step; 

    static std::vector<float> verts; 
    static std::vector<uint8_t> colors; 

    if (startAngle < endAngle) 
    { 
     step = +1; 
     ++ endAngle; 
    } else 
    { 
     step = -1; 
     -- endAngle; 
    } 

    verts.clear(); 
    colors.clear(); 

    verts.push_back(x); 
    verts.push_back(y); 

    colors.push_back(color[R]); 
    colors.push_back(color[G]); 
    colors.push_back(color[B]); 
    colors.push_back(opacity); 

    while (startAngle != endAngle) 
    { 
     cx = cos(DTR * startAngle) * radiusX; 
     cy = sin(DTR * startAngle) * radiusY; 

     verts.push_back(x + cx); 
     verts.push_back(y - cy); 

     colors.push_back(color[R]); 
     colors.push_back(color[G]); 
     colors.push_back(color[B]); 
     colors.push_back(opacity); 

     startAngle += step; 
    } 

    drawElements(GL_POLYGON, sizeof(arcIndices)/sizeof(arcIndices[0]), GL_FLOAT, 
       &verts[0], &colors[0], &arcIndices[0]); 

    if (border_x != 0 || border_y != 0) 
    { 
     //remove (x, y) 
     verts.erase(verts.begin(), verts.begin() + 2); 

//  float px, py; 
// 
//  px = *(verts.begin() + 0); 
//  py = *(verts.begin() + 1); 
// 
//  glPointSize(5); 
// 
//  glBegin(GL_POINTS); 
// 
//  glColor3ub(0,0,255); 
//  glVertex2i(px, py); 
// 
//  px = *(verts.end() - 2); 
//  py = *(verts.end() - 1); 
// 
//  glColor3ub(255,0,0); 
//  glVertex2i(px , py); 
//  glEnd(); 

     //attempting to reuse the edges 
     //I think the last vertices are opposed 
     //that's why I got a crossed out lines?? 
     for (int i = 0;i <= 90; ++i) 
     { 
      verts.push_back(verts[i + 0] + border_x); 
      verts.push_back(verts[i + 1] + border_y); 

      colors.push_back(bcX[R]); 
      colors.push_back(bcX[G]); 
      colors.push_back(bcX[B]); 
      colors.push_back(opacity); 
     } 

     //91 = steps from 0-90 degree revolution 
     //182 = 91 * 2 
     unsigned int index[182 + 91 * 2]; 
     for (int i = 0;i < 182 + 91 * 2; ++i) 
      index[i] = i; 

     drawElements(GL_LINE_LOOP, verts.size()/2, GL_FLOAT, 
        &verts[0], &colors[0], &index[0]); 
    } 

} 

编辑:

我不能只是重复之前的预先计算(X,Y)?

nooh

对不起,过多的使用图片

的红点是预先计算出(X,Y),我指的是,只是附加在这接下来的弧形底座。

我要渲染很多这种类型,所以我需要尽可能高效(没有太多的用于三角函数)。

更新:

这里是我使用stencil buffer得到的是什么Andon M. Coleman建议的结果:

nuuh

顺便说一句,你可以看到,我试图模仿我自己使用OpenGL的UI:D

+0

您是否考虑过使用模板缓冲区来逐字切出灰色形状覆盖的区域?你将不得不改变你绘制一些东西的顺序,但是你不必使用令人讨厌的线条基元。 –

+0

@ AndonM.Coleman我可能会使用它,当我从该rect应用纹理时,但这不是很昂贵吗? – mr5

+0

@ AndonM.Coleman你能给我一个链接,我该怎么做?我认为这很有趣,并且会在我开始在其上应用纹理时做我未来的必需品。 – mr5

回答

1

你表示在看到使用模板缓存昨天这到底是怎么解决的兴趣,所以我正在跟进一些基本的伪代码。

glClearStencil (0x0); 
glClear  (GL_STENCIL_BUFFER_BIT); 

glEnable  (GL_STENCIL_TEST); 
glStencilFunc (GL_ALWAYS, 0x0, 0x0); 

// Add 1 to stencil buffer at every location the object to be bordered is visible 
glStencilOp (GL_KEEP, GL_KEEP, GL_INCR); 

// Draw your grey object 

// Only draw the red border where the grey object was never drawn (stencil = 0x0) 
glStencilFunc (GL_EQUAL, 0x0, 0xff); 

// Draw your red quarter circles 

glDisable  (GL_STENCIL_TEST); 

每次绘制轮廓对象时清除模板缓冲区可能是矫枉过正。如果你选择每帧一次地清除模板缓冲区,你可以做一些非常有趣的事情。例如,如果你画的轮廓作为一个单独的传球后所有非概括形状绘制,你可以使用这个模板缓冲区设置勾勒出工会(而不是包括对象的交叉区域作为绘制的轮廓的一部分)任何重叠的对象..这将允许您从简单的圆角矩形构造更复杂的形状。

当然这个工作,你的像素格式必须有一个模板缓存。我将不得不将这部分留给你,因为设置这个过程是特定于实现的。

+0

如果我移动到'glEnable(GL_STENCIL_TEST)'它的顶部,但是如果我遵循你发布的内容,它不会。无论如何,它现在真的很棒!但如果我尝试在它上添加纹理,它将不会显示出来。也许我只需要预先计算我的drawable的顺序。也许我会暂时离开你说的“像素格式设置”,只要我没有看到任何担心。很多人非常感谢你:D'stencil buffer'是我在'OpenGL'中发现的最好的东西之一' – mr5

+0

@ mr5:啊,好点。这完全滑落了我的想法,我做了一些应该更好的改变。 –

+0

此外,它甚至可以不使用glStencilFunc(GL_ALWAYS,0x0,0x0);',为什么? – mr5

1

GL_POLYGON只适用于多边形。

链接在一起,在你的内,外半径的顶点,形成四边形/三角形:

partial torus

#include <GL/glut.h> 
#include <cmath> 

void Torus2d 
    ( 
    float angle,   // starting angle in radians 
    float length,   // length of arc in radians, >0 
    float radius,   // inner radius, >0 
    float width,   // width of torus, >0 
    unsigned int samples // number of circle samples, >=3 
    ) 
{ 
    if(samples < 3) samples = 3; 
    const float outer = radius + width; 
    glBegin(GL_QUAD_STRIP); 
    for(unsigned int i = 0; i <= samples; ++i) 
    { 
     float a = angle + (i/(float)samples) * length; 
     glVertex2f(radius * cos(a), radius * sin(a)); 
     glVertex2f(outer * cos(a), outer * sin(a)); 
    } 
    glEnd(); 
} 

void display() 
{ 
    glClear(GL_COLOR_BUFFER_BIT); 

    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    double w = glutGet(GLUT_WINDOW_WIDTH); 
    double h = glutGet(GLUT_WINDOW_HEIGHT); 
    double ar = w/h; 
    glOrtho(-4 * ar, 4 * ar, -4, 4, -1, 1); 

    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 

    glColor3ub(255, 0, 0); 
    Torus2d(0, 1.57079633, 2, 1, 20); 

    glutSwapBuffers(); 
} 

int main(int argc, char **argv) 
{ 
    glutInit(&argc, argv); 
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE); 
    glutInitWindowSize(640, 480); 
    glutCreateWindow("GLUT"); 
    glutDisplayFunc(display); 
    glutMainLoop(); 
    return 0; 
} 
+0

我实际上对将在'Torus2D'中传递的参数感到困惑。你能解释一下吗? – mr5

+0

@ mr5:已编辑。 “角度”是逆时针方向绕开环面多远。 “长度”是环面应该有多长。 “半径”是内圆环半径。 “宽度”是环面应该有多宽。样品越大,环面看起来就越好,但会牺牲更多的几何形状。 – genpfault

+0

我对这些三角函数有点困惑。在我的情况下,弧半径分开,即rX,rY。我怎么修改它来达到这个目的?难道我不能只是再次摆脱那些trigo?我不能只重用预先计算的x,y吗? – mr5