예제 #1
0
	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;
	}
예제 #2
0
	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);
	}