shader_group_t* shader_group_new(const shader_t* program, const vertex_buffer_t* buff, const char* name, int z, struct tex_group_t* tg, struct blend_group_t* bg) { struct_malloc(shader_group_t, self); self->program = program; self->name = sen_strdup(name); self->buff = vertex_buffer_new(vertex_buffer_format(buff)); self->num = 0; self->z = z; self->tg = tg; self->bg = bg; return self; }
vertex_buffer_t* get_group_buffer(vertex_buffer_t* buff, const texture_t* tex, const font_t* font, const shader_t* program, blend_func blend) { tex_group_t* tg; blend_group_t* bg; unsigned int bkey; khiter_t i,j; khash_t(hmsp)* tgs; const char* atlas_name = NO_ATLAS; char buffer [128]; vec4* v; int z; shader_group_t* sg; khash_t(hmsp)* sgs; if (tex) atlas_name = sen_texture_atlas(tex); else if (font) atlas_name = sen_font_atlas(font); bkey = (unsigned int)blend; i = kh_get(hmip, g_bgs, bkey); if (i != kh_end(g_bgs)) bg = kh_val(g_bgs, i); else { bg = blend_group_new(bkey); kh_insert(hmip, g_bgs, bkey, bg); } bg->num++; tgs = bg->tgs; j = kh_get(hmsp, tgs, atlas_name); if (j != kh_end(tgs)) tg = kh_val(tgs, j); else { tg = tex_group_new(tex,font); kh_insert(hmsp, tgs, atlas_name, tg); } tg->num++; v = (vec4*) buff->vertices->items; z = (int) (v->z * 10000); sprintf (buffer, "%05d%s",z,program->name); sgs = tg->sgs; i = kh_get(hmsp, sgs, buffer); if (i != kh_end(sgs)) sg = kh_val(sgs, i); else { sg = shader_group_new(program, buff,buffer,z,tg,bg); kh_insert(hmsp, sgs, sg->name, sg); } if (sg->buff == NULL) { sg->buff = vertex_buffer_new(vertex_buffer_format(buff)); } sg->num++; return sg->buff; }
/* * A1-------------------J---I * | * A--------------------B K * | | * A2---------------L | | * | | | * | | | * | | | * C2 C C1 */ void vertex_buffer_add_polyline( vertex_buffer_t * self, vec2 *points, size_t n_points, vec4 color, double thickness, int join, int cap ) { typedef struct { float x,y,z,r,g,b,a,s,t,u; } vertex_t; assert( self ); assert( n_points > 2 ); assert( strcmp( vertex_buffer_format( self ), "v3f:c4f:t3f" ) == 0 ); float d,w; if (thickness < 1.0) { w = 2.0; color.a *= thickness; d = (w+2)/w; } else { d = (thickness+2.0)/thickness; w = thickness+2.0; } float r = color.r; float g = color.g; float b = color.b; float a = color.a; float t = thickness; size_t n_vertices = 0; size_t n_indices = 0; if( (join == bevel_join) ) { n_vertices = 2 + (n_points-2) * 6; n_indices = 2*3 + (n_points-2) * 3 * 3; } else if( join == miter_join ) { n_vertices = 2 + (n_points-2) * 6; n_indices = 2*3 + (n_points-2) * 4 * 3; } else { n_vertices = 2 + (n_points-2) * 10; n_indices = 2*3 + (n_points-2) * 6 * 3; } vertex_t * vertices = (vertex_t *) calloc( n_vertices, sizeof(vertex_t) ); GLuint * indices = (GLuint *) calloc( n_indices, sizeof(GLuint) ); vec2 A,B,C; vec2 A1,A2,C1,C2; vec2 T_ba,O_ab, T_bc, O_cb; vec2 I,J,K,L,T; size_t i; size_t v_index = 0; size_t v_count = 0; size_t i_index = 0; size_t i_count = 0; for( i=0; i< (n_points-2); ++i ) { v_count = 0; i_count = 0; A = points[i+0]; B = points[i+1]; C = points[i+2]; T_ba = (vec2) {{ B.x-A.x, B.y-A.y }}; T_bc = (vec2) {{ B.x-C.x, B.y-C.y }}; O_ab = vec2_ortho( A, B ); O_cb = vec2_ortho( C, B ); C1 = (vec2) {{ C.x - w/2*O_cb.x, C.y - w/2*O_cb.y }}; C2 = (vec2) {{ C.x + w/2*O_cb.x, C.y + w/2*O_cb.y }}; if( i == 0) { A1 = (vec2) {{ A.x + w/2*O_ab.x, A.y + w/2*O_ab.y }}; A2 = (vec2) {{ A.x - w/2*O_ab.x, A.y - w/2*O_ab.y }}; } intersection( A1, (vec2) {{ A1.x + T_ba.x, A1.y + T_ba.y }}, C1, (vec2) {{ C1.x + T_bc.x, C1.y + T_bc.y }}, &I); int cross = intersection( A2, (vec2) {{ A2.x + T_ba.x, A2.y + T_ba.y }}, C2, (vec2) {{ C2.x + T_bc.x, C2.y + T_bc.y }}, &L); if( cross == 2) { J = (vec2) {{ B.x + w/2*O_ab.x, B.y + w/2*O_ab.y }}; K = (vec2) {{ B.x - w/2*O_cb.x, B.y - w/2*O_cb.y }}; } else { T = I; I = L; L = T; T = A1; A1 = A2; A2 = T; T = C1; C1 = C2; C2 = T; J = (vec2) {{ B.x - w/2*O_ab.x, B.y - w/2*O_ab.y }}; K = (vec2) {{ B.x + w/2*O_cb.x, B.y + w/2*O_cb.y }}; } vertices[v_index+0] = (vertex_t) { A1.x,A1.y,0, r,g,b,a, 0,+d,t }; // A1 vertices[v_index+1] = (vertex_t) { A2.x,A2.y,0, r,g,b,a, 0,-d,t }; // A2 vertices[v_index+2] = (vertex_t) { I.x, I.y,0, r,g,b,a, 0,+d,t }; // I vertices[v_index+3] = (vertex_t) { J.x, J.y,0, r,g,b,a, 0,+d,t }; // J vertices[v_index+4] = (vertex_t) { K.x, K.y,0, r,g,b,a, 0,+d,t }; // K vertices[v_index+5] = (vertex_t) { L.x, L.y,0, r,g,b,a, 0,-d,t }; // L v_count += 6; indices[i_index+0] = v_index+0; // A1 indices[i_index+1] = v_index+1; // A2 indices[i_index+2] = v_index+5; // L i_index += 3; i_count += 3; indices[i_index+0] = v_index+0; // A1 indices[i_index+1] = v_index+3; // J indices[i_index+2] = v_index+5; // L i_index += 3; i_count += 3; /* Bevel joints */ if( join == bevel_join ) { indices[i_index+0] = v_index+3; // J indices[i_index+1] = v_index+4; // K indices[i_index+2] = v_index+5; // L i_index += 3; i_count += 3; } /* Miter joints */ else if( join == miter_join ) { indices[i_index+0] = v_index+2; // I indices[i_index+1] = v_index+3; // J indices[i_index+2] = v_index+5; // L i_index += 3; i_count += 3; indices[i_index+0] = v_index+2; // I indices[i_index+1] = v_index+4; // K indices[i_index+2] = v_index+5; // L i_index += 3; i_count += 3; } /* Round joints */ else { float jk = vec2_norm( (vec2) {{ J.x-K.x, J.y-K.y }} ); float jb = vec2_norm( (vec2) {{ J.x-B.x, J.y-B.y }} ); float ib = vec2_norm( (vec2) {{ I.x-B.x, I.y-B.y }} ); float jl = vec2_norm( (vec2) {{ J.x-L.x, J.y-L.y }} ); float d1 = ib/jb; float d2 = 0.5*jk/jb; float d3 = sqrt(1-d2*d2); float c = w/jl; d1 *= d; d2 *= d; d3 *= d; vertices[v_index+6] = (vertex_t) { I.x, I.y,0, r,g,b,a, -d1, 0,t }; // I' vertices[v_index+7] = (vertex_t) { J.x, J.y,0, r,g,b,a, -d3,+d2,t }; // J' vertices[v_index+8] = (vertex_t) { K.x, K.y,0, r,g,b,a, -d3,-d2,t }; // K' vertices[v_index+9] = (vertex_t) { L.x, L.y,0, r,g,b,a, 2*c*d-d3,0,t }; // L' v_count += 4; indices[i_index+0] = v_index+6; // I' indices[i_index+1] = v_index+7; // J' indices[i_index+2] = v_index+8; // K' i_index += 3; i_count += 3; indices[i_index+0] = v_index+7; // J' indices[i_index+1] = v_index+8; // K' indices[i_index+2] = v_index+9; // L' i_index += 3; i_count += 3; } if( i == (n_points-3) ) { vertices[v_index+v_count+0] = (vertex_t) { C1.x, C1.y,0, r,g,b,a, 0,+d,t }; // C1 vertices[v_index+v_count+1] = (vertex_t) { C2.x, C2.y,0, r,g,b,a, 0,-d,t }; // C2 v_count += 2; indices[i_index+0] = v_index+v_count-2+0; // C1 indices[i_index+1] = v_index+v_count-2+1; // C2 indices[i_index+2] = v_index+5; // L i_index += 3; i_count += 3; indices[i_index+0] = v_index+v_count-2+0; // C1 indices[i_index+1] = v_index+5; // L indices[i_index+2] = v_index+4; // K i_index += 3; i_count += 3; } v_index += v_count; if( cross == 2 ) { A1 = K; A2 = L; } else { A1 = L; A2 = K; } } vertex_buffer_append( self, vertices, n_vertices, indices, n_indices ); }