1 /** 2 * Copyright (c) 2006-2019 LOVE Development Team 3 * 4 * This software is provided 'as-is', without any express or implied 5 * warranty. In no event will the authors be held liable for any damages 6 * arising from the use of this software. 7 * 8 * Permission is granted to anyone to use this software for any purpose, 9 * including commercial applications, and to alter it and redistribute it 10 * freely, subject to the following restrictions: 11 * 12 * 1. The origin of this software must not be misrepresented; you must not 13 * claim that you wrote the original software. If you use this software 14 * in a product, an acknowledgment in the product documentation would be 15 * appreciated but is not required. 16 * 2. Altered source versions must be plainly marked as such, and must not be 17 * misrepresented as being the original software. 18 * 3. This notice may not be removed or altered from any source distribution. 19 **/ 20 21 #pragma once 22 23 // LOVE 24 #include "common/config.h" 25 #include "common/Vector.h" 26 #include "graphics/vertex.h" 27 28 // C++ 29 #include <vector> 30 #include <string.h> 31 32 namespace love 33 { 34 namespace graphics 35 { 36 37 class Graphics; 38 39 /** 40 * Abstract base class for a chain of segments. 41 * @author Matthias Richter 42 **/ 43 class Polyline 44 { 45 public: 46 47 Polyline(vertex::TriangleIndexMode mode = vertex::TriangleIndexMode::STRIP) vertices(nullptr)48 : vertices(nullptr) 49 , overdraw(nullptr) 50 , vertex_count(0) 51 , overdraw_vertex_count(0) 52 , triangle_mode(mode) 53 , overdraw_vertex_start(0) 54 {} 55 56 virtual ~Polyline(); 57 58 /** 59 * @param vertices Vertices defining the core line segments 60 * @param count Number of vertices 61 * @param size_hint Expected number of vertices of the rendering sleeve around the core line. 62 * @param halfwidth linewidth / 2. 63 * @param pixel_size Dimension of one pixel on the screen in world coordinates. 64 * @param draw_overdraw Fake antialias the line. 65 */ 66 void render(const Vector2 *vertices, size_t count, size_t size_hint, float halfwidth, float pixel_size, bool draw_overdraw); 67 68 /** Draws the line on the screen 69 */ 70 void draw(love::graphics::Graphics *gfx); 71 72 protected: 73 74 virtual void calc_overdraw_vertex_count(bool is_looping); 75 virtual void render_overdraw(const std::vector<Vector2> &normals, float pixel_size, bool is_looping); 76 virtual void fill_color_array(Color32 constant_color, Color32 *colors, int count); 77 78 /** Calculate line boundary points. 79 * 80 * @param[out] anchors Anchor points defining the core line. 81 * @param[out] normals Normals defining the edge of the sleeve. 82 * @param[in,out] s Direction of segment pq (updated to the segment qr). 83 * @param[in,out] len_s Length of segment pq (updated to the segment qr). 84 * @param[in,out] ns Normal on the segment pq (updated to the segment qr). 85 * @param[in] q Current point on the line. 86 * @param[in] r Next point on the line. 87 * @param[in] hw Half line width (see Polyline.render()). 88 */ 89 virtual void renderEdge(std::vector<Vector2> &anchors, std::vector<Vector2> &normals, 90 Vector2 &s, float &len_s, Vector2 &ns, 91 const Vector2 &q, const Vector2 &r, float hw) = 0; 92 93 Vector2 *vertices; 94 Vector2 *overdraw; 95 size_t vertex_count; 96 size_t overdraw_vertex_count; 97 vertex::TriangleIndexMode triangle_mode; 98 size_t overdraw_vertex_start; 99 100 }; // Polyline 101 102 103 /** 104 * A Polyline whose segments are not connected. 105 * @author Matthias Richter 106 */ 107 class NoneJoinPolyline : public Polyline 108 { 109 public: 110 NoneJoinPolyline()111 NoneJoinPolyline() 112 : Polyline(vertex::TriangleIndexMode::QUADS) 113 {} 114 render(const Vector2 * vertices,size_t count,float halfwidth,float pixel_size,bool draw_overdraw)115 void render(const Vector2 *vertices, size_t count, float halfwidth, float pixel_size, bool draw_overdraw) 116 { 117 Polyline::render(vertices, count, 4 * count - 4, halfwidth, pixel_size, draw_overdraw); 118 119 // discard the first and last two vertices. (these are redundant) 120 for (size_t i = 0; i < vertex_count - 4; ++i) 121 this->vertices[i] = this->vertices[i+2]; 122 123 // The last quad is now garbage, so zero it out to make sure it doesn't 124 // get rasterized. These vertices are in between the core line vertices 125 // and the overdraw vertices in the combined vertex array, so they still 126 // get "rendered" since we draw everything with one draw call. 127 memset(&this->vertices[vertex_count - 4], 0, sizeof(love::Vector2) * 4); 128 129 vertex_count -= 4; 130 } 131 132 protected: 133 134 void calc_overdraw_vertex_count(bool is_looping) override; 135 void render_overdraw(const std::vector<Vector2> &normals, float pixel_size, bool is_looping) override; 136 void fill_color_array(Color32 constant_color, Color32 *colors, int count) override; 137 void renderEdge(std::vector<Vector2> &anchors, std::vector<Vector2> &normals, 138 Vector2 &s, float &len_s, Vector2 &ns, const Vector2 &q, 139 const Vector2 &r, float hw) override; 140 141 }; // NoneJoinPolyline 142 143 144 /** 145 * A Polyline whose segments are connected by a sharp edge. 146 * @author Matthias Richter 147 */ 148 class MiterJoinPolyline : public Polyline 149 { 150 public: 151 render(const Vector2 * vertices,size_t count,float halfwidth,float pixel_size,bool draw_overdraw)152 void render(const Vector2 *vertices, size_t count, float halfwidth, float pixel_size, bool draw_overdraw) 153 { 154 Polyline::render(vertices, count, 2 * count, halfwidth, pixel_size, draw_overdraw); 155 } 156 157 protected: 158 159 void renderEdge(std::vector<Vector2> &anchors, std::vector<Vector2> &normals, 160 Vector2 &s, float &len_s, Vector2 &ns, const Vector2 &q, 161 const Vector2 &r, float hw) override; 162 163 }; // MiterJoinPolyline 164 165 166 /** 167 * A Polyline whose segments are connected by a flat edge. 168 * @author Matthias Richter 169 */ 170 class BevelJoinPolyline : public Polyline 171 { 172 public: 173 render(const Vector2 * vertices,size_t count,float halfwidth,float pixel_size,bool draw_overdraw)174 void render(const Vector2 *vertices, size_t count, float halfwidth, float pixel_size, bool draw_overdraw) 175 { 176 Polyline::render(vertices, count, 4 * count - 4, halfwidth, pixel_size, draw_overdraw); 177 } 178 179 protected: 180 181 void renderEdge(std::vector<Vector2> &anchors, std::vector<Vector2> &normals, 182 Vector2 &s, float &len_s, Vector2 &ns, const Vector2 &q, 183 const Vector2 &r, float hw) override; 184 185 }; // BevelJoinPolyline 186 187 } // graphics 188 } // love 189