From c37e9ed6bf4b60f4bce6e884f5079cdddede8708 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sun, 23 Jul 2017 01:49:27 -0300 Subject: [PATCH] Use vector2 arrays instead of raw float arrays for graphics primitives. Simplifies the code a bit. --HG-- branch : minor --- src/modules/graphics/Graphics.cpp | 95 ++++++++++++-------------- src/modules/graphics/Graphics.h | 18 +++-- src/modules/graphics/Polyline.cpp | 16 ++--- src/modules/graphics/Polyline.h | 16 ++--- src/modules/graphics/wrap_Graphics.cpp | 94 ++++++++++++++----------- 5 files changed, 124 insertions(+), 115 deletions(-) diff --git a/src/modules/graphics/Graphics.cpp b/src/modules/graphics/Graphics.cpp index 394513871..16f1b2841 100644 --- a/src/modules/graphics/Graphics.cpp +++ b/src/modules/graphics/Graphics.cpp @@ -951,7 +951,7 @@ void Graphics::printf(const std::vector &str, Font *font, f * Primitives (points, shapes, lines). **/ -void Graphics::points(const float *coords, const Colorf *colors, size_t numpoints) +void Graphics::points(const Vector2 *positions, const Colorf *colors, size_t numpoints) { const Matrix4 &t = getTransform(); bool is2D = t.isAffine2DTransform(); @@ -965,9 +965,9 @@ void Graphics::points(const float *coords, const Colorf *colors, size_t numpoint StreamVertexData data = requestStreamDraw(req); if (is2D) - t.transformXY((Vector2 *) data.stream[0], (const Vector2 *) coords, req.vertexCount); + t.transformXY((Vector2 *) data.stream[0], positions, req.vertexCount); else - t.transformXY0((Vector3 *) data.stream[0], (const Vector2 *) coords, req.vertexCount); + t.transformXY0((Vector3 *) data.stream[0], positions, req.vertexCount); Color *colordata = (Color *) data.stream[1]; @@ -1008,7 +1008,7 @@ int Graphics::calculateEllipsePoints(float rx, float ry) const return std::max(points, 8); } -void Graphics::polyline(const float *coords, size_t count) +void Graphics::polyline(const Vector2 *vertices, size_t count) { float halfwidth = getLineWidth() * 0.5f; LineJoin linejoin = getLineJoin(); @@ -1019,27 +1019,27 @@ void Graphics::polyline(const float *coords, size_t count) if (linejoin == LINE_JOIN_NONE) { NoneJoinPolyline line; - line.render(coords, count, halfwidth, pixelsize, linestyle == LINE_SMOOTH); + line.render(vertices, count, halfwidth, pixelsize, linestyle == LINE_SMOOTH); line.draw(this); } else if (linejoin == LINE_JOIN_BEVEL) { BevelJoinPolyline line; - line.render(coords, count, halfwidth, pixelsize, linestyle == LINE_SMOOTH); + line.render(vertices, count, halfwidth, pixelsize, linestyle == LINE_SMOOTH); line.draw(this); } else if (linejoin == LINE_JOIN_MITER) { MiterJoinPolyline line; - line.render(coords, count, halfwidth, pixelsize, linestyle == LINE_SMOOTH); + line.render(vertices, count, halfwidth, pixelsize, linestyle == LINE_SMOOTH); line.draw(this); } } void Graphics::rectangle(DrawMode mode, float x, float y, float w, float h) { - float coords[] = {x,y, x,y+h, x+w,y+h, x+w,y, x,y}; - polygon(mode, coords, 5 * 2); + Vector2 coords[] = {Vector2(x,y), Vector2(x,y+h), Vector2(x+w,y+h), Vector2(x+w,y), Vector2(x,y)}; + polygon(mode, coords, 5); } void Graphics::rectangle(DrawMode mode, float x, float y, float w, float h, float rx, float ry, int points) @@ -1062,44 +1062,43 @@ void Graphics::rectangle(DrawMode mode, float x, float y, float w, float h, floa const float half_pi = static_cast(LOVE_M_PI / 2); float angle_shift = half_pi / ((float) points + 1.0f); - int num_coords = (points + 2) * 8; - float *coords = getScratchBuffer(num_coords + 2); + int num_coords = (points + 2) * 4; + Vector2 *coords = getScratchBuffer(num_coords + 1); float phi = .0f; for (int i = 0; i <= points + 2; ++i, phi += angle_shift) { - coords[2 * i + 0] = x + rx * (1 - cosf(phi)); - coords[2 * i + 1] = y + ry * (1 - sinf(phi)); + coords[i].x = x + rx * (1 - cosf(phi)); + coords[i].y = y + ry * (1 - sinf(phi)); } phi = half_pi; for (int i = points + 2; i <= 2 * (points + 2); ++i, phi += angle_shift) { - coords[2 * i + 0] = x + w - rx * (1 + cosf(phi)); - coords[2 * i + 1] = y + ry * (1 - sinf(phi)); + coords[i].x = x + w - rx * (1 + cosf(phi)); + coords[i].y = y + ry * (1 - sinf(phi)); } phi = 2 * half_pi; for (int i = 2 * (points + 2); i <= 3 * (points + 2); ++i, phi += angle_shift) { - coords[2 * i + 0] = x + w - rx * (1 + cosf(phi)); - coords[2 * i + 1] = y + h - ry * (1 + sinf(phi)); + coords[i].x = x + w - rx * (1 + cosf(phi)); + coords[i].y = y + h - ry * (1 + sinf(phi)); } - phi = 3 * half_pi; + phi = 3 * half_pi; for (int i = 3 * (points + 2); i <= 4 * (points + 2); ++i, phi += angle_shift) { - coords[2 * i + 0] = x + rx * (1 - cosf(phi)); - coords[2 * i + 1] = y + h - ry * (1 + sinf(phi)); + coords[i].x = x + rx * (1 - cosf(phi)); + coords[i].y = y + h - ry * (1 + sinf(phi)); } - coords[num_coords + 0] = coords[0]; - coords[num_coords + 1] = coords[1]; + coords[num_coords] = coords[0]; - polygon(mode, coords, num_coords + 2); + polygon(mode, coords, num_coords + 1); } void Graphics::rectangle(DrawMode mode, float x, float y, float w, float h, float rx, float ry) @@ -1124,15 +1123,14 @@ void Graphics::ellipse(DrawMode mode, float x, float y, float a, float b, int po float angle_shift = (two_pi / points); float phi = .0f; - float *coords = getScratchBuffer(2 * (points + 1)); + Vector2 *coords = getScratchBuffer(points + 1); for (int i = 0; i < points; ++i, phi += angle_shift) { - coords[2*i+0] = x + a * cosf(phi); - coords[2*i+1] = y + b * sinf(phi); + coords[i].x = x + a * cosf(phi); + coords[i].y = y + b * sinf(phi); } - coords[2*points+0] = coords[0]; - coords[2*points+1] = coords[1]; + coords[points] = coords[0]; polygon(mode, coords, (points + 1) * 2); } @@ -1173,45 +1171,43 @@ void Graphics::arc(DrawMode drawmode, ArcMode arcmode, float x, float y, float r float phi = angle1; - float *coords = nullptr; + Vector2 *coords = nullptr; int num_coords = 0; - const auto createPoints = [&](float *coordinates) + const auto createPoints = [&](Vector2 *coordinates) { for (int i = 0; i <= points; ++i, phi += angle_shift) { - coordinates[2 * i + 0] = x + radius * cosf(phi); - coordinates[2 * i + 1] = y + radius * sinf(phi); + coordinates[i].x = x + radius * cosf(phi); + coordinates[i].y = y + radius * sinf(phi); } }; if (arcmode == ARC_PIE) { - num_coords = (points + 3) * 2; - coords = getScratchBuffer(num_coords); + num_coords = points + 3; + coords = getScratchBuffer(num_coords); - coords[0] = coords[num_coords - 2] = x; - coords[1] = coords[num_coords - 1] = y; + coords[0] = coords[num_coords - 1] = Vector2(x, y); - createPoints(coords + 2); + createPoints(coords + 1); } else if (arcmode == ARC_OPEN) { - num_coords = (points + 1) * 2; - coords = getScratchBuffer(num_coords); + num_coords = points + 1; + coords = getScratchBuffer(num_coords); createPoints(coords); } else // ARC_CLOSED { - num_coords = (points + 2) * 2; - coords = getScratchBuffer(num_coords); + num_coords = points + 2; + coords = getScratchBuffer(num_coords); createPoints(coords); // Connect the ends of the arc. - coords[num_coords - 2] = coords[0]; - coords[num_coords - 1] = coords[1]; + coords[num_coords - 1] = coords[0]; } polygon(drawmode, coords, num_coords); @@ -1229,13 +1225,10 @@ void Graphics::arc(DrawMode drawmode, ArcMode arcmode, float x, float y, float r arc(drawmode, arcmode, x, y, radius, angle1, angle2, (int) (points + 0.5f)); } -/// @param mode the draw mode -/// @param coords the coordinate array -/// @param count the number of coordinates/size of the array -void Graphics::polygon(DrawMode mode, const float *coords, size_t count) +void Graphics::polygon(DrawMode mode, const Vector2 *coords, size_t count) { // coords is an array of a closed loop of vertices, i.e. - // coords[count-2] = coords[0], coords[count-1] = coords[1] + // coords[count-1] == coords[0] if (mode == DRAW_LINE) { polyline(coords, count); @@ -1249,14 +1242,14 @@ void Graphics::polygon(DrawMode mode, const float *coords, size_t count) req.formats[0] = vertex::getSinglePositionFormat(is2D); req.formats[1] = vertex::CommonFormat::RGBAub; req.indexMode = vertex::TriangleIndexMode::FAN; - req.vertexCount = (int)count/2 - 1; + req.vertexCount = (int)count - 1; StreamVertexData data = requestStreamDraw(req); if (is2D) - t.transformXY((Vector2 *) data.stream[0], (const Vector2 *) coords, req.vertexCount); + t.transformXY((Vector2 *) data.stream[0], coords, req.vertexCount); else - t.transformXY0((Vector3 *) data.stream[0], (const Vector2 *) coords, req.vertexCount); + t.transformXY0((Vector3 *) data.stream[0], coords, req.vertexCount); Color c = toColor(getColor()); Color *colordata = (Color *) data.stream[1]; diff --git a/src/modules/graphics/Graphics.h b/src/modules/graphics/Graphics.h index a515a1d21..7fda77ae4 100644 --- a/src/modules/graphics/Graphics.h +++ b/src/modules/graphics/Graphics.h @@ -620,18 +620,16 @@ public: void printf(const std::vector &str, Font *font, float wrap, Font::AlignMode align, const Matrix4 &m); /** - * Draws a point at (x,y). - * @param x Point along x-axis. - * @param y Point along y-axis. + * Draws a series of points at the specified positions. **/ - void points(const float *coords, const Colorf *colors, size_t numpoints); + void points(const Vector2 *positions, const Colorf *colors, size_t numpoints); /** * Draws a series of lines connecting the given vertices. - * @param coords Vertex components (x1, y1, ..., xn, yn). If x1,y1 == xn,yn the line will be drawn closed. - * @param count Number of items in the array, i.e. count = 2 * n + * @param coords Vertex positions (v1, ..., vn). If v1 == vn the line will be drawn closed. + * @param count Number of vertices. **/ - void polyline(const float *coords, size_t count); + void polyline(const Vector2 *vertices, size_t count); /** * Draws a rectangle. @@ -696,10 +694,10 @@ public: /** * Draws a polygon with an arbitrary number of vertices. * @param mode The type of drawing (line/filled). - * @param coords Vertex components (x1, y1, x2, y2, etc.) - * @param count Coord array size + * @param coords Vertex positions. + * @param count Vertex array size. **/ - void polygon(DrawMode mode, const float *coords, size_t count); + void polygon(DrawMode mode, const Vector2 *vertices, size_t count); /** * Gets the graphics capabilities (feature support, limit values, and diff --git a/src/modules/graphics/Polyline.cpp b/src/modules/graphics/Polyline.cpp index ebf651ef5..060a01da4 100644 --- a/src/modules/graphics/Polyline.cpp +++ b/src/modules/graphics/Polyline.cpp @@ -33,7 +33,7 @@ namespace love namespace graphics { -void Polyline::render(const float *coords, size_t count, size_t size_hint, float halfwidth, float pixel_size, bool draw_overdraw) +void Polyline::render(const Vector2 *coords, size_t count, size_t size_hint, float halfwidth, float pixel_size, bool draw_overdraw) { static std::vector anchors; anchors.clear(); @@ -48,26 +48,26 @@ void Polyline::render(const float *coords, size_t count, size_t size_hint, float halfwidth -= pixel_size * 0.3f; // compute sleeve - bool is_looping = (coords[0] == coords[count - 2]) && (coords[1] == coords[count - 1]); + bool is_looping = (coords[0] == coords[count - 1]); Vector2 s; if (!is_looping) // virtual starting point at second point mirrored on first point - s = Vector2(coords[2] - coords[0], coords[3] - coords[1]); + s = coords[1] - coords[0]; else // virtual starting point at last vertex - s = Vector2(coords[0] - coords[count - 4], coords[1] - coords[count - 3]); + s = coords[0] - coords[count - 2]; float len_s = s.getLength(); Vector2 ns = s.getNormal(halfwidth / len_s); - Vector2 q, r(coords[0], coords[1]); - for (size_t i = 0; i + 3 < count; i += 2) + Vector2 q, r(coords[0]); + for (size_t i = 0; i + 1 < count; i++) { q = r; - r = Vector2(coords[i + 2], coords[i + 3]); + r = coords[i + 1]; renderEdge(anchors, normals, s, len_s, ns, q, r, halfwidth); } q = r; - r = is_looping ? Vector2(coords[2], coords[3]) : r + s; + r = is_looping ? coords[1] : r + s; renderEdge(anchors, normals, s, len_s, ns, q, r, halfwidth); vertex_count = normals.size(); diff --git a/src/modules/graphics/Polyline.h b/src/modules/graphics/Polyline.h index 9bdc2ab6a..773f06147 100644 --- a/src/modules/graphics/Polyline.h +++ b/src/modules/graphics/Polyline.h @@ -57,13 +57,13 @@ public: /** * @param vertices Vertices defining the core line segments - * @param count Number of coordinates (= size of the array vertices) + * @param count Number of vertices * @param size_hint Expected number of vertices of the rendering sleeve around the core line. * @param halfwidth linewidth / 2. * @param pixel_size Dimension of one pixel on the screen in world coordinates. * @param draw_overdraw Fake antialias the line. */ - void render(const float *vertices, size_t count, size_t size_hint, float halfwidth, float pixel_size, bool draw_overdraw); + void render(const Vector2 *vertices, size_t count, size_t size_hint, float halfwidth, float pixel_size, bool draw_overdraw); /** Draws the line on the screen */ @@ -112,9 +112,9 @@ public: : Polyline(vertex::TriangleIndexMode::QUADS) {} - void render(const float *vertices, size_t count, float halfwidth, float pixel_size, bool draw_overdraw) + void render(const Vector2 *vertices, size_t count, float halfwidth, float pixel_size, bool draw_overdraw) { - Polyline::render(vertices, count, 2 * count - 4, halfwidth, pixel_size, draw_overdraw); + Polyline::render(vertices, count, 4 * count - 4, halfwidth, pixel_size, draw_overdraw); // discard the first and last two vertices. (these are redundant) for (size_t i = 0; i < vertex_count - 4; ++i) @@ -149,9 +149,9 @@ class MiterJoinPolyline : public Polyline { public: - void render(const float *vertices, size_t count, float halfwidth, float pixel_size, bool draw_overdraw) + void render(const Vector2 *vertices, size_t count, float halfwidth, float pixel_size, bool draw_overdraw) { - Polyline::render(vertices, count, count, halfwidth, pixel_size, draw_overdraw); + Polyline::render(vertices, count, 2 * count, halfwidth, pixel_size, draw_overdraw); } protected: @@ -171,9 +171,9 @@ class BevelJoinPolyline : public Polyline { public: - void render(const float *vertices, size_t count, float halfwidth, float pixel_size, bool draw_overdraw) + void render(const Vector2 *vertices, size_t count, float halfwidth, float pixel_size, bool draw_overdraw) { - Polyline::render(vertices, count, 2 * count - 4, halfwidth, pixel_size, draw_overdraw); + Polyline::render(vertices, count, 4 * count - 4, halfwidth, pixel_size, draw_overdraw); } protected: diff --git a/src/modules/graphics/wrap_Graphics.cpp b/src/modules/graphics/wrap_Graphics.cpp index e6e870813..7e7cc9fba 100644 --- a/src/modules/graphics/wrap_Graphics.cpp +++ b/src/modules/graphics/wrap_Graphics.cpp @@ -2279,23 +2279,23 @@ int w_points(lua_State *L) if (args % 2 != 0 && !is_table_of_tables) return luaL_error(L, "Number of vertex components must be a multiple of two"); - int numpoints = args / 2; + int numpositions = args / 2; if (is_table_of_tables) - numpoints = args; + numpositions = args; - float *coords = nullptr; + Vector2 *positions = nullptr; Colorf *colors = nullptr; if (is_table_of_tables) { - size_t datasize = (sizeof(float) * 2 + sizeof(Colorf)) * numpoints; + size_t datasize = (sizeof(Vector2) + sizeof(Colorf)) * numpositions; uint8 *data = instance()->getScratchBuffer(datasize); - coords = (float *) data; - colors = (Colorf *) (data + sizeof(float) * numpoints * 2); + positions = (Vector2 *) data; + colors = (Colorf *) (data + sizeof(Vector2) * numpositions); } else - coords = instance()->getScratchBuffer(numpoints * 2); + positions = instance()->getScratchBuffer(numpositions); if (is_table) { @@ -2308,13 +2308,13 @@ int w_points(lua_State *L) for (int j = 1; j <= 6; j++) lua_rawgeti(L, -j, j); - coords[i * 2 + 0] = luax_tofloat(L, -6); - coords[i * 2 + 1] = luax_tofloat(L, -5); + positions[i].x = luax_tofloat(L, -6); + positions[i].y = luax_tofloat(L, -5); - colors[i].r = luaL_optnumber(L, -4, 1.0); - colors[i].g = luaL_optnumber(L, -3, 1.0); - colors[i].b = luaL_optnumber(L, -2, 1.0); - colors[i].a = luaL_optnumber(L, -1, 1.0); + colors[i].r = (float) luaL_optnumber(L, -4, 1.0); + colors[i].g = (float) luaL_optnumber(L, -3, 1.0); + colors[i].b = (float) luaL_optnumber(L, -2, 1.0); + colors[i].a = (float) luaL_optnumber(L, -1, 1.0); lua_pop(L, 7); } @@ -2322,21 +2322,26 @@ int w_points(lua_State *L) else { // points({x1, y1, x2, y2, ...}) - for (int i = 0; i < args; i++) + for (int i = 0; i < numpositions; i++) { - lua_rawgeti(L, 1, i + 1); - coords[i] = luax_tofloat(L, -1); - lua_pop(L, 1); + lua_rawgeti(L, 1, i * 2 + 1); + lua_rawgeti(L, 1, i * 2 + 2); + positions[i].x = luax_tofloat(L, -2); + positions[i].y = luax_tofloat(L, -1); + lua_pop(L, 2); } } } else { - for (int i = 0; i < args; i++) - coords[i] = luax_tofloat(L, i + 1); + for (int i = 0; i < numpositions; i++) + { + positions[i].x = luax_tofloat(L, i * 2 + 1); + positions[i].y = luax_tofloat(L, i * 2 + 2); + } } - luax_catchexcept(L, [&](){ instance()->points(coords, colors, numpoints); }); + luax_catchexcept(L, [&](){ instance()->points(positions, colors, numpositions); }); return 0; } @@ -2355,24 +2360,31 @@ int w_line(lua_State *L) else if (args < 4) return luaL_error(L, "Need at least two vertices to draw a line"); - float *coords = instance()->getScratchBuffer(args); + int numvertices = args / 2; + + Vector2 *coords = instance()->getScratchBuffer(numvertices); if (is_table) { - for (int i = 0; i < args; ++i) + for (int i = 0; i < numvertices; ++i) { - lua_rawgeti(L, 1, i + 1); - coords[i] = luax_tofloat(L, -1); - lua_pop(L, 1); + lua_rawgeti(L, 1, (i * 2) + 1); + lua_rawgeti(L, 1, (i * 2) + 2); + coords[i].x = luax_tofloat(L, -2); + coords[i].y = luax_tofloat(L, -1); + lua_pop(L, 2); } } else { - for (int i = 0; i < args; ++i) - coords[i] = luax_tofloat(L, i + 1); + for (int i = 0; i < numvertices; ++i) + { + coords[i].x = luax_tofloat(L, (i * 2) + 1); + coords[i].y = luax_tofloat(L, (i * 2) + 2); + } } luax_catchexcept(L, - [&](){ instance()->polyline(coords, args); } + [&](){ instance()->polyline(coords, numvertices); } ); return 0; @@ -2513,28 +2525,34 @@ int w_polygon(lua_State *L) else if (args < 6) return luaL_error(L, "Need at least three vertices to draw a polygon"); + int numvertices = args / 2; + // fetch coords - float *coords = instance()->getScratchBuffer(args + 2); + Vector2 *coords = instance()->getScratchBuffer(numvertices + 1); if (is_table) { - for (int i = 0; i < args; ++i) + for (int i = 0; i < numvertices; ++i) { - lua_rawgeti(L, 2, i + 1); - coords[i] = luax_tofloat(L, -1); - lua_pop(L, 1); + lua_rawgeti(L, 2, (i * 2) + 1); + lua_rawgeti(L, 2, (i * 2) + 2); + coords[i].x = luax_tofloat(L, -2); + coords[i].y = luax_tofloat(L, -1); + lua_pop(L, 2); } } else { - for (int i = 0; i < args; ++i) - coords[i] = luax_tofloat(L, i + 2); + for (int i = 0; i < numvertices; ++i) + { + coords[i].x = luax_tofloat(L, (i * 2) + 2); + coords[i].y = luax_tofloat(L, (i * 2) + 3); + } } // make a closed loop - coords[args] = coords[0]; - coords[args+1] = coords[1]; + coords[numvertices] = coords[0]; - luax_catchexcept(L, [&](){ instance()->polygon(mode, coords, args+2); }); + luax_catchexcept(L, [&](){ instance()->polygon(mode, coords, numvertices+1); }); return 0; }