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
|
25 | static GLuint sliCircleOutlineVBOs[1] = {0};
|
26 |
|
27 | #ifndef USE_GLES
|
28 | static GLuint sliCircleFillVAO = 0;
|
29 | #endif
|
30 | static GLuint sliCircleFillVBOs[1] = {0};
|
31 |
|
32 | static double sliOutlineRadius = 0;
|
33 | static double sliFillRadius = 0;
|
34 |
|
35 | static int sliNumOutlineVertices = 0;
|
36 | static int sliNumFillVertices = 0;
|
37 |
|
38 | void 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 |
|
67 | void 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 |
|
80 | void 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 |
|
148 | void 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 | |