web-dev-qa-db-fra.com

COMMENT dessiner des cercles, des arcs et des graphiques vectoriels en SDL?

(J'utilise SDL2)

SDL est une bibliothèque relativement petite pour "un accès bas niveau à l'audio, au clavier, à la souris, au joystick et au matériel graphique via OpenGL et Direct3D" Il est utilisé pour le développement de jeux et, dans mon cas, comme simple audiovisuel sortie et entrée souris + clavier. Ce n'est pas une "boîte à outils" comme GTK, Qt, wxWindows, etc. Mais c'est multi-plateforme.

Mais la seule façon que je peux trouver pour dessiner une forme est avec les fonctions ligne, rect et pixel.

En dehors de l'utilisation de trig ou de "l'équation d'un cercle", comment pourrais-je dessiner une courbe? Que diriez-vous des graphiques vectoriels généraux?

SDL est-il un point de départ approprié ou dois-je chercher ailleurs?

11
effbiae

Si vous souhaitez écrire votre propre fonction de dessin de cercle, je suggère d'adapter algorithme de point médian à SDL2 en dessinant des pixels.

Les courbes seraient effectuées de la même manière, mais utiliseraient davantage un algorithme de dessin d'ellipses.

Les graphiques vectoriels réels commencent à devenir beaucoup plus compliqués, et vous devrez probablement trouver quelque chose qui rend les fichiers SVG, ce dont je ne suis pas sûr qu'il existe de nombreuses options pour SDL2.

Cependant, si vous préférez simplement avoir des fonctions avec lesquelles vous pouvez travailler, je vous suggère d'aller directement à SDL2_gfx à la place. Il a beaucoup plus de fonctions déjà implémentées avec lesquelles vous pouvez travailler.

14
davek

Ceci est un exemple de l'algorithme du cercle médian tel que référencé ci-dessus. Il ne nécessite pas de bibliothèque mathématique et est très rapide. (Rendu en environ 500 microsecondes) C'est ce que Windows utilise/utilisé pour pixelliser les cercles.

void DrawCircle(SDL_Renderer * renderer, int32_t centreX, int32_t centreY, int32_t radius)
{
   const int32_t diameter = (radius * 2);

   int32_t x = (radius - 1);
   int32_t y = 0;
   int32_t tx = 1;
   int32_t ty = 1;
   int32_t error = (tx - diameter);

   while (x >= y)
   {
      //  Each of the following renders an octant of the circle
      SDL_RenderDrawPoint(renderer, centreX + x, centreY - y);
      SDL_RenderDrawPoint(renderer, centreX + x, centreY + y);
      SDL_RenderDrawPoint(renderer, centreX - x, centreY - y);
      SDL_RenderDrawPoint(renderer, centreX - x, centreY + y);
      SDL_RenderDrawPoint(renderer, centreX + y, centreY - x);
      SDL_RenderDrawPoint(renderer, centreX + y, centreY + x);
      SDL_RenderDrawPoint(renderer, centreX - y, centreY - x);
      SDL_RenderDrawPoint(renderer, centreX - y, centreY + x);

      if (error <= 0)
      {
         ++y;
         error += ty;
         ty += 2;
      }

      if (error > 0)
      {
         --x;
         tx += 2;
         error += (tx - diameter);
      }
   }
}
14
Scotty Stephens

SDL permet aux bibliothèques tierces de dessiner sur une texture. Si le Caire était souhaitable, il pourrait être utilisé dans une fonction comme celle-ci:

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;
}

alors cb peut être passé à cette fonction:

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;
}
2
effbiae

Si vous voulez faire un cercle ou une ellipse sans bibliothèques tierces, incluez math.h et utilisez la fonction ci-dessous que j'ai écrite. Il dessinera très bien une ellipse ou des cercles aliasés. Testé sur SDL 2.0.2 et fonctionne. Il dessine un arc de quadrant et reflète les autres arcs, réduisant les appels à cosf et 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
12oclocker