void Prop2D::render(Camera *cam, DrawBatchList *bl ) { if( debug_id ) { assertmsg(deck || grid_used_num > 0 || children_num > 0 || prim_drawer , "no deck/grid/prim_drawer is set. deck:%p grid:%d child:%d prim:%p", deck, grid_used_num, children_num, prim_drawer ); } float camx=0.0f; float camy=0.0f; if(cam){ camx = cam->loc.x; camy = cam->loc.y; } if( children_num > 0 && render_children_first ){ for(int i=0;i<children_num;i++){ Prop2D *p = (Prop2D*) children[i]; if( p->visible ) { if( !p->parent_group ) { p->parent_group = parent_group; } p->render( cam, bl ); } } } if( grid_used_num > 0 ){ glEnable(GL_TEXTURE_2D); glColor4f(color.r,color.g,color.b,color.a); for(int i=0;i<grid_used_num;i++){ Grid *grid = grids[i]; if(!grid)break; if(!grid->visible)continue; if(!grid->index_table)continue; Deck *draw_deck = deck; if( grid->deck ) draw_deck = grid->deck; if( grid->fragment_shader ){ #if !(TARGET_IPHONE_SIMULATOR ||TARGET_OS_IPHONE || defined(__linux__) ) glUseProgram(grid->fragment_shader->program ); #endif grid->fragment_shader->updateUniforms(); } if(!grid->mesh) { // print("new grid mesh! wh:%d,%d", grid->width, grid->height ); grid->mesh = new Mesh(); VertexFormat *vf = DrawBatch::getVertexFormat( VFTYPE_COORD_COLOR_UV ); IndexBuffer *ib = new IndexBuffer(); VertexBuffer *vb = new VertexBuffer(); vb->setFormat(vf); /* 3+--+--+--+--+ | | | | | 2+--+--+--+--+ | | | | | 1+--+--+--+--+ | | | | | 0+--+--+--+--+ 0 1 2 3 4 */ int quad_num = grid->width * grid->height; int triangle_num = quad_num * 2; int vert_num = quad_num * 4; // Can't share vertices because each vert has different UVs vb->reserve( vert_num); ib->reserve( triangle_num*3 ); grid->mesh->setVertexBuffer(vb); grid->mesh->setIndexBuffer(ib); grid->mesh->setPrimType( GL_TRIANGLES ); grid->uv_changed = true; grid->color_changed = true; } if( grid->uv_changed || grid->color_changed ) { if(grid->debug) { print("debug:%d Grid changed: uv:%d col:%d", grid->debug, grid->uv_changed, grid->color_changed ); } grid->uv_changed = false; grid->color_changed = false; VertexBuffer *vb = grid->mesh->vb; IndexBuffer *ib = grid->mesh->ib; vb->unbless(); ib->unbless(); int quad_cnt=0; for(int y=0;y<grid->height;y++) { for(int x=0;x<grid->width;x++) { int ind = x+y*grid->width; if(grid->debug) { if(grid->texofs_table) { prt("%.2f,%.2f ", grid->texofs_table[ind].x, grid->texofs_table[ind].y ); } else if( grid->index_table ) { prt("%3d ", grid->index_table[ind] ); } } if( grid->index_table[ind] == Grid::GRID_NOT_USED ) continue; Vec2 left_bottom, right_top; float u0,v0,u1,v1; draw_deck->getUVFromIndex( grid->index_table[ind], &u0,&v0,&u1,&v1,0,0,grid->uv_margin); if(grid->texofs_table) { float u_per_cell = draw_deck->getUperCell(); float v_per_cell = draw_deck->getVperCell(); u0 += grid->texofs_table[ind].x * u_per_cell; v0 += grid->texofs_table[ind].y * v_per_cell; u1 += grid->texofs_table[ind].x * u_per_cell; v1 += grid->texofs_table[ind].y * v_per_cell; } // // Q (u0,v0) - R (u1,v0) top-bottom upside down. // | | // | | // P (u0,v1) - S (u1,v1) // if(grid->xflip_table && grid->xflip_table[ind]) { swapf( &u0, &u1 ); } if(grid->yflip_table && grid->yflip_table[ind]) { swapf( &v0, &v1 ); } Vec2 uv_p(u0,v1), uv_q(u0,v0), uv_r(u1,v0), uv_s(u1,v1); // left bottom const float d = 1; int vi = quad_cnt * 4; vb->setCoord(vi,Vec3(d*x-enfat_epsilon,d*y-enfat_epsilon,0)); if(grid->rot_table && grid->rot_table[ind]) vb->setUV(vi,uv_s); else vb->setUV(vi,uv_p); if(grid->color_table) vb->setColor(vi, grid->color_table[ind]); else vb->setColor(vi, Color(1,1,1,1)); // right bottom vb->setCoord(vi+1,Vec3(d*(x+1)+enfat_epsilon,d*y-enfat_epsilon,0)); if(grid->rot_table && grid->rot_table[ind]) vb->setUV(vi+1,uv_r); else vb->setUV(vi+1,uv_s); if(grid->color_table) vb->setColor(vi+1,grid->color_table[ind]); else vb->setColor(vi+1, Color(1,1,1,1)); // left top vb->setCoord(vi+2,Vec3(d*x-enfat_epsilon,d*(y+1)+enfat_epsilon,0)); if(grid->rot_table && grid->rot_table[ind]) vb->setUV(vi+2,uv_p); else vb->setUV(vi+2,uv_q); if(grid->color_table) vb->setColor(vi+2,grid->color_table[ind]); else vb->setColor(vi+2, Color(1,1,1,1)); // right top vb->setCoord(vi+3,Vec3(d*(x+1)+enfat_epsilon,d*(y+1)+enfat_epsilon,0)); if(grid->rot_table && grid->rot_table[ind]) vb->setUV(vi+3,uv_q); else vb->setUV(vi+3,uv_r); if(grid->color_table) vb->setColor(vi+3,grid->color_table[ind]); else vb->setColor(vi+3, Color(1,1,1,1)); // TODO: no need to update index every time it changes. int indi = quad_cnt * 6; // 2 triangles = 6 verts per quad ib->setIndex(indi++, quad_cnt*4+0 ); ib->setIndex(indi++, quad_cnt*4+2 ); ib->setIndex(indi++, quad_cnt*4+1 ); ib->setIndex(indi++, quad_cnt*4+1 ); ib->setIndex(indi++, quad_cnt*4+2 ); ib->setIndex(indi++, quad_cnt*4+3 ); quad_cnt++; // next quad! } if(grid->debug) print(""); } ib->setRenderLen(quad_cnt*6); } // draw if(!draw_deck) { print("no tex? (grid)"); continue; } if( grid->mesh == NULL || grid->mesh->hasIndexesToRender() == false ) { continue; } FragmentShader *fs = fragment_shader; if( grid->fragment_shader ) fs = grid->fragment_shader; // print("appendMesh, tex:%d vn:%d rn:%d", draw_deck->tex->tex, grid->mesh->vb->array_len, grid->mesh->ib->render_len ); Vec2 finloc(loc.x+grid->rel_loc.x, loc.y+grid->rel_loc.y); Vec2 finscl(scl.x*grid->rel_scl.x, scl.y*grid->rel_scl.y); if(!fs)fs=default_fs; bl->appendMesh( getViewport(), fs, getBlendType(), draw_deck->tex->tex, finloc - Vec2(camx,camy), finscl, rot, grid->mesh, copy_mesh_at_draw ); } } if(deck && index >= 0 ){ float u0,v0,u1,v1; deck->getUVFromIndex( index, &u0,&v0,&u1,&v1,0,0,uv_margin); if(xflip) { swapf(&u0,&u1); } if(yflip) { swapf(&v0,&v1); } // Q (u0,v0) - R (u1,v0) top-bottom upside down. // | | // | | // P (u0,v1) - S (u1,v1) Vec2 uv_p(u0,v1), uv_q(u0,v0), uv_r(u1,v0), uv_s(u1,v1); if(uvrot) { Vec2 tmp = uv_p; uv_p = uv_s; uv_s = uv_r; uv_r = uv_q; uv_q = tmp; } if(!fragment_shader)fragment_shader=default_fs; bl->appendSprite1( getViewport(), fragment_shader, getBlendType(), deck->tex->tex, color, loc - Vec2(camx,camy) + draw_offset, scl, rot, uv_p, uv_q, uv_r, uv_s ); } if( children_num > 0 && (render_children_first == false) ){ for(int i=0;i<children_num;i++){ Prop2D *p = (Prop2D*) children[i]; if(p->visible) { if( !p->parent_group ) { p->parent_group = parent_group; } p->render( cam, bl ); } } } // primitives should go over image sprites if( prim_drawer ){ prim_drawer->drawAll( bl, getViewport(), loc - Vec2(camx,camy),scl,rot); } }