Browse Source

Use vector2 arrays instead of raw float arrays for graphics primitives. Simplifies the code a bit.

--HG--
branch : minor
Alex Szpakowski 8 years ago
parent
commit
c37e9ed6bf

+ 44 - 51
src/modules/graphics/Graphics.cpp

@@ -951,7 +951,7 @@ void Graphics::printf(const std::vector<Font::ColoredString> &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<float>(LOVE_M_PI / 2);
 	float angle_shift = half_pi / ((float) points + 1.0f);
 
-	int num_coords = (points + 2) * 8;
-	float *coords = getScratchBuffer<float>(num_coords + 2);
+	int num_coords = (points + 2) * 4;
+	Vector2 *coords = getScratchBuffer<Vector2>(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<float>(2 * (points + 1));
+	Vector2 *coords = getScratchBuffer<Vector2>(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<float>(num_coords);
+		num_coords = points + 3;
+		coords = getScratchBuffer<Vector2>(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<float>(num_coords);
+		num_coords = points + 1;
+		coords = getScratchBuffer<Vector2>(num_coords);
 
 		createPoints(coords);
 	}
 	else // ARC_CLOSED
 	{
-		num_coords = (points + 2) * 2;
-		coords = getScratchBuffer<float>(num_coords);
+		num_coords = points + 2;
+		coords = getScratchBuffer<Vector2>(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];

+ 8 - 10
src/modules/graphics/Graphics.h

@@ -620,18 +620,16 @@ public:
 	void printf(const std::vector<Font::ColoredString> &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

+ 8 - 8
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<Vector2> 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();

+ 8 - 8
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:

+ 56 - 38
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<uint8>(datasize);
 
-		coords = (float *) data;
-		colors = (Colorf *) (data + sizeof(float) * numpoints * 2);
+		positions = (Vector2 *) data;
+		colors = (Colorf *) (data + sizeof(Vector2) * numpositions);
 	}
 	else
-		coords = instance()->getScratchBuffer<float>(numpoints * 2);
+		positions = instance()->getScratchBuffer<Vector2>(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<float>(args);
+	int numvertices = args / 2;
+
+	Vector2 *coords = instance()->getScratchBuffer<Vector2>(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<float>(args + 2);
+	Vector2 *coords = instance()->getScratchBuffer<Vector2>(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;
 }