1#include "circle.h"
2#include "shaders.h"
3
4#include "../util/shader.h"
5
6#include "config.h"
7
8#ifdef USE_GLES
9 #include <GLES2/gl2.h>
10 #include <GLES2/gl2ext.h>
11#else
12 #include <GL/glew.h>
13#endif
14
15#include <math.h>
16#include <stdlib.h>
17
18#define PI 3.1415926
19#define MIN_VERTICES 3
20#define MAX_VERTICES 100
21
22#ifndef USE_GLES
23 static GLuint sliCircleOutlineVAO = 0;
24#endif
25static GLuint sliCircleOutlineVBOs[1] = {0};
26
27#ifndef USE_GLES
28 static GLuint sliCircleFillVAO = 0;
29#endif
30static GLuint sliCircleFillVBOs[1] = {0};
31
32static double sliOutlineRadius = 0;
33static double sliFillRadius = 0;
34
35static int sliNumOutlineVertices = 0;
36static int sliNumFillVertices = 0;
37
38void sliCircleInit()
39{
40 // initialize our outline state object
41 #ifndef USE_GLES
42 glGenVertexArrays(1, &sliCircleOutlineVAO);
43 glBindVertexArray(sliCircleOutlineVAO);
44 #endif
45 glGenBuffers(1, sliCircleOutlineVBOs);
46
47 // configure outline vertex data
48 glBindBuffer(GL_ARRAY_BUFFER, sliCircleOutlineVBOs[0]);
49 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * MAX_VERTICES * 2, NULL, GL_DYNAMIC_DRAW);
50 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL);
51 glEnableVertexAttribArray(0);
52
53 // initialize our fill state object
54 #ifndef USE_GLES
55 glGenVertexArrays(1, &sliCircleFillVAO);
56 glBindVertexArray(sliCircleFillVAO);
57 #endif
58 glGenBuffers(1, sliCircleFillVBOs);
59
60 // configure fill vertex data
61 glBindBuffer(GL_ARRAY_BUFFER, sliCircleFillVBOs[0]);
62 glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * (MAX_VERTICES + 2) * 2, NULL, GL_DYNAMIC_DRAW); // + 2 for middle and end of triangle fan
63 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL);
64 glEnableVertexAttribArray(0);
65}
66
67void sliCircleDestroy()
68{
69 glDeleteBuffers(1, sliCircleOutlineVBOs);
70 #ifndef USE_GLES
71 glDeleteVertexArrays(1, &sliCircleOutlineVAO);
72 #endif
73
74 glDeleteBuffers(1, sliCircleFillVBOs);
75 #ifndef USE_GLES
76 glDeleteVertexArrays(1, &sliCircleFillVAO);
77 #endif
78}
79
80void sliCircleOutline(Mat4 *modelview, Vec4 *color, double radius, int numVertices)
81{
82 const double EPS = 0.00001;
83
84 GLfloat vertices[MAX_VERTICES * 2];
85 GLfloat *vertexPtr;
86 double theta;
87 double transform;
88 double c, s;
89 double x, y;
90 int i;
91
92 // make sure the number of vertices is something reasonable
93 if(numVertices < MIN_VERTICES) numVertices = MIN_VERTICES;
94 if(numVertices > MAX_VERTICES) numVertices = MAX_VERTICES;
95
96 // if the number of vertices specified is different from what we've allocated, prepare to re-compute them
97 if(numVertices != sliNumOutlineVertices || fabs(radius - sliOutlineRadius) > EPS)
98 {
99 // assign new vertex count and radius
100 sliNumOutlineVertices = numVertices;
101 sliOutlineRadius = radius;
102 vertexPtr = vertices;
103
104 // compute angle increment, and pre-compute sin and cos of that increment
105 theta = 2 * (PI / (double)sliNumOutlineVertices);
106 c = cos(theta);
107 s = sin(theta);
108
109 // first vertex position of line loop
110 x = radius;
111 y = 0.0f;
112
113 // compute new vertex positions
114 for(i = 0; i < sliNumOutlineVertices; i ++)
115 {
116 *vertexPtr++ = (float)x;
117 *vertexPtr++ = (float)y;
118
119 // apply rotation matrix to current vertex position
120 transform = x;
121 x = c * x - s * y;
122 y = s * transform + c * y;
123 }
124
125 // now pass the vertex data to OpenGL
126 #ifndef USE_GLES
127 glBindVertexArray(sliCircleOutlineVAO);
128 #endif
129 glBindBuffer(GL_ARRAY_BUFFER, sliCircleOutlineVBOs[0]);
130 glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GLfloat) * sliNumOutlineVertices * 2, vertices);
131 }
132
133 // prepare our shader object
134 shaderBind(sliBasicShader);
135 shaderUniformMatrix4fv(sliBasicShader, "u_Modelview", 1, (float*)modelview);
136 shaderUniform4f(sliBasicShader, "u_Color", (float)color -> x, (float)color -> y, (float)color -> z, (float)color -> w);
137
138 // bind appropriate object state and render the object
139 #ifndef USE_GLES
140 glBindVertexArray(sliCircleOutlineVAO);
141 #else
142 glBindBuffer(GL_ARRAY_BUFFER, sliCircleOutlineVBOs[0]);
143 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL);
144 #endif
145 glDrawArrays(GL_LINE_LOOP, 0, sliNumOutlineVertices);
146}
147
148void sliCircleFill(Mat4 *modelview, Vec4 *color, double radius, int numVertices)
149{
150 const double EPS = 0.00001;
151
152 GLfloat vertices[(MAX_VERTICES + 2) * 3]; // + 2 for middle and end of triangle fan
153 GLfloat *vertexPtr;
154 double theta;
155 double transform;
156 double c, s;
157 double x, y;
158 int i;
159
160 // make sure the number of vertices is something reasonable
161 if(numVertices < MIN_VERTICES) numVertices = MIN_VERTICES;
162 if(numVertices > MAX_VERTICES) numVertices = MAX_VERTICES;
163
164 // if the number of vertices specified is different from what we've allocated, prepare to re-compute them
165 if(numVertices != sliNumFillVertices || fabs(radius - sliFillRadius) > EPS)
166 {
167 // assign new vertex count
168 sliNumFillVertices = numVertices;
169 sliFillRadius = radius;
170 vertexPtr = vertices;
171
172 // compute angle increment, and pre-compute sin and cos of that increment
173 theta = 2 * (PI / (double)sliNumFillVertices);
174 c = cos(theta);
175 s = sin(theta);
176
177 // first vertex position of line loop
178 x = radius;
179 y = 0;
180
181 // insert triangle fan center vertex, which contributes to the 2
182 // extra vertices we define in total
183 *vertexPtr++ = 0.0f;
184 *vertexPtr++ = 0.0f;
185
186 // compute new vertex positions
187 for(i = 0; i < sliNumFillVertices + 1; i ++) // + 1 here for end of triangle fan
188 {
189 *vertexPtr++ = (float)x;
190 *vertexPtr++ = (float)y;
191
192 // apply rotation matrix to current vertex position
193 transform = x;
194 x = c * x - s * y;
195 y = s * transform + c * y;
196 }
197
198 // now pass the vertex data to OpenGL
199 #ifndef USE_GLES
200 glBindVertexArray(sliCircleFillVAO);
201 #endif
202 glBindBuffer(GL_ARRAY_BUFFER, sliCircleFillVBOs[0]);
203 glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GLfloat) * (sliNumFillVertices + 2) * 2, vertices); // + 2 for middle and end of triangle fan
204 }
205
206 // prepare our shader object
207 shaderBind(sliBasicShader);
208 shaderUniformMatrix4fv(sliBasicShader, "u_Modelview", 1, (float*)modelview);
209 shaderUniform4f(sliBasicShader, "u_Color", (float)color -> x, (float)color -> y, (float)color -> z, (float)color -> w);
210
211 // bind appropriate object state and render the object
212 #ifndef USE_GLES
213 glBindVertexArray(sliCircleFillVAO);
214 #else
215 glBindBuffer(GL_ARRAY_BUFFER, sliCircleFillVBOs[0]);
216 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL);
217 #endif
218 glDrawArrays(GL_TRIANGLE_FAN, 0, sliNumFillVertices + 2); // + 2 for middle and end of triangle fan
219}
220