如何在SDL中绘制多边形?

时间:2016-12-06 02:26:47

标签: c++ opengl sdl polygon sdl-2

我想在SDL中绘制一个多边形。边数将由程序在运行时确定。任何人都可以帮我解决这个问题吗?

2 个答案:

答案 0 :(得分:3)

它不是原生SDL,但有一个库sdl_gfx,它具有filledPolygonColour功能。

答案 1 :(得分:0)

几年前我有同样的问题我found the following implementation

bool DrawFilledPolygon(PolygonShape poly, const SDL_Color color, SDL_Renderer* renderer) {
    int topY;            // used to hold the y coordinate of the top vertex
    int topCnt;            // used to hold the index of the top vertex
    int leftCnt;            // used to hold the index of the vertex left of the top vertex
    int rightCnt;           // used to hold the index of the vertex right of the top vertex
    int startX;            // Starting point to draw the line, uses FP math
    int endX;            // ending point to draw the line, uses FP math
    int cntY;            // y position of the current line
    int leftSlope;              // Slope of the left side, uses FP math
    int rightSlope;             // Slope of the right side, uses FP math
    int cnt;            // counting variable used in loops
    int numVerts = poly.GetNumberOfVertices();    // number of vertices in the polygon being drawn, initialize immediately
    int numVertsProc = 1;           // number of vertices that have been processed, initialize to 1

    Point center = poly.GetCenter();
    Point *verts = poly.GetVertices();      // Vertex information of the polygon

    topY = verts[0].y;          // Initialize the top y coordinate to the first point
    topCnt = 0;            // set to top point to 0

    // assumes points in counterclockwise order
    // find the true top point
    for(cnt = 1; cnt < numVerts; cnt++)      // for all the vertices in the polygon
    {
        if(verts[cnt].y < topY)        // if vertex of the current vertex is above the top vertex
        {
            topY = verts[cnt].y;        // set the top vertex to the current vertex
            topCnt = cnt;           // set the reference number of the top vertex
        }
    }

    // find point to left
    leftCnt = topCnt - 1;           // set the left point to one less than the top point
    if(leftCnt < 0)             // if the left vertex specified is less than 0
        leftCnt = numVerts - 1;        // set the left vertex to the top vertex

    // find point to right
    rightCnt = topCnt + 1;          // set the right vertex to one more than the top vertex
    if(rightCnt >= numVerts)        // if the right vertex specified is more than the number of vertices
        rightCnt = 0;          // set it equal to 0

    startX = endX = (verts[topCnt].x + center.x) << 16;  // set the starting and ending points of the line
    cntY = verts[topCnt].y;         // set the first y value to draw at

    if(verts[leftCnt].y != verts[topCnt].y)     // if the top and left vertex do not have the same y value
        leftSlope = ((verts[leftCnt].x - verts[topCnt].x) << 16) / (verts[leftCnt].y - verts[topCnt].y);    // find the left side slope
    if(verts[rightCnt].y != verts[topCnt].y)    // if the top and right vertex do not have the same y value
        rightSlope = ((verts[rightCnt].x - verts[topCnt].x) << 16) / (verts[rightCnt].y - verts[topCnt].y); // find the right side slope

    SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, color.a);       

    // find slopes
    while(numVertsProc < numVerts)          // if there remain vertices to be processed
    {
     // rasterize to first point
        while(cntY < verts[leftCnt].y && cntY < verts[rightCnt].y)  // while one of the two side points hasn't been reached yet
        {
            SDL_RenderDrawLine(renderer, startX >> 16, cntY + center.y, endX >> 16, cntY + center.y);
            //DrawLine(Point(startX >> 16, cntY + center.y), Point(endX >> 16, cntY + center.y), col);  // draw a line between the sides
            cntY++;             // increment the y position by 1
            startX += leftSlope;        // increase the starting x value by the left slope
            endX += rightSlope;        // increase the ending x value by the right slope
        }
        // set top point to point met
        // set point met to next point
        // find new slope
        if(verts[leftCnt].y <= cntY)      // if the raster line passes the left coordinate
        {
            topCnt = leftCnt;        // set the top point to the left side
            leftCnt--;          // decrement the left point
            if(leftCnt < 0)         // if the left point is less than zero
                leftCnt = numVerts - 1;      // wrap around
            if(verts[leftCnt].y != verts[topCnt].y)     // if the top and new left vertex do not have the same y value
                leftSlope = ((verts[leftCnt].x - verts[topCnt].x) << 16) / (verts[leftCnt].y - verts[topCnt].y);    // find the left side slope

            startX = (verts[topCnt].x + center.x) << 16;    // set the starting x position
            numVertsProc++;         // increment the number of vertices processed
        }

        if(verts[rightCnt].y <= cntY)      // if the raster line passes the right coordinate
        {
            topCnt = rightCnt;        // set the top point to the right side
            rightCnt++;          // increment the right point
            if(rightCnt == numVerts)      // if the right point is more than the number of vertices
                rightCnt = 0;        // set the right point to zero
            if(verts[rightCnt].y != verts[topCnt].y)  // if the top and new right vertex do not have the same y value
                rightSlope = ((verts[rightCnt].x - verts[topCnt].x) << 16) / (verts[rightCnt].y - verts[topCnt].y); // find the right side slope

            endX = (verts[topCnt].x + center.x) << 16;  // set the ending x position
            numVertsProc++;         // increment the number of vertices processed
        }
        SDL_RenderDrawLine(renderer, startX >> 16, cntY + center.y, endX >> 16, cntY + center.y);
        //DrawLine(Point(startX >> 16, cntY + center.y), Point(endX >> 16, cntY + center.y), col); // draw a line between the sides 
    }
    // continue until the number of vertices p0 has touched == number of vertices

    return true;            // return success
}

通过这段代码我改编了我的代码,以便按如下方式进行测试:

#include "SDL.h"
//#include "SDL_image.h"
//#include "SDL_ttf.h"
//#include "SDL_mixer.h"

#include <iostream>
#include <vector>

class Point {
    public:
        Point() {};
        Point(int x, int y) { this->x = x; this->y = y; };
        int x, y;
};

class PolygonShape {
    public:
        PolygonShape(std::vector<Point> vertices);
        ~PolygonShape();
        Point GetCenter(void);  
        Point * GetVertices(void);
        int GetNumberOfVertices(void);
    private:
        Point * vertices;
        Point center;
        int length;
};

PolygonShape::PolygonShape(std::vector<Point> vertices){
    int minX = 0xFFFF, minY = 0xFFFF, maxX = 0, maxY = 0;
    this->length = vertices.size();
    this->vertices = new Point[length];
    for (int i = 0; i < this->length; i++) {
        this->vertices[i] = Point(vertices[i].x, vertices[i].y);
        if (this->vertices[i].x > maxX) maxX = this->vertices[i].x;
        if (this->vertices[i].x < minX) minX = this->vertices[i].x;
        if (this->vertices[i].y > maxY) maxY = this->vertices[i].y;
        if (this->vertices[i].y < minY) minY = this->vertices[i].y;
    }
    this->center.x = minX + ((maxX - minX) / 2);
    this->center.y = minY + ((maxY - minY) / 2);
}

PolygonShape::~PolygonShape() {
    delete[] this->vertices;
}

Point PolygonShape::GetCenter(void) {
    return center;
}

Point * PolygonShape::GetVertices(void) {
    return this->vertices;
}

int PolygonShape::GetNumberOfVertices(void) {
    return this->length;
}

主要功能:

int main(int argc, char** argv) {
    if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
        std::cout << "SDL_Init Error: " << SDL_GetError() << std::endl;
        return 1;
    }
    SDL_Window *win = SDL_CreateWindow("Prueba", 100, 100, 960, 540, SDL_WINDOW_SHOWN);
    if (win == NULL) {
        std::cout << "SDL_CreateWindow Error: " << SDL_GetError() << std::endl;
        return 1;
    }
    SDL_Renderer *ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
    if (ren == NULL) {
        std::cout << "SDL_CreateRenderer Error: " << SDL_GetError() << std::endl;
        return 1;
    }

    SDL_RenderClear(ren);

    SDL_Color color = {.r = 255, .g = 255, .b = 255, .a = 255 };

    std::vector<Point> vertices;

    vertices.push_back(Point(10, 10));
    vertices.push_back(Point(100, 10));
    vertices.push_back(Point(150, 75));
    vertices.push_back(Point(20, 105));

    PolygonShape poly = PolygonShape(vertices);

    DrawFilledPolygon(poly, color, ren);

    SDL_RenderPresent(ren);

    getchar();

    SDL_DestroyRenderer(ren);
    SDL_DestroyWindow(win);
    SDL_Quit();

    return 0;
}

我希望它可以帮到你! : - )