void operator() (Drawable & drawable) { Model * mo = drawable.GetModel(); assert(mo); // early out if model already bound Segment & sg = mo->GetVertexBufferSegment(); if (sg.age == ctx.age_static) { drawable.SetVertexBufferSegment(sg); return; } const VertexArray & va = mo->GetVertexArray(); const VertexFormat::Enum vf = va.GetVertexFormat(); const unsigned int vsize = VertexFormat::Get(vf).stride; const unsigned int vcount = va.GetNumVertices(); const unsigned int icount = va.GetNumIndices(); assert(vcount > 0); // get object (first object is reserved for dynamic vertex data) std::vector<Object> & obs = ctx.objects[vf]; if (obs.size() < 2 || (obs.back().vcount + vcount) * vsize > max_buffer_size) { obs.push_back(Object()); assert(obs.size() <= 256); } const unsigned int obindex = obs.size() - 1; Object & ob = obs[obindex]; // gen object buffers if (ob.vbuffer == 0) { glGenBuffers(1, &ob.ibuffer); glGenBuffers(1, &ob.vbuffer); if (ctx.use_vao) { glGenVertexArrays(1, &ob.varray); if (ob.varray == 0) ctx.use_vao = ctx.good_vao = false; } ob.vformat = vf; } // set segment sg.ioffset = ob.icount * sizeof(unsigned int); sg.icount = icount; sg.voffset = ob.vcount; sg.vcount = vcount; sg.vbuffer = ob.varray ? ob.varray : ob.vbuffer; sg.vformat = vf; sg.object = obindex; sg.age = ctx.age_static; drawable.SetVertexBufferSegment(sg); // store va for vertex data upload and update buffer counts varrays[vf].push_back(&va); ob.icount += icount; ob.vcount += vcount; }
void operator() (Drawable & drawable) { if (!drawable.GetDrawEnable()) return; assert(drawable.GetVertArray()); const VertexArray & va = *drawable.GetVertArray(); const VertexFormat::Enum vf = va.GetVertexFormat(); const unsigned int vsize = VertexFormat::Get(vf).stride / sizeof(float); const unsigned int vcount = va.GetNumVertices(); const unsigned int icount = va.GetNumIndices(); // FIXME: text drawables can contain empty vertex arrays, // they should be culled before getting here if (vcount == 0) { // reset segment as we might miss text drawable vcount change // happens with Tracks/Cars scroll onfocus tooltip update // need to investigate this if (drawable.GetVertexBufferSegment().age) drawable.SetVertexBufferSegment(Segment()); return; } // get dynamic vertex data object (first object in the vector) const unsigned int obindex = 0; assert(!ctx.objects[vf].empty()); Object & ob = ctx.objects[vf][obindex]; // gen object buffers if (ob.vbuffer == 0) { glGenBuffers(1, &ob.ibuffer); glGenBuffers(1, &ob.vbuffer); if (ctx.use_vao) { glGenVertexArrays(1, &ob.varray); if (ob.varray == 0) ctx.use_vao = ctx.good_vao = false; } ob.vformat = vf; } // set segment Segment sg; sg.ioffset = ob.icount * sizeof(unsigned int); sg.icount = icount; sg.voffset = ob.vcount; sg.vcount = vcount; sg.vbuffer = ob.varray ? ob.varray : ob.vbuffer; sg.vformat = vf; sg.object = obindex; sg.age = ctx.age_dynamic; drawable.SetVertexBufferSegment(sg); // upload data into staging buffers std::vector<unsigned int> & index_buffer = ctx.staging_index_buffer[vf]; std::vector<float> & vertex_buffer = ctx.staging_vertex_buffer[vf]; const unsigned int ibn = (ob.icount + icount); const unsigned int vbn = (ob.vcount + vcount) * vsize; if (index_buffer.size() < ibn) { const unsigned int ibmin = min_dynamic_index_buffer_size / sizeof(unsigned int); index_buffer.resize(std::max(ibn, ibmin)); } if (vertex_buffer.size() < vbn) { const unsigned int vbmin = min_dynamic_vertex_buffer_size / sizeof(float); vertex_buffer.resize(std::max(vbn, vbmin)); } ob.icount = WriteIndices(va, ob.icount, ob.vcount, index_buffer); ob.vcount = WriteVertices(va, ob.vcount, vsize, vertex_buffer); }