1 package org.newdawn.slick.opengl.renderer;
2
3 import javax.annotation.Nonnull;
4
5
6
7
8
9
10 public class QuadBasedLineStripRenderer implements LineStripRenderer {
11
12 private final SGL GL = Renderer.get();
13
14
15 private static final int MAX_POINTS = 10000;
16
17 private boolean antialias;
18
19 private float width = 1;
20
21 private final float[] points;
22
23 private final float[] colours;
24
25 private int pts;
26
27 private int cpt;
28
29
30 @Nonnull
31 private final DefaultLineStripRenderer def = new DefaultLineStripRenderer();
32
33 private boolean renderHalf;
34
35
36 private boolean lineCaps = false;
37
38
39
40
41 public QuadBasedLineStripRenderer() {
42 points = new float[MAX_POINTS * 2];
43 colours = new float[MAX_POINTS * 4];
44 }
45
46
47
48
49
50
51 public void setLineCaps(boolean caps) {
52 this.lineCaps = caps;
53 }
54
55
56
57
58 public void start() {
59 if (width == 1) {
60 def.start();
61 return;
62 }
63
64 pts = 0;
65 cpt = 0;
66 GL.flush();
67
68 float[] col = GL.getCurrentColor();
69 color(col[0],col[1],col[2],col[3]);
70 }
71
72
73
74
75 public void end() {
76 if (width == 1) {
77 def.end();
78 return;
79 }
80
81 renderLines(points, pts);
82 }
83
84
85
86
87 public void vertex(float x, float y) {
88 if (width == 1) {
89 def.vertex(x,y);
90 return;
91 }
92
93 points[(pts*2)] = x;
94 points[(pts*2)+1] = y;
95 pts++;
96
97 int index = pts-1;
98 color(colours[(index*4)], colours[(index*4)+1], colours[(index*4)+2], colours[(index*4)+3]);
99 }
100
101
102
103
104 public void setWidth(float width) {
105 this.width = width;
106 }
107
108
109
110
111 public void setAntiAlias(boolean antialias) {
112 def.setAntiAlias(antialias);
113 this.antialias = antialias;
114 }
115
116
117
118
119
120
121
122 void renderLines(float[] points, int count) {
123 if (antialias) {
124 GL.glEnable(SGL.GL_POLYGON_SMOOTH);
125 renderLinesImpl(points,count,width+1f);
126 }
127
128 GL.glDisable(SGL.GL_POLYGON_SMOOTH);
129 renderLinesImpl(points,count,width);
130
131 if (antialias) {
132 GL.glEnable(SGL.GL_POLYGON_SMOOTH);
133 }
134 }
135
136
137
138
139
140
141
142
143 void renderLinesImpl(float[] points, int count, float w) {
144 float width = w / 2;
145
146 float lastx1 = 0;
147 float lasty1 = 0;
148 float lastx2 = 0;
149 float lasty2 = 0;
150
151 GL.glBegin(SGL.GL_QUADS);
152 for (int i=0;i<count+1;i++) {
153 int current = i;
154 int next = i+1;
155 int prev = i-1;
156 if (prev < 0) {
157 prev += count;
158 }
159 if (next >= count) {
160 next -= count;
161 }
162 if (current >= count) {
163 current -= count;
164 }
165
166 float x1 = points[(current*2)];
167 float y1 = points[(current*2)+1];
168 float x2 = points[(next*2)];
169 float y2 = points[(next*2)+1];
170
171
172 float dx = x2 - x1;
173 float dy = y2 - y1;
174
175 if ((dx == 0) && (dy == 0)) {
176 continue;
177 }
178
179 float d2 = (dx*dx)+(dy*dy);
180 float d = (float) Math.sqrt(d2);
181 dx *= width;
182 dy *= width;
183 dx /= d;
184 dy /= d;
185
186 float tx = dy;
187 float ty = -dx;
188
189 if (i != 0) {
190 bindColor(prev);
191 GL.glVertex3f(lastx1,lasty1,0);
192 GL.glVertex3f(lastx2,lasty2,0);
193 bindColor(current);
194 GL.glVertex3f(x1+tx,y1+ty,0);
195 GL.glVertex3f(x1-tx,y1-ty,0);
196 }
197
198 lastx1 = x2-tx;
199 lasty1 = y2-ty;
200 lastx2 = x2+tx;
201 lasty2 = y2+ty;
202
203 if (i < count-1) {
204 bindColor(current);
205 GL.glVertex3f(x1+tx,y1+ty,0);
206 GL.glVertex3f(x1-tx,y1-ty,0);
207 bindColor(next);
208 GL.glVertex3f(x2-tx,y2-ty,0);
209 GL.glVertex3f(x2+tx,y2+ty,0);
210 }
211 }
212
213 GL.glEnd();
214
215 float step = width <= 12.5f ? 5 : 180 / (float)Math.ceil(width / 2.5);
216
217
218 if (lineCaps) {
219 float dx = points[2] - points[0];
220 float dy = points[3] - points[1];
221 float fang = (float) Math.toDegrees(Math.atan2(dy,dx)) + 90;
222
223 if ((dx != 0) || (dy != 0)) {
224 GL.glBegin(SGL.GL_TRIANGLE_FAN);
225 bindColor(0);
226 GL.glVertex2f(points[0], points[1]);
227 for (int i=0;i<180+step;i+=step) {
228 float ang = (float) Math.toRadians(fang+i);
229 GL.glVertex2f(points[0]+((float) (Math.cos(ang) * width)),
230 points[1]+((float) (Math.sin(ang) * width)));
231 }
232 GL.glEnd();
233 }
234 }
235
236
237 if (lineCaps) {
238 float dx = points[(count*2)-2] - points[(count*2)-4];
239 float dy = points[(count*2)-1] - points[(count*2)-3];
240 float fang = (float) Math.toDegrees(Math.atan2(dy,dx)) - 90;
241
242 if ((dx != 0) || (dy != 0)) {
243 GL.glBegin(SGL.GL_TRIANGLE_FAN);
244 bindColor(count-1);
245 GL.glVertex2f(points[(count*2)-2], points[(count*2)-1]);
246 for (int i=0;i<180+step;i+=step) {
247 float ang = (float) Math.toRadians(fang+i);
248 GL.glVertex2f(points[(count*2)-2]+((float) (Math.cos(ang) * width)),
249 points[(count*2)-1]+((float) (Math.sin(ang) * width)));
250 }
251 GL.glEnd();
252 }
253 }
254 }
255
256
257
258
259
260
261 private void bindColor(int index) {
262 if (index < cpt) {
263 if (renderHalf) {
264 GL.glColor4f(colours[(index*4)]*0.5f, colours[(index*4)+1]*0.5f,
265 colours[(index*4)+2]*0.5f, colours[(index*4)+3]*0.5f);
266 } else {
267 GL.glColor4f(colours[(index*4)], colours[(index*4)+1],
268 colours[(index*4)+2], colours[(index*4)+3]);
269 }
270 }
271 }
272
273
274
275
276 public void color(float r, float g, float b, float a) {
277 if (width == 1) {
278 def.color(r,g,b,a);
279 return;
280 }
281
282 colours[(pts*4)] = r;
283 colours[(pts*4)+1] = g;
284 colours[(pts*4)+2] = b;
285 colours[(pts*4)+3] = a;
286 cpt++;
287 }
288
289 public boolean applyGLLineFixes() {
290 if (width == 1) {
291 return def.applyGLLineFixes();
292 }
293
294 return def.applyGLLineFixes();
295 }
296 }