2016-07-12 5 views
3

(я использую SDL2)HOWTO рисовать круги, дуги и векторную графику в SDL?

SDL is a relatively small library for "low level access to audio, keyboard, mouse, joystick, and graphics hardware via OpenGL and Direct3D" Он используется для разработки игр и, в моем случае, как простой аудиовизуальный выход и мышь + клавиатура. Это не «инструментарий», как GTK, Qt, wxWindows и т. Д. Но это кросс-платформенный.

But the only way I can find to draw a shape is with the line, rect and pixel functions.

Помимо использования триг или «уравнение окружности», как я мог бы нарисовать кривую? Как насчет общей векторной графики?

Является ли SDL подходящей отправной точкой или я должен искать в другом месте?

ответ

4

Если вы хотите написать свою собственную функцию рисования круга, я бы предложил адаптировать midpoint algorithm к SDL2 путем рисования пикселей.

Кривые будут выполнены аналогичным образом, но будут использовать больше алгоритмов рисования эллипсов.

Фактическая векторная графика начинает усложняться, и вам, вероятно, придется найти что-то, что отображает SVG-файлы, и я не уверен, что для SDL2 есть много вариантов.

Однако, если вы предпочитаете просто функции, с которыми вы можете работать, я предлагаю перейти прямо к SDL2_gfx. У него есть еще много функций, которые уже были реализованы для вас.

1

SDL позволяет сторонним библиотекам рисовать по текстуре. Если каир желательно, он может быть использован в функции как это:

cairo_t*cb(cairo_t*cr) 
{cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); 
cairo_rectangle(cr, 10, 20, 128, 128); 
cairo_stroke(cr); 
return cr; 
} 

затем центибар могут быть переданы этой функции:

cairo_t*cai(SDL_Window*w,SDL_Renderer*r,cairo_t*(*f)(cairo_t*)) 
{int width, height, pitch;void *pixels; 
SDL_GetWindowSize(w, &width, &height); 
SDL_Texture*t=SDL_CreateTexture(r,SDL_PIXELFORMAT_ARGB8888,SDL_TEXTUREACCESS_STREAMING,width,height); 
SDL_LockTexture(t, NULL, &pixels, &pitch); 
cairo_surface_t *cs=cairo_image_surface_create_for_data(pixels,CAIRO_FORMAT_ARGB32,width,height,pitch); 
cairo_t*s=cairo_create(cs); 
cairo_t*fr=f(s);SDL_UnlockTexture(t);SDL_RenderCopy(r,t,NULL,NULL);SDL_RenderPresent(r); 
return fr; 
} 
0

Если вы хотите сделать круг или эллипс без 3-й партии библиотеки, включите math.h и используйте функцию ниже, которую я написал. Он очень хорошо рисует эллипс или круги. Протестировано на SDL 2.0.2 и работает. Он рисует одну квадрантную дугу и отображает другие дуги, уменьшая вызовы cosf и sinf.

//draw one quadrant arc, and mirror the other 4 quadrants 
void sdl_ellipse(SDL_Renderer* r, int x0, int y0, int radiusX, int radiusY) 
{ 
    float pi = 3.14159265358979323846264338327950288419716939937510; 
    float pih = pi/2.0; //half of pi 

    //drew 28 lines with 4x4 circle with precision of 150 0ms 
    //drew 132 lines with 25x14 circle with precision of 150 0ms 
    //drew 152 lines with 100x50 circle with precision of 150 3ms 
    const int prec = 27; // precision value; value of 1 will draw a diamond, 27 makes pretty smooth circles. 
    float theta = 0;  // angle that will be increased each loop 

    //starting point 
    int x = (float)radiusX * cos(theta);//start point 
    int y = (float)radiusY * sin(theta);//start point 
    int x1 = x; 
    int y1 = y; 

    //repeat until theta >= 90; 
    float step = pih/(float)prec; // amount to add to theta each time (degrees) 
    for(theta=step; theta <= pih; theta+=step)//step through only a 90 arc (1 quadrant) 
    { 
     //get new point location 
     x1 = (float)radiusX * cosf(theta) + 0.5; //new point (+.5 is a quick rounding method) 
     y1 = (float)radiusY * sinf(theta) + 0.5; //new point (+.5 is a quick rounding method) 

     //draw line from previous point to new point, ONLY if point incremented 
     if((x != x1) || (y != y1))//only draw if coordinate changed 
     { 
      SDL_RenderDrawLine(r, x0 + x, y0 - y, x0 + x1, y0 - y1);//quadrant TR 
      SDL_RenderDrawLine(r, x0 - x, y0 - y, x0 - x1, y0 - y1);//quadrant TL 
      SDL_RenderDrawLine(r, x0 - x, y0 + y, x0 - x1, y0 + y1);//quadrant BL 
      SDL_RenderDrawLine(r, x0 + x, y0 + y, x0 + x1, y0 + y1);//quadrant BR 
     } 
     //save previous points 
     x = x1;//save new previous point 
     y = y1;//save new previous point 
    } 
    //arc did not finish because of rounding, so finish the arc 
    if(x!=0) 
    { 
     x=0; 
     SDL_RenderDrawLine(r, x0 + x, y0 - y, x0 + x1, y0 - y1);//quadrant TR 
     SDL_RenderDrawLine(r, x0 - x, y0 - y, x0 - x1, y0 - y1);//quadrant TL 
     SDL_RenderDrawLine(r, x0 - x, y0 + y, x0 - x1, y0 + y1);//quadrant BL 
     SDL_RenderDrawLine(r, x0 + x, y0 + y, x0 + x1, y0 + y1);//quadrant BR 
    } 
} 
1

Это пример Алгоритма окружности Midpoint, как указано выше. Это не требует математической библиотеки и очень быстро. (Отображает примерно 500 микросекунд) Это то, что Windows использует/используется для растеризации кругов.

typedef int32_t s32; 

void DrawCircle(SDL_Renderer *Renderer, s32 _x, s32 _y, s32 radius) 
{ 
    s32 x = radius - 1; 
    s32 y = 0; 
    s32 tx = 1; 
    s32 ty = 1; 
    s32 err = tx - (radius << 1); // shifting bits left by 1 effectively 
           // doubles the value. == tx - diameter 
    while (x >= y) 
    { 
     // Each of the following renders an octant of the circle 
     SDL_RenderDrawPoint(Renderer, _x + x, _y - y); 
     SDL_RenderDrawPoint(Renderer, _x + x, _y + y); 
     SDL_RenderDrawPoint(Renderer, _x - x, _y - y); 
     SDL_RenderDrawPoint(Renderer, _x - x, _y + y); 
     SDL_RenderDrawPoint(Renderer, _x + y, _y - x); 
     SDL_RenderDrawPoint(Renderer, _x + y, _y + x); 
     SDL_RenderDrawPoint(Renderer, _x - y, _y - x); 
     SDL_RenderDrawPoint(Renderer, _x - y, _y + x); 

     if (err <= 0) 
     { 
     y++; 
     err += ty; 
     ty += 2; 
     } 
     else if (err > 0) 
     { 
     x--; 
     tx += 2; 
     err += tx - (radius << 1); 
     } 
    } 
} 

** Обратите внимание, что «еще, если» заявление на самом деле является второй «если» в первоначальной реализации, но я убежден, что это семантическая ошибка.

Смежные вопросы