1 /** 2 * Copyright (c) 2006-2016 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 #ifndef LOVE_GRAPHICS_OPENGL_POLYLINE_H 22 #define LOVE_GRAPHICS_OPENGL_POLYLINE_H 23 24 // LOVE 25 #include "common/config.h" 26 #include "common/Vector.h" 27 28 // OpenGL 29 #include "OpenGL.h" 30 31 // C++ 32 #include <vector> 33 #include <string.h> 34 35 namespace love 36 { 37 namespace graphics 38 { 39 namespace opengl 40 { 41 42 /** 43 * Abstract base class for a chain of segments. 44 * @author Matthias Richter 45 **/ 46 class Polyline 47 { 48 public: 49 Polyline(GLenum mode = GL_TRIANGLE_STRIP, bool quadindices = false) vertices(nullptr)50 : vertices(nullptr) 51 , overdraw(nullptr) 52 , vertex_count(0) 53 , overdraw_vertex_count(0) 54 , draw_mode(mode) 55 , use_quad_indices(quadindices) 56 , overdraw_vertex_start(0) 57 {} 58 virtual ~Polyline(); 59 60 /** 61 * @param vertices Vertices defining the core line segments 62 * @param count Number of coordinates (= size of the array vertices) 63 * @param size_hint Expected number of vertices of the rendering sleeve around the core line. 64 * @param halfwidth linewidth / 2. 65 * @param pixel_size Dimension of one pixel on the screen in world coordinates. 66 * @param draw_overdraw Fake antialias the line. 67 */ 68 void render(const float *vertices, size_t count, size_t size_hint, float halfwidth, float pixel_size, bool draw_overdraw); 69 70 /** Draws the line on the screen 71 */ 72 void draw(); 73 74 protected: 75 virtual void calc_overdraw_vertex_count(bool is_looping); 76 virtual void render_overdraw(const std::vector<Vector> &normals, float pixel_size, bool is_looping); 77 virtual void fill_color_array(Color *colors); 78 79 /** Calculate line boundary points. 80 * 81 * @param[out] anchors Anchor points defining the core line. 82 * @param[out] normals Normals defining the edge of the sleeve. 83 * @param[in,out] s Direction of segment pq (updated to the segment qr). 84 * @param[in,out] len_s Length of segment pq (updated to the segment qr). 85 * @param[in,out] ns Normal on the segment pq (updated to the segment qr). 86 * @param[in] q Current point on the line. 87 * @param[in] r Next point on the line. 88 * @param[in] hw Half line width (see Polyline.render()). 89 */ 90 virtual void renderEdge(std::vector<Vector> &anchors, std::vector<Vector> &normals, 91 Vector &s, float &len_s, Vector &ns, 92 const Vector &q, const Vector &r, float hw) = 0; 93 94 Vector *vertices; 95 Vector *overdraw; 96 size_t vertex_count; 97 size_t overdraw_vertex_count; 98 GLenum draw_mode; 99 bool use_quad_indices; 100 size_t overdraw_vertex_start; 101 102 }; // Polyline 103 104 105 /** 106 * A Polyline whose segments are not connected. 107 * @author Matthias Richter 108 */ 109 class NoneJoinPolyline : public Polyline 110 { 111 public: NoneJoinPolyline()112 NoneJoinPolyline() 113 : Polyline(GL_TRIANGLES, true) 114 {} 115 render(const float * vertices,size_t count,float halfwidth,float pixel_size,bool draw_overdraw)116 void render(const float *vertices, size_t count, float halfwidth, float pixel_size, bool draw_overdraw) 117 { 118 Polyline::render(vertices, count, 2 * count - 4, halfwidth, pixel_size, draw_overdraw); 119 120 // discard the first and last two vertices. (these are redundant) 121 for (size_t i = 0; i < vertex_count - 4; ++i) 122 this->vertices[i] = this->vertices[i+2]; 123 124 // The last quad is now garbage, so zero it out to make sure it doesn't 125 // get rasterized. These vertices are in between the core line vertices 126 // and the overdraw vertices in the combined vertex array, so they still 127 // get "rendered" since we draw everything with one draw call. 128 memset(&this->vertices[vertex_count - 4], 0, sizeof(love::Vector) * 4); 129 130 vertex_count -= 4; 131 } 132 133 protected: 134 virtual void calc_overdraw_vertex_count(bool is_looping); 135 virtual void render_overdraw(const std::vector<Vector> &normals, float pixel_size, bool is_looping); 136 virtual void fill_color_array(Color *colors); 137 virtual void renderEdge(std::vector<Vector> &anchors, std::vector<Vector> &normals, 138 Vector &s, float &len_s, Vector &ns, 139 const Vector &q, const Vector &r, float hw); 140 }; 141 142 143 /** 144 * A Polyline whose segments are connected by a sharp edge. 145 * @author Matthias Richter 146 */ 147 class MiterJoinPolyline : public Polyline 148 { 149 public: render(const float * vertices,size_t count,float halfwidth,float pixel_size,bool draw_overdraw)150 void render(const float *vertices, size_t count, float halfwidth, float pixel_size, bool draw_overdraw) 151 { 152 Polyline::render(vertices, count, count, halfwidth, pixel_size, draw_overdraw); 153 } 154 155 protected: 156 virtual void renderEdge(std::vector<Vector> &anchors, std::vector<Vector> &normals, 157 Vector &s, float &len_s, Vector &ns, 158 const Vector &q, const Vector &r, float hw); 159 }; 160 161 162 /** 163 * A Polyline whose segments are connected by a flat edge. 164 * @author Matthias Richter 165 */ 166 class BevelJoinPolyline : public Polyline 167 { 168 public: render(const float * vertices,size_t count,float halfwidth,float pixel_size,bool draw_overdraw)169 void render(const float *vertices, size_t count, float halfwidth, float pixel_size, bool draw_overdraw) 170 { 171 Polyline::render(vertices, count, 2 * count - 4, halfwidth, pixel_size, draw_overdraw); 172 } 173 174 protected: 175 virtual void renderEdge(std::vector<Vector> &anchors, std::vector<Vector> &normals, 176 Vector &s, float &len_s, Vector &ns, 177 const Vector &q, const Vector &r, float hw); 178 }; 179 180 } // opengl 181 } // graphics 182 } // love 183 184 #endif // LOVE_GRAPHICS_OPENGL_POLYLINE_H 185