// // objects.c // IntroOpenGL // // Created by Ilya Rimchikov on 29/03/14. // Copyright (c) 2014 IntroOpenGL. All rights reserved. // #include "objects.h" #include "buffer.h" #include "platform_gl.h" #include "program.h" #include "shader.h" #include "linmath.h" #include "matrix.h" #include "math_helper.h" #include "platform_log.h" #include #include #include "animations.h" float scale_factor; int width, height; int y_offset_absolute; static TextureProgram texture_program; static TextureProgram texture_program_one; static TextureProgram texture_program_red; static TextureProgram texture_program_blue; static TextureProgram texture_program_light_red; static TextureProgram texture_program_light_blue; static TextureProgram *texture_program_temp; static ColorProgram color_program; static GradientProgram gradient_program; static float y_offset; void set_y_offset_objects(float a) { y_offset = a; } void setup_shaders() { char *vshader = "uniform mat4 u_MvpMatrix;" "attribute vec4 a_Position;" "void main(){" " gl_Position = u_MvpMatrix * a_Position;" "}"; char *fshader = "precision lowp float;" "uniform vec4 u_Color;" "uniform float u_Alpha;" "void main() {" " gl_FragColor = u_Color;" //" gl_FragColor = vec4(0,1,0,1);" " gl_FragColor.w*=u_Alpha;" "}"; color_program = get_color_program(build_program(vshader, (GLint)strlen(vshader), fshader, (GLint)strlen(fshader))); char *vertex_gradient_shader = "uniform mat4 u_MvpMatrix;" "attribute vec4 a_Position;" "attribute vec4 a_Color;" "varying vec4 v_DestinationColor;" "void main(){" " v_DestinationColor = a_Color;" " gl_Position = u_MvpMatrix * a_Position;" "}"; char *fragment_gradient_shader = "precision lowp float;" "uniform float u_Alpha;" "varying vec4 v_DestinationColor;" "void main() {" " gl_FragColor = v_DestinationColor;" " gl_FragColor.w*=u_Alpha;" //" gl_FragColor = vec4(0,1,0,1);" "}"; gradient_program = get_gradient_program(build_program(vertex_gradient_shader, (GLint)strlen(vertex_gradient_shader), fragment_gradient_shader, (GLint)strlen(fragment_gradient_shader))); char* vshader_texture = "uniform mat4 u_MvpMatrix;" "attribute vec4 a_Position;" "attribute vec2 a_TextureCoordinates;" "varying vec2 v_TextureCoordinates;" "void main(){" " v_TextureCoordinates = a_TextureCoordinates;" " gl_Position = u_MvpMatrix * a_Position;" "}"; char* fshader_texture = "precision lowp float;" "uniform sampler2D u_TextureUnit;" "varying vec2 v_TextureCoordinates;" "uniform float u_Alpha;" "void main(){" " gl_FragColor = texture2D(u_TextureUnit, v_TextureCoordinates);" " gl_FragColor.w *= u_Alpha;" "}"; texture_program = get_texture_program(build_program(vshader_texture, (GLint)strlen(vshader_texture), fshader_texture, (GLint)strlen(fshader_texture))); char* vshader_texture_blue = "uniform mat4 u_MvpMatrix;" "attribute vec4 a_Position;" "attribute vec2 a_TextureCoordinates;" "varying vec2 v_TextureCoordinates;" "void main(){" " v_TextureCoordinates = a_TextureCoordinates;" " gl_Position = u_MvpMatrix * a_Position;" "}"; char* fshader_texture_blue = "precision lowp float;" "uniform sampler2D u_TextureUnit;" "varying vec2 v_TextureCoordinates;" "uniform float u_Alpha;" "void main(){" " gl_FragColor = texture2D(u_TextureUnit, v_TextureCoordinates);" //" float p = u_Alpha*gl_FragColor.w*0.4;" //" gl_FragColor = vec4(0,0.353,0.761,p);" " float p = u_Alpha*gl_FragColor.w;" " gl_FragColor = vec4(0,0.6,0.898,p);" "}"; texture_program_blue = get_texture_program(build_program(vshader_texture_blue, (GLint)strlen(vshader_texture_blue), fshader_texture_blue, (GLint)strlen(fshader_texture_blue))); char* vshader_texture_red = "uniform mat4 u_MvpMatrix;" "attribute vec4 a_Position;" "attribute vec2 a_TextureCoordinates;" "varying vec2 v_TextureCoordinates;" "void main(){" " v_TextureCoordinates = a_TextureCoordinates;" " gl_Position = u_MvpMatrix * a_Position;" "}"; char* fshader_texture_red = "precision lowp float;" "uniform sampler2D u_TextureUnit;" "varying vec2 v_TextureCoordinates;" "uniform float u_Alpha;" "void main(){" " gl_FragColor = texture2D(u_TextureUnit, v_TextureCoordinates);" //" float p = gl_FragColor.w*0.45*u_Alpha;" //" gl_FragColor = vec4(0.722,0.035,0,p);" " float p = gl_FragColor.w*u_Alpha;" " gl_FragColor = vec4(210./255.,57./255.,41./255.,p);" "}"; texture_program_red = get_texture_program(build_program(vshader_texture_red, (GLint)strlen(vshader_texture_red), fshader_texture_red, (GLint)strlen(fshader_texture_red))); vshader = "uniform mat4 u_MvpMatrix;" "attribute vec4 a_Position;" "attribute vec2 a_TextureCoordinates;" "varying vec2 v_TextureCoordinates;" "void main(){" " v_TextureCoordinates = a_TextureCoordinates;" " gl_Position = u_MvpMatrix * a_Position;" "}"; fshader = "precision lowp float;" "uniform sampler2D u_TextureUnit;" "varying vec2 v_TextureCoordinates;" "uniform float u_Alpha;" "void main(){" " gl_FragColor = texture2D(u_TextureUnit, v_TextureCoordinates);" //" float p = u_Alpha*gl_FragColor.w;" //" gl_FragColor = vec4(237./255., 64./255., 27./255., p);" " float p = u_Alpha*gl_FragColor.w;" " gl_FragColor = vec4(246./255., 73./255., 55./255., p);" "}"; texture_program_light_red = get_texture_program(build_program(vshader, (GLint)strlen(vshader), fshader, (GLint)strlen(fshader))); vshader = "uniform mat4 u_MvpMatrix;" "attribute vec4 a_Position;" "attribute vec2 a_TextureCoordinates;" "varying vec2 v_TextureCoordinates;" "void main(){" " v_TextureCoordinates = a_TextureCoordinates;" " gl_Position = u_MvpMatrix * a_Position;" "}"; fshader = "precision lowp float;" "uniform sampler2D u_TextureUnit;" "varying vec2 v_TextureCoordinates;" "uniform float u_Alpha;" "void main(){" " gl_FragColor = texture2D(u_TextureUnit, v_TextureCoordinates);" " float p = u_Alpha*gl_FragColor.w;" //" gl_FragColor = vec4(100./255.,182./255.,248./255.,p);" " gl_FragColor = vec4(42./255.,180./255.,247./255.,p);" "}"; texture_program_light_blue = get_texture_program(build_program(vshader, (GLint)strlen(vshader), fshader, (GLint)strlen(fshader))); vshader = "uniform mat4 u_MvpMatrix;" "attribute vec4 a_Position;" "attribute vec2 a_TextureCoordinates;" "varying vec2 v_TextureCoordinates;" "void main(){" " v_TextureCoordinates = a_TextureCoordinates;" " gl_Position = u_MvpMatrix * a_Position;" "}"; fshader = "precision lowp float;" "uniform sampler2D u_TextureUnit;" "varying vec2 v_TextureCoordinates;" "uniform float u_Alpha;" "void main(){" " gl_FragColor = texture2D(u_TextureUnit, v_TextureCoordinates);" " gl_FragColor *= u_Alpha;" "}"; texture_program_one = get_texture_program(build_program(vshader, (GLint)strlen(vshader), fshader, (GLint)strlen(fshader))); } CPoint CPointMake(float x, float y) { CPoint p = {x, y}; return p; } CSize CSizeMake(float width, float height) { CSize s = {width, height}; return s; } float D2R(float a) { return a*M_PI/180.0; } float R2D(float a) { return a*180.0/M_PI; } xyz xyzMake(float x, float y, float z) { xyz result; result.x = x; result.y = y; result.z = z; return result; } LayerParams default_layer_params() { LayerParams params; params.anchor.x=params.anchor.y=params.anchor.z=0; params.position.x=params.position.y=params.position.z=0; params.rotation=0; params.scale.x=params.scale.y=params.scale.z=1.; return params; } Params default_params() { Params params; params.anchor.x=params.anchor.y=params.anchor.z=0; params.position.x=params.position.y=params.position.z=0; params.rotation=0; params.scale.x=params.scale.y=params.scale.z=1.; params.alpha=1.; params.var_params.side_length=0; params.var_params.start_angle=0; params.var_params.end_angle=0; params.var_params.angle=0; params.var_params.size=CSizeMake(0, 0); params.var_params.radius=0; params.var_params.width=0; params.const_params.is_star=0; LayerParams p = default_layer_params(); params.layer_params=&p; return params; } void mat4x4_translate_independed(mat4x4 m, float x, float y, float z) { mat4x4 tr; mat4x4_identity(tr); mat4x4_translate_in_place(tr, x, y, z); //mat4x4 model_matrix2_tr; //mat4x4_mul(model_matrix2_tr, tr, m); mat4x4 m_dup; mat4x4_dup(m_dup, m); mat4x4_mul(m, tr, m_dup ); } static inline void mvp_matrix(mat4x4 model_view_projection_matrix, Params params, mat4x4 view_projection_matrix) { mat4x4 model_matrix; mat4x4_identity(model_matrix); mat4x4 id; mat4x4_identity(id); mat4x4_translate(model_matrix, -params.anchor.x, -params.anchor.y, params.anchor.z); mat4x4 scaled; mat4x4_identity(scaled); mat4x4_scale_aniso(scaled, scaled, params.scale.x, -params.scale.y, params.scale.z); mat4x4 tmp; mat4x4_dup(tmp, model_matrix); mat4x4_mul(model_matrix, scaled, tmp); mat4x4 rotate; mat4x4_dup(rotate, id); mat4x4_rotate_Z2(rotate, id, deg_to_radf(-params.rotation)); mat4x4_dup(tmp, model_matrix); mat4x4_mul(model_matrix, rotate, tmp); mat4x4_translate_independed(model_matrix, params.position.x, -params.position.y, params.position.z); mat4x4 model_matrix3; mat4x4_identity(model_matrix3); mat4x4 mm; mat4x4_mul(mm, model_matrix3, view_projection_matrix); mat4x4_mul(model_view_projection_matrix, mm, model_matrix); mat4x4_translate_independed(model_view_projection_matrix, 0, -y_offset/view_projection_matrix[3][3], 0); } void mat4x4_log(mat4x4 M) { /* printf("\n\n"); int i, j; for(i=0; i<4; ++i) { for(j=0; j<4; ++j) { printf("%6.2f ", M[i][j]); } printf("\n"); } printf("\n\n"); */ } void vec4_log(vec4 M) { /* printf("\n\n"); int i; for(i=0; i<4; ++i) { printf("%6.2f ", M[i]); } printf("\n\n"); */ } void draw_shape(const Shape* shape, mat4x4 view_projection_matrix) { if (shape->params.alpha>0 && (fabs(shape->params.scale.x)>0 && fabs(shape->params.scale.y)>0 && fabs(shape->params.scale.z)>0)) { mat4x4 model_view_projection_matrix; mvp_matrix(model_view_projection_matrix, shape->params, view_projection_matrix); glUseProgram(color_program.program); glUniformMatrix4fv(color_program.u_mvp_matrix_location, 1, GL_FALSE, (GLfloat*)model_view_projection_matrix); if (shape->params.rotation==5.) { glUniform4fv(color_program.u_color_location, 1, shape->color); } else if (shape->params.rotation==10.) { vec4 col ={0,1,0,1}; glUniform4fv(color_program.u_color_location, 1, col); //glUniform4fv(color_program.u_color_location, 1, shape->color); } else { glUniform4fv(color_program.u_color_location, 1, shape->color); } glUniform1f(color_program.u_alpha_loaction, shape->params.alpha); glVertexAttribPointer(color_program.a_position_location, 2, GL_FLOAT, GL_FALSE, sizeof(CPoint), &shape->data[0].x); glEnableVertexAttribArray(color_program.a_position_location); glDrawArrays(shape->params.const_params.triangle_mode, 0, shape->num_points); } } void draw_textured_shape(const TexturedShape* shape, mat4x4 view_projection_matrix, texture_program_type program_type) { if (shape->params.alpha>0 && (fabs(shape->params.scale.x)>0 && fabs(shape->params.scale.y)>0 && fabs(shape->params.scale.z)>0)) { mat4x4 model_view_projection_matrix; mvp_matrix(model_view_projection_matrix, shape->params, view_projection_matrix); if (shape->params.const_params.is_star==1) { vec4 pos; vec4 vertex = {0,0,0,1}; mat4x4_mul_vec4(pos, model_view_projection_matrix, vertex); vec4 p_NDC = {pos[0]/pos[3], pos[1]/pos[3], pos[2]/pos[3], pos[3]/pos[3]}; // p_window = (p_NDC + 1)/2 * viewport.{width, height} + viewport{x, y} //vec4 p_window={p_NDC[0]*width, -p_NDC[1]*height, 0, 0}; vec4 p_window={p_NDC[0]*width, -p_NDC[1]*height, 0, 0}; int d = 160; if (fabs(p_window[0])>d || p_window[1] > y_offset_absolute*2 + d || p_window[1] < y_offset_absolute*2 - d) { return; } } if (program_type==RED) { texture_program_temp=&texture_program_red; } else if (program_type==BLUE) { texture_program_temp=&texture_program_blue; } else if (program_type==LIGHT_RED) { texture_program_temp=&texture_program_light_red; } else if (program_type==LIGHT_BLUE) { texture_program_temp=&texture_program_light_blue; } else if (program_type==NORMAL_ONE) { texture_program_temp=&texture_program_one; } else { texture_program_temp=&texture_program; } glUseProgram(texture_program_temp->program); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, shape->texture); glUniformMatrix4fv(texture_program_temp->u_mvp_matrix_location, 1, GL_FALSE, (GLfloat*)model_view_projection_matrix); glUniform1i(texture_program_temp->u_texture_unit_location, 0); glUniform1f(texture_program_temp->u_alpha_loaction, shape->params.alpha); glBindBuffer(GL_ARRAY_BUFFER, shape->buffer); // glVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr) glVertexAttribPointer(texture_program_temp->a_position_location, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GL_FLOAT), BUFFER_OFFSET(0)); glVertexAttribPointer(texture_program_temp->a_texture_coordinates_location, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GL_FLOAT), BUFFER_OFFSET(2 * sizeof(GL_FLOAT))); glEnableVertexAttribArray(texture_program_temp->a_position_location); glEnableVertexAttribArray(texture_program_temp->a_texture_coordinates_location); glDrawArrays(shape->params.const_params.triangle_mode, 0, shape->num_points); glBindBuffer(GL_ARRAY_BUFFER, 0); } } // Rounded rectangle static inline int size_of_rounded_rectangle_in_vertices(int round_count) { return 4*(2+round_count)+2; } static inline void gen_rounded_rectangle(CPoint* out, CSize size, float radius, int round_count) { //printf("gen_rounded_rectangle> %d \n", round_count); int offset=0; out[offset++] = CPointMake(0, 0); float k = M_PI/2/(round_count+1); int i=0; int n=0; for (i=(round_count+2)*n; i<=round_count+1 + (round_count+1)*n; i++) { out[offset++] = CPointMake(size.width/2-radius + cos(i*k)*radius, size.height/2-radius + sin(i*k)*radius); } n++; for (i=(round_count+1)*n; i<=round_count+1 + (round_count+1)*n; i++) { out[offset++] = CPointMake(-size.width/2+radius + cos(i*k)*radius, size.height/2-radius + sin(i*k)*radius); } n++; for (i=(round_count+1)*n; i<=round_count+1 + (round_count+1)*n; i++) { out[offset++] = CPointMake(-size.width/2+radius + cos(i*k)*radius, -size.height/2+radius + sin(i*k)*radius); } n++; for (i=(round_count+1)*n; i<=round_count+1 + (round_count+1)*n; i++) { out[offset++] = CPointMake(size.width/2-radius + cos(i*k)*radius, -size.height/2+radius + sin(i*k)*radius); } n++; out[offset++] = CPointMake(size.width/2, size.height/2-radius); } Shape create_rounded_rectangle(CSize size, float radius, int round_count, const vec4 color) { int real_vertex_count = size_of_rounded_rectangle_in_vertices(round_count); Params params = default_params(); params.const_params.datasize = sizeof(CPoint)*real_vertex_count*2; params.const_params.round_count=round_count; params.const_params.triangle_mode = GL_TRIANGLE_FAN; params.var_params.size=size; params.var_params.radius=radius; CPoint *data = malloc(params.const_params.datasize); gen_rounded_rectangle(data, params.var_params.size, params.var_params.radius, params.const_params.round_count); /* char str[150]; sprintf(str, "rounded_rectangle_data_size(%d) = %d", real_vertex_count, rounded_rectangle_data_size(real_vertex_count)); DEBUG_LOG_WRITE_D("fps>",str); */ return (Shape) {{color[0], color[1], color[2], color[3]}, data, create_vbo(params.const_params.datasize, data, GL_DYNAMIC_DRAW), real_vertex_count, params}; } void change_rounded_rectangle(Shape* shape, CSize size, float radius) { if ((*shape).params.var_params.size.width != size.width || (*shape).params.var_params.size.height != size.height || (*shape).params.var_params.radius != radius ) { //DEBUG_LOG_WRITE_D("fps","change_rounded_rectangle"); (*shape).params.var_params.size.width = size.width; (*shape).params.var_params.size.height = size.height; (*shape).params.var_params.radius = radius; gen_rounded_rectangle((*shape).data, (*shape).params.var_params.size, (*shape).params.var_params.radius, (*shape).params.const_params.round_count); glBindBuffer(GL_ARRAY_BUFFER, shape->buffer); glBufferSubData(GL_ARRAY_BUFFER, 0, shape->params.const_params.datasize, shape->data); // proved glBindBuffer(GL_ARRAY_BUFFER, 0); } } // Segmented square static inline int size_of_segmented_square_in_vertices() { return 7; } static inline CPoint square_point(float angle, float radius) { CPoint p; if (angle<=M_PI/2*.5 || angle>M_PI/2*3.5) { p = CPointMake(radius, radius * sin(angle)/cos(angle)); } else if (angle<=M_PI/2*1.5) { p = CPointMake(radius * cos(angle)/sin(angle), radius); } else if (angle<=M_PI/2*2.5) { p = CPointMake(-radius, -radius * sin(angle)/cos(angle)); } else if (angle<=M_PI/2*3.5) { p = CPointMake(-radius * cos(angle)/sin(angle), -radius); } return p; } static inline CPoint square_texture_point(CPoint p, float side_length) { return CPointMake((-p.x/side_length*.5 +.5), -p.y/side_length*.5 +.5); } static inline void gen_segmented_square(CPoint* out, float side_length, float start_angle, float end_angle) { CPoint p; float radius = side_length; int offset=0; float k=1; float da=D2R(-2.6*2)*k; p = CPointMake(sin(start_angle+end_angle)*6*k, - cos(start_angle+end_angle)*6*k); //p = CPointMake(0, 0); out[offset++] = p; out[offset++] = square_texture_point(p, side_length); //1 p = square_point(start_angle+da, radius); //p.y=p.y; //p.y=side_length; out[offset++] = p; out[offset++] = square_texture_point(p, side_length); int q=0; int i; for (i=start_angle; ibuffer); glBufferSubData(GL_ARRAY_BUFFER, 0, shape->params.const_params.datasize, shape->data); // proved glBindBuffer(GL_ARRAY_BUFFER, 0); } } // ok // Rectangle static inline void gen_rectangle(CPoint* out, CSize size) { int offset=0; out[offset++] = CPointMake(-size.width/2, -size.height/2); out[offset++] = CPointMake(size.width/2, -size.height/2); out[offset++] = CPointMake(-size.width/2, size.height/2); out[offset++] = CPointMake(size.width/2, size.height/2); } Shape create_rectangle(CSize size, const vec4 color) { int real_vertex_count = 4; Params params = default_params(); params.const_params.datasize = sizeof(CPoint)*real_vertex_count; params.const_params.triangle_mode = GL_TRIANGLE_STRIP; CPoint *data = malloc(params.const_params.datasize); gen_rectangle(data, size); return (Shape) {{color[0], color[1], color[2], color[3]}, data, create_vbo(params.const_params.datasize, data, GL_DYNAMIC_DRAW), real_vertex_count, params}; } // ok // Textured rectangle static inline CPoint rectangle_texture_point(CPoint p, CSize size) { return CPointMake(1-(-p.x/size.width+.5), p.y/size.height+.5); } static inline void gen_textured_rectangle(CPoint* out, CSize size) { int offset=0; out[offset++] = CPointMake(-size.width/2, -size.height/2); out[offset++] = rectangle_texture_point(CPointMake(-size.width/2, -size.height/2), size); out[offset++] = CPointMake(size.width/2, -size.height/2); out[offset++] = rectangle_texture_point(CPointMake(size.width/2, -size.height/2), size); out[offset++] = CPointMake(-size.width/2, size.height/2); out[offset++] = rectangle_texture_point(CPointMake(-size.width/2, size.height/2), size); out[offset++] = CPointMake(size.width/2, size.height/2); out[offset++] = rectangle_texture_point(CPointMake(size.width/2, size.height/2), size); } TexturedShape create_textured_rectangle(CSize size, GLuint texture) { int real_vertex_count = 4; Params params = default_params(); params.const_params.datasize = sizeof(CPoint) * real_vertex_count * 2; params.const_params.triangle_mode = GL_TRIANGLE_STRIP; CPoint *data = malloc(params.const_params.datasize); gen_textured_rectangle(data, size); return (TexturedShape) {texture, data, create_vbo(params.const_params.datasize, data, GL_STATIC_DRAW), real_vertex_count, params}; } void change_textured_rectangle(TexturedShape* shape, CSize size) { //DEBUG_LOG_WRITE_D("fps","change_textured_rectangle"); gen_textured_rectangle((*shape).data, size); glBindBuffer(GL_ARRAY_BUFFER, shape->buffer); glBufferSubData(GL_ARRAY_BUFFER, 0, shape->params.const_params.datasize, shape->data); // proved glBindBuffer(GL_ARRAY_BUFFER, 0); } // ok // Ribbon static inline void gen_ribbon(CPoint* out, float length) { int offset=0; out[offset++] = CPointMake(-MAXf(length-5.5, 0), -5.5); out[offset++] = CPointMake(0, -5.5); out[offset++] = CPointMake(-MAXf(length, 0), 5.5); out[offset++] = CPointMake(0, 5.5); } Shape create_ribbon(float length, const vec4 color) { int real_vertex_count = 4; Params params=default_params(); params.const_params.datasize = sizeof(CPoint)*real_vertex_count; params.const_params.triangle_mode = GL_TRIANGLE_STRIP; params.var_params.side_length=length; CPoint *data = malloc(params.const_params.datasize); gen_ribbon(data, length); return (Shape) {{color[0], color[1], color[2], color[3]}, data, create_vbo(params.const_params.datasize, data, GL_DYNAMIC_DRAW), real_vertex_count, params}; } void change_ribbon(Shape* shape, float length) { if ((*shape).params.var_params.side_length != length) { //DEBUG_LOG_WRITE_D("fps","change_segmented_square"); (*shape).params.var_params.side_length = length; gen_ribbon((*shape).data, length); glBindBuffer(GL_ARRAY_BUFFER, shape->buffer); glBufferSubData(GL_ARRAY_BUFFER, 0, shape->params.const_params.datasize, shape->data); // proved glBindBuffer(GL_ARRAY_BUFFER, 0); } } // ok // Segmented circle static inline int size_of_segmented_circle_in_vertices(int num_points) { return 1 + (num_points + 1); } static inline void gen_segmented_circle(CPoint* out, float radius, float start_angle, float angle, int vertex_count) { int offset=0; out[offset++] = CPointMake(0, 0); int i; for (i = 0; i <= vertex_count; i++) { out[offset++] = CPointMake(radius*cos(start_angle+(i/(float)vertex_count)*angle), radius*sin(start_angle+(i/(float)vertex_count)*angle)); //int o=offset-1; } } Shape create_segmented_circle(float radius, int vertex_count, float start_angle, float angle, const vec4 color) { int real_vertex_count = size_of_segmented_circle_in_vertices(vertex_count); Params params=default_params(); params.const_params.datasize = sizeof(CPoint)*real_vertex_count; params.const_params.triangle_mode=GL_TRIANGLE_FAN; params.const_params.round_count=vertex_count; CPoint *data = malloc(params.const_params.datasize); gen_segmented_circle(data, radius, start_angle, angle, vertex_count); return (Shape) {{color[0], color[1], color[2], color[3]}, data, create_vbo(params.const_params.datasize, data, GL_DYNAMIC_DRAW), real_vertex_count, params}; } void change_segmented_circle(Shape* shape, float radius, float start_angle, float angle) { if ((*shape).params.var_params.radius != radius || (*shape).params.var_params.start_angle != start_angle || (*shape).params.var_params.angle != angle ) { //DEBUG_LOG_WRITE_D("fps","change_segmented_square"); (*shape).params.var_params.radius = radius; (*shape).params.var_params.start_angle = start_angle; (*shape).params.var_params.angle = angle; gen_segmented_circle((*shape).data, radius, start_angle, angle, (*shape).params.const_params.round_count); glBindBuffer(GL_ARRAY_BUFFER, shape->buffer); glBufferSubData(GL_ARRAY_BUFFER, 0, shape->params.const_params.datasize, shape->data); // proved glBindBuffer(GL_ARRAY_BUFFER, 0); } } // ok // Circle static inline int size_of_circle_in_vertices(int num_points) { return 1 + (num_points + 1); } static inline void gen_circle(CPoint* out, float radius, int vertex_count) { int offset=0; out[offset++] = CPointMake(0, 0); int i; for (i = 0; i <= vertex_count; i++) { out[offset++] = CPointMake(radius*cos(2*M_PI*(i/(float)vertex_count)), radius*sin(2*M_PI*(i/(float)vertex_count)) ); } } Shape create_circle(float radius, int vertex_count, const vec4 color) { int real_vertex_count = size_of_segmented_circle_in_vertices(vertex_count); Params params=default_params(); params.const_params.datasize = sizeof(CPoint)*real_vertex_count; params.const_params.triangle_mode=GL_TRIANGLE_FAN; params.const_params.round_count=vertex_count; CPoint *data = malloc(params.const_params.datasize); gen_circle(data, radius, vertex_count); return (Shape) {{color[0], color[1], color[2], color[3]}, data, create_vbo(params.const_params.datasize, data, GL_STATIC_DRAW), real_vertex_count, params}; } void change_circle(Shape* shape, float radius) { if ((*shape).params.var_params.radius != radius) { //DEBUG_LOG_WRITE_D("fps","change_segmented_square"); (*shape).params.var_params.radius = radius; gen_circle((*shape).data, radius, (*shape).params.const_params.round_count); glBindBuffer(GL_ARRAY_BUFFER, shape->buffer); glBufferSubData(GL_ARRAY_BUFFER, 0, shape->params.const_params.datasize, shape->data); // proved glBindBuffer(GL_ARRAY_BUFFER, 0); } } // ok // Infinity int size_of_infinity_in_vertices(int segment_count) { return (segment_count+1)*2; } static inline void gen_infinity(CPoint* out, float width, float angle, int segment_count) { CPoint path[13]; path[0]=CPointMake(53,23); path[1]=CPointMake(49,31); path[2]=CPointMake(39,47); path[3]=CPointMake(22,47); path[4]=CPointMake(6,47); path[5]=CPointMake(0,31); path[6]=CPointMake(0,23); path[7]=CPointMake(0,16); path[8]=CPointMake(5,0); path[9]=CPointMake(23,0); path[10]=CPointMake(39,0); path[11]=CPointMake(48,15); path[12]=CPointMake(52,21); int offset=0; int seg; for (seg=0; seg<=segment_count; seg++) { float tt = ((float)seg/(float)segment_count)*angle; int q=4; float tstep=1./q; int n = floor(tt/tstep); if (seg >= segment_count) { //n=n-1;//q-1; } //printf("n>%d\n", n); CPoint a = path[0+3*n];; CPoint p1 = path[1+3*n]; CPoint p2 = path[2+3*n]; CPoint b = path[3+3*n]; float t=(tt-tstep*n)*q; float nt = 1.0f - t; vec2 p = {a.x * nt * nt * nt + 3.0 * p1.x * nt * nt * t + 3.0 * p2.x * nt * t * t + b.x * t * t * t, a.y * nt * nt * nt + 3.0 * p1.y * nt * nt * t + 3.0 * p2.y * nt * t * t + b.y * t * t * t}; vec2 tangent = {-3.0 * a.x * nt * nt + 3.0 * p1.x * (1.0 - 4.0 * t + 3.0 * t * t) + 3.0 * p2.x * (2.0 * t - 3.0 * t * t) + 3.0 * b.x * t * t, -3.0 * a.y * nt * nt + 3.0 * p1.y * (1.0 - 4.0 * t + 3.0 * t * t) + 3.0 * p2.y * (2.0 * t - 3.0 * t * t) + 3.0 * b.y * t * t}; vec2 tan_norm = {-tangent[1], tangent[0]}; vec2 norm; vec2_norm(norm, tan_norm); vec2 v; vec2 norm_scaled; vec2_scale(norm_scaled, norm, +width/2.); vec2_add(v, p, norm_scaled); out[offset] = CPointMake(v[0], v[1]); offset++; vec2_scale(norm_scaled, norm, -width/2.); vec2_add(v, p, norm_scaled); out[offset] = CPointMake(v[0], v[1]); offset++; } //printf("infinity_q>%d", offset); } Shape create_infinity(float width, float angle, int segment_count, const vec4 color) { int real_vertex_count = size_of_infinity_in_vertices(segment_count); Params params=default_params(); params.const_params.datasize = sizeof(CPoint)*real_vertex_count; params.const_params.triangle_mode=GL_TRIANGLE_STRIP; params.const_params.round_count=segment_count; params.var_params.width = width; params.var_params.angle = angle; CPoint *data = malloc(params.const_params.datasize); gen_infinity(data, width, angle, segment_count); return (Shape) {{color[0], color[1], color[2], color[3]}, data, create_vbo(params.const_params.datasize, data, GL_DYNAMIC_DRAW), real_vertex_count, params}; } void change_infinity(Shape* shape, float angle) { if ( (*shape).params.var_params.angle != angle ) { (*shape).params.var_params.angle = angle; gen_infinity(shape->data, (*shape).params.var_params.width, (*shape).params.var_params.angle, (*shape).params.const_params.round_count); glBindBuffer(GL_ARRAY_BUFFER, shape->buffer); glBufferData(GL_ARRAY_BUFFER, shape->params.const_params.datasize, shape->data, GL_DYNAMIC_DRAW); // proved glBindBuffer(GL_ARRAY_BUFFER, 0); } } void draw_infinity(const Shape* shape, mat4x4 view_projection_matrix) { if (shape->params.alpha>0 && (fabs(shape->params.scale.x)>0 && fabs(shape->params.scale.y)>0 && fabs(shape->params.scale.z)>0)) { mat4x4 model_view_projection_matrix; mvp_matrix(model_view_projection_matrix, shape->params, view_projection_matrix); glUseProgram(color_program.program); glUniformMatrix4fv(color_program.u_mvp_matrix_location, 1, GL_FALSE, (GLfloat*)model_view_projection_matrix); glUniform4fv(color_program.u_color_location, 1, shape->color); glUniform1f(color_program.u_alpha_loaction, shape->params.alpha); glVertexAttribPointer(color_program.a_position_location, 2, GL_FLOAT, GL_FALSE, sizeof(CPoint), &shape->data[0].x); glEnableVertexAttribArray(color_program.a_position_location); glDrawArrays(shape->params.const_params.triangle_mode, 0, shape->num_points); } } // ok // Rounded rectangle stroked static inline int size_of_rounded_rectangle_stroked_in_vertices(int round_count) { return 4*(2+round_count)*2+2; } static inline void gen_rounded_rectangle_stroked(CPoint* out, CSize size, float radius, float stroke_width, int round_count) { int offset=0; float k = M_PI/2/(round_count+1); float inner_radius = radius - stroke_width; int i=0; int n=0; for (i=(round_count+2)*n; i<=round_count+1 + (round_count+1)*n; i++) { out[offset++] = CPointMake(size.width/2-radius + cos(i*k)*radius, size.height/2-radius + sin(i*k)*radius); out[offset++] = CPointMake(size.width/2-radius + cos(i*k)*inner_radius, size.height/2-radius + sin(i*k)*inner_radius); } n++; for (i=(round_count+1)*n; i<=round_count+1 + (round_count+1)*n; i++) { out[offset++] = CPointMake(-size.width/2+radius + cos(i*k)*radius, size.height/2-radius + sin(i*k)*radius); out[offset++] = CPointMake(-size.width/2+radius + cos(i*k)*inner_radius, size.height/2-radius + sin(i*k)*inner_radius); } n++; for (i=(round_count+1)*n; i<=round_count+1 + (round_count+1)*n; i++) { out[offset++] = CPointMake(-size.width/2+radius + cos(i*k)*radius, -size.height/2+radius + sin(i*k)*radius); out[offset++] = CPointMake(-size.width/2+radius + cos(i*k)*inner_radius, -size.height/2+radius + sin(i*k)*inner_radius); } n++; for (i=(round_count+1)*n; i<=round_count+1 + (round_count+1)*n; i++) { out[offset++] = CPointMake(size.width/2-radius + cos(i*k)*radius, -size.height/2+radius + sin(i*k)*radius); out[offset++] = CPointMake(size.width/2-radius + cos(i*k)*inner_radius, -size.height/2+radius + sin(i*k)*inner_radius); } n++; i=0; out[offset++] = CPointMake(size.width/2-radius + cos(i*k)*radius, size.height/2-radius + sin(i*k)*radius); out[offset++] = CPointMake(size.width/2-radius + cos(i*k)*inner_radius, size.height/2-radius + sin(i*k)*inner_radius); } Shape create_rounded_rectangle_stroked(CSize size, float radius, float stroke_width, int round_count, const vec4 color) { // round_count == 10 : polygons fall out int real_vertex_count = size_of_rounded_rectangle_stroked_in_vertices(round_count); Params params = default_params(); params.const_params.round_count=round_count; params.const_params.datasize = sizeof(CPoint)*real_vertex_count*2; params.var_params.size=size; params.var_params.radius=radius; params.var_params.width=stroke_width; CPoint *data = malloc(params.const_params.datasize); gen_rounded_rectangle_stroked(data, params.var_params.size, params.var_params.radius, params.var_params.width, params.const_params.round_count); params.const_params.triangle_mode = GL_TRIANGLE_STRIP; return (Shape) {{color[0], color[1], color[2], color[3]}, data, create_vbo(params.const_params.datasize, data, GL_DYNAMIC_DRAW), real_vertex_count, params}; } void change_rounded_rectangle_stroked(Shape* shape, CSize size, float radius, float stroke_width) { if ((*shape).params.var_params.size.width != size.width || (*shape).params.var_params.size.height != size.height || (*shape).params.var_params.radius != radius ) { //DEBUG_LOG_WRITE_D("fps","change_rounded_rectangle"); (*shape).params.var_params.size.width = size.width; (*shape).params.var_params.size.height = size.height; (*shape).params.var_params.radius = radius; gen_rounded_rectangle_stroked((*shape).data, (*shape).params.var_params.size, (*shape).params.var_params.radius, (*shape).params.var_params.width, (*shape).params.const_params.round_count); glBindBuffer(GL_ARRAY_BUFFER, shape->buffer); glBufferSubData(GL_ARRAY_BUFFER, 0, shape->params.const_params.datasize, shape->data); // glBindBuffer(GL_ARRAY_BUFFER, 0); } }