Browse Source

lines can render more than 65k vertices (resolves issue #1356).

Alex Szpakowski 5 years ago
parent
commit
ed537c4f6a
2 changed files with 60 additions and 36 deletions
  1. 47 23
      src/modules/graphics/Polyline.cpp
  2. 13 13
      src/modules/graphics/Polyline.h

+ 47 - 23
src/modules/graphics/Polyline.cpp

@@ -367,39 +367,63 @@ Polyline::~Polyline()
 
 void Polyline::draw(love::graphics::Graphics *gfx)
 {
+	const Matrix4 &t = gfx->getTransform();
+	bool is2D = t.isAffine2DTransform();
+	Color32 curcolor = toColor32(gfx->getColor());
+
+	int overdraw_start = (int) overdraw_vertex_start;
+	int overdraw_count = (int) overdraw_vertex_count;
+
 	int total_vertex_count = (int) vertex_count;
 	if (overdraw)
-		total_vertex_count = (int) (overdraw_vertex_start + overdraw_vertex_count);
+		total_vertex_count = overdraw_start + overdraw_count;
 
-	const Matrix4 &t = gfx->getTransform();
-	bool is2D = t.isAffine2DTransform();
+	// love's automatic batching can only deal with < 65k vertices per draw.
+	// uint16_max - 3 is evenly divisible by 6 (needed for quads mode).
+	int maxvertices = LOVE_UINT16_MAX - 3;
 
-	Graphics::StreamDrawCommand cmd;
-	cmd.formats[0] = vertex::getSinglePositionFormat(is2D);
-	cmd.formats[1] = vertex::CommonFormat::RGBAub;
-	cmd.indexMode = triangle_mode;
-	cmd.vertexCount = total_vertex_count;
+	int advance = maxvertices;
+	if (triangle_mode == vertex::TriangleIndexMode::STRIP)
+		advance -= 2;
 
-	Graphics::StreamVertexData data = gfx->requestStreamDraw(cmd);
+	for (int vertex_start = 0; vertex_start < total_vertex_count; vertex_start += advance)
+	{
+		const Vector2 *verts = vertices + vertex_start;
 
-	if (is2D)
-		t.transformXY((Vector2 *) data.stream[0], vertices, total_vertex_count);
-	else
-		t.transformXY0((Vector3 *) data.stream[0], vertices, total_vertex_count);
+		Graphics::StreamDrawCommand cmd;
+		cmd.formats[0] = vertex::getSinglePositionFormat(is2D);
+		cmd.formats[1] = vertex::CommonFormat::RGBAub;
+		cmd.indexMode = triangle_mode;
+		cmd.vertexCount = std::min(maxvertices, total_vertex_count - vertex_start);
 
-	Color32 curcolor = toColor32(gfx->getColor());
-	Color32 *colordata = (Color32 *) data.stream[1];
+		Graphics::StreamVertexData data = gfx->requestStreamDraw(cmd);
 
-	for (int i = 0; i < (int) vertex_count; i++)
-		colordata[i] = curcolor;
+		if (is2D)
+			t.transformXY((Vector2 *) data.stream[0], verts, cmd.vertexCount);
+		else
+			t.transformXY0((Vector3 *) data.stream[0], verts, cmd.vertexCount);
 
-	if (overdraw)
-		fill_color_array(curcolor, colordata + overdraw_vertex_start);
+		Color32 *colordata = (Color32 *) data.stream[1];
+
+		// Constant vertex color up to the overdraw vertices.
+		for (int i = 0; i < std::min(cmd.vertexCount, (int) vertex_count - vertex_start); i++)
+			colordata[i] = curcolor;
+
+		int colorcount = 0;
+		if (overdraw)
+			colorcount = std::min(cmd.vertexCount, overdraw_count - (vertex_start - overdraw_start));
+
+		if (colorcount > 0)
+		{
+			Color32 *colors = colordata + std::max(0, (overdraw_start - vertex_start));
+			fill_color_array(curcolor, colors, colorcount);
+		}
+	}
 }
 
-void Polyline::fill_color_array(Color32 constant_color, Color32 *colors)
+void Polyline::fill_color_array(Color32 constant_color, Color32 *colors, int count)
 {
-	for (size_t i = 0; i < overdraw_vertex_count; ++i)
+	for (int i = 0; i < count; ++i)
 	{
 		Color32 c = constant_color;
 		c.a *= (i+1) % 2; // avoids branching. equiv to if (i%2 == 1) c.a = 0;
@@ -407,9 +431,9 @@ void Polyline::fill_color_array(Color32 constant_color, Color32 *colors)
 	}
 }
 
-void NoneJoinPolyline::fill_color_array(Color32 constant_color, Color32 *colors)
+void NoneJoinPolyline::fill_color_array(Color32 constant_color, Color32 *colors, int count)
 {
-	for (size_t i = 0; i < overdraw_vertex_count; ++i)
+	for (int i = 0; i < count; ++i)
 	{
 		Color32 c = constant_color;
 		c.a *= (i & 3) < 2; // if (i % 4 == 2 || i % 4 == 3) c.a = 0

+ 13 - 13
src/modules/graphics/Polyline.h

@@ -73,7 +73,7 @@ protected:
 
 	virtual void calc_overdraw_vertex_count(bool is_looping);
 	virtual void render_overdraw(const std::vector<Vector2> &normals, float pixel_size, bool is_looping);
-	virtual void fill_color_array(Color32 constant_color, Color32 *colors);
+	virtual void fill_color_array(Color32 constant_color, Color32 *colors, int count);
 
 	/** Calculate line boundary points.
 	 *
@@ -131,12 +131,12 @@ public:
 
 protected:
 
-	virtual void calc_overdraw_vertex_count(bool is_looping);
-	virtual void render_overdraw(const std::vector<Vector2> &normals, float pixel_size, bool is_looping);
-	virtual void fill_color_array(Color32 constant_color, Color32 *colors);
-	virtual void renderEdge(std::vector<Vector2> &anchors, std::vector<Vector2> &normals,
-	                        Vector2 &s, float &len_s, Vector2 &ns,
-	                        const Vector2 &q, const Vector2 &r, float hw);
+	void calc_overdraw_vertex_count(bool is_looping) override;
+	void render_overdraw(const std::vector<Vector2> &normals, float pixel_size, bool is_looping) override;
+	void fill_color_array(Color32 constant_color, Color32 *colors, int count) override;
+	void renderEdge(std::vector<Vector2> &anchors, std::vector<Vector2> &normals,
+	                Vector2 &s, float &len_s, Vector2 &ns, const Vector2 &q,
+	                const Vector2 &r, float hw) override;
 
 }; // NoneJoinPolyline
 
@@ -156,9 +156,9 @@ public:
 
 protected:
 
-	virtual void renderEdge(std::vector<Vector2> &anchors, std::vector<Vector2> &normals,
-	                        Vector2 &s, float &len_s, Vector2 &ns,
-	                        const Vector2 &q, const Vector2 &r, float hw);
+	void renderEdge(std::vector<Vector2> &anchors, std::vector<Vector2> &normals,
+	                Vector2 &s, float &len_s, Vector2 &ns, const Vector2 &q,
+	                const Vector2 &r, float hw) override;
 
 }; // MiterJoinPolyline
 
@@ -178,9 +178,9 @@ public:
 
 protected:
 
-	virtual void renderEdge(std::vector<Vector2> &anchors, std::vector<Vector2> &normals,
-	                        Vector2 &s, float &len_s, Vector2 &ns,
-	                        const Vector2 &q, const Vector2 &r, float hw);
+	void renderEdge(std::vector<Vector2> &anchors, std::vector<Vector2> &normals,
+	                Vector2 &s, float &len_s, Vector2 &ns, const Vector2 &q,
+	                const Vector2 &r, float hw) override;
 
 }; // BevelJoinPolyline