vbo_MapRender.hpp 11.5 KB
Newer Older
Pierre Kraemer's avatar
Pierre Kraemer committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/*******************************************************************************
* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps  *
* version 0.1                                                                  *
* Copyright (C) 2009, IGG Team, LSIIT, University of Strasbourg                *
*                                                                              *
* This library is free software; you can redistribute it and/or modify it      *
* under the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, or (at your     *
* option) any later version.                                                   *
*                                                                              *
* This library is distributed in the hope that it will be useful, but WITHOUT  *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or        *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License  *
* for more details.                                                            *
*                                                                              *
* You should have received a copy of the GNU Lesser General Public License     *
* along with this library; if not, write to the Free Software Foundation,      *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.           *
*                                                                              *
* Web site: https://iggservis.u-strasbg.fr/CGoGN/                              *
* Contact information: cgogn@unistra.fr                                        *
*                                                                              *
*******************************************************************************/
24 25
#include "Topology/generic/dartmarker.h"
#include "Topology/generic/cellmarker.h"
Pierre Kraemer's avatar
Pierre Kraemer committed
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41

namespace CGoGN
{

namespace Algo
{

namespace Render
{

namespace VBO
{



template <typename ATTR_HANDLER>
42
void MapRender_VBO::updateData(int upType, const ATTR_HANDLER& attrib, ConvertAttrib* conv)
Pierre Kraemer's avatar
Pierre Kraemer committed
43 44 45 46 47 48 49 50 51 52 53
{
	// choisit le bon buffer en fonction du paramètre upType
	unsigned int indexVBO = -1 ;
	if (upType == POSITIONS)
		indexVBO = POSITIONS_BUFFER ;
	else if (upType == NORMALS)
		indexVBO = NORMALS_BUFFER ;
	else if (upType == COLORS)
		indexVBO = COLORS_BUFFER ;
	else
	{
54
		std::cout << "MapRender_VBO::updateData : should not get here.. Bad type to update.." << std::endl ;
Pierre Kraemer's avatar
Pierre Kraemer committed
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
		return ;
	}

	m_allocatedBuffers[indexVBO] = true ;
	m_usedBuffers[indexVBO] = true ;

	if (conv)
		fillBufferConvert(indexVBO, attrib, conv) ;
	else
		fillBufferDirect(indexVBO, attrib) ;
}



template <typename ATTR_HANDLER>
70
void MapRender_VBO::fillBufferDirect(unsigned int indexVBO, const ATTR_HANDLER& attrib)
Pierre Kraemer's avatar
Pierre Kraemer committed
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
{
	AttribMultiVect<typename ATTR_HANDLER::DATA_TYPE>* mv = attrib.getDataVector() ;

	std::vector<void*> addr;
	unsigned int byteTableSize;
	unsigned int nbb = mv->getStartAddresses(addr, byteTableSize);

	glBindBufferARB(GL_ARRAY_BUFFER, m_VBOBuffers[indexVBO]);
	glBufferDataARB(GL_ARRAY_BUFFER, nbb * byteTableSize, 0, GL_STREAM_DRAW);

	unsigned int offset = 0;
//	unsigned int offsetInc = byteTableSize;

	for (unsigned int i = 0; i < nbb; ++i)
	{
		glBufferSubDataARB(GL_ARRAY_BUFFER, offset, byteTableSize, addr[i]);
		offset += byteTableSize;
	}
}

91

Pierre Kraemer's avatar
Pierre Kraemer committed
92
template <typename ATTR_HANDLER>
93
void MapRender_VBO::fillBufferConvert(unsigned int indexVBO, const ATTR_HANDLER& attrib, ConvertAttrib* conv)
Pierre Kraemer's avatar
Pierre Kraemer committed
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
{
	AttribMultiVect<typename ATTR_HANDLER::DATA_TYPE>* mv = attrib.getDataVector() ;

	std::vector<void*> addr;
	unsigned int byteTableSize;
	unsigned int nbb = mv->getStartAddresses(addr, byteTableSize);

	// alloue la memoire pour le buffer et initialise le conv
	conv->reserve(mv->BlockSize());

	// bind buffer to update
	glBindBufferARB(GL_ARRAY_BUFFER, m_VBOBuffers[indexVBO]);
	glBufferDataARB(GL_ARRAY_BUFFER, nbb * conv->sizeBuffer(), 0, GL_STREAM_DRAW);

	unsigned int offset = 0;
//	unsigned int offsetInc = byteTableSize;

	for (unsigned int i = 0; i < nbb; ++i)
	{
		// convertit les donnees dans le buffer de conv
		conv->convert(addr[i]);
		// update sub-vbo
		glBufferSubDataARB(GL_ARRAY_BUFFER, offset, conv->sizeBuffer(), conv->buffer());
		// block suivant
		offset += conv->sizeBuffer();
	}

	// libere la memoire de la conversion
	conv->release();
}

template<typename PFP>
126
inline void MapRender_VBO::addTri(typename PFP::MAP& map, Dart d, std::vector<GLuint>& tableIndices)
Pierre Kraemer's avatar
Pierre Kraemer committed
127 128
{
	Dart a = d;
129 130
	Dart b = map.phi1(a);
	Dart c = map.phi1(b);
Pierre Kraemer's avatar
Pierre Kraemer committed
131 132 133 134
	
	// loop to cut a polygon in triangle on the fly (works only with convex faces)
	do
	{
135 136 137
		tableIndices.push_back(map.getEmbedding(d, VERTEX_ORBIT));
		tableIndices.push_back(map.getEmbedding(b, VERTEX_ORBIT));
		tableIndices.push_back(map.getEmbedding(c, VERTEX_ORBIT));
Pierre Kraemer's avatar
Pierre Kraemer committed
138
		b = c;
139
		c = map.phi1(b);
Pierre Kraemer's avatar
Pierre Kraemer committed
140 141 142 143
	} while (c != d);
}

template<typename PFP>
Sylvain Thery's avatar
Sylvain Thery committed
144
void MapRender_VBO::initTriangles(typename PFP::MAP& map, const FunctorSelect& good, std::vector<GLuint>& tableIndices, unsigned int thread)
Pierre Kraemer's avatar
Pierre Kraemer committed
145
{
Sylvain Thery's avatar
Sylvain Thery committed
146
	DartMarker m(map,thread);
147
	tableIndices.reserve(4*map.getNbDarts()/3);
Pierre Kraemer's avatar
Pierre Kraemer committed
148

149
	for(Dart dd = map.begin(); dd != map.end(); map.next(dd))
Pierre Kraemer's avatar
Pierre Kraemer committed
150
	{
151
		if(!m.isMarked(dd) && good(dd))
Pierre Kraemer's avatar
Pierre Kraemer committed
152
		{
153
			addTri<PFP>(map, dd, tableIndices);
Pierre Kraemer's avatar
Pierre Kraemer committed
154 155 156 157 158 159
			m.markOrbit(FACE_ORBIT, dd);
		}
	}
}

template<typename PFP>
Sylvain Thery's avatar
Sylvain Thery committed
160
void MapRender_VBO::initTrianglesOptimized(typename PFP::MAP& map, const FunctorSelect& good, std::vector<GLuint>& tableIndices, unsigned int thread)
Pierre Kraemer's avatar
Pierre Kraemer committed
161 162
{
#define LIST_SIZE 20
Sylvain Thery's avatar
Sylvain Thery committed
163
	DartMarker m(map,thread);
Pierre Kraemer's avatar
Pierre Kraemer committed
164 165 166
	// reserve memory for triangles ( nb indices == nb darts )
	// and a little bit more
	// if lots of polygonal faces, realloc is done by vector 
167
	tableIndices.reserve(4*map.getNbDarts()/3);
Pierre Kraemer's avatar
Pierre Kraemer committed
168

169
	for (Dart dd = map.begin(); dd != map.end(); map.next(dd))
Pierre Kraemer's avatar
Pierre Kraemer committed
170 171 172 173 174
	{
		if (!m.isMarked(dd))
		{
			std::list<Dart> bound;

175 176
			if(good(dd))
				addTri<PFP>(map,dd,tableIndices);
Pierre Kraemer's avatar
Pierre Kraemer committed
177 178 179 180 181 182 183 184 185 186 187 188 189 190
			m.markOrbit(FACE_ORBIT, dd);
			bound.push_back(dd);
			int nb = 1;
			do
			{
				Dart e = bound.back();
				Dart ee = e;
				do
				{
					Dart f = ee;
					do
					{
						if (!m.isMarked(f))
						{
191 192
							if(good(f))
								addTri<PFP>(map, f, tableIndices);
Pierre Kraemer's avatar
Pierre Kraemer committed
193
							m.markOrbit(FACE_ORBIT, f);
194
							bound.push_back(map.phi1(f));
Pierre Kraemer's avatar
Pierre Kraemer committed
195 196 197 198 199 200 201
							++nb;
							if (nb > LIST_SIZE)
							{
								bound.pop_front();
								--nb;
							}
						}
202
						f = map.phi1(map.phi2(f));
Pierre Kraemer's avatar
Pierre Kraemer committed
203
					} while (f != ee);
204
					ee = map.phi1(ee);
Pierre Kraemer's avatar
Pierre Kraemer committed
205 206 207 208 209 210 211 212 213 214 215
				} while (ee != e);

				bound.pop_back();
				--nb;
			} while (!bound.empty());
		}
	}
#undef LIST_SIZE
}

template<typename PFP>
Sylvain Thery's avatar
Sylvain Thery committed
216
void MapRender_VBO::initLines(typename PFP::MAP& map, const FunctorSelect& good, std::vector<GLuint>& tableIndices, unsigned int thread)
Pierre Kraemer's avatar
Pierre Kraemer committed
217
{
Sylvain Thery's avatar
Sylvain Thery committed
218
	DartMarker m(map,thread);
219
	tableIndices.reserve(map.getNbDarts());
Pierre Kraemer's avatar
Pierre Kraemer committed
220

221
	for(Dart d = map.begin(); d != map.end(); map.next(d))
Pierre Kraemer's avatar
Pierre Kraemer committed
222
	{
223
		if(!m.isMarked(d) && good(d))
Pierre Kraemer's avatar
Pierre Kraemer committed
224
		{
225 226
			tableIndices.push_back(map.getEmbedding(d, VERTEX_ORBIT));
			tableIndices.push_back(map.getEmbedding(map.phi2(d), VERTEX_ORBIT));
Pierre Kraemer's avatar
Pierre Kraemer committed
227 228 229 230 231 232
			m.markOrbit(EDGE_ORBIT, d);
		}
	}
}

template<typename PFP>
Sylvain Thery's avatar
Sylvain Thery committed
233
void MapRender_VBO::initLinesOptimized(typename PFP::MAP& map, const FunctorSelect& good, std::vector<GLuint>& tableIndices, unsigned int thread)
Pierre Kraemer's avatar
Pierre Kraemer committed
234 235
{
#define LIST_SIZE 20
Sylvain Thery's avatar
Sylvain Thery committed
236 237 238

	DartMarker m(map,thread);

Pierre Kraemer's avatar
Pierre Kraemer committed
239
	// reserve memory for edges indices ( nb indices == nb darts)
240
	tableIndices.reserve(map.getNbDarts());
Pierre Kraemer's avatar
Pierre Kraemer committed
241

242
	for (Dart dd = map.begin(); dd != map.end(); map.next(dd))
Pierre Kraemer's avatar
Pierre Kraemer committed
243 244 245 246 247 248 249 250 251 252 253 254
	{
		if (!m.isMarked(dd))
		{
			std::list<Dart> bound;
			bound.push_back(dd);
			int nb = 1;
			do
			{
				Dart e = bound.back();
				Dart ee = e;
				do
				{
255
					Dart f = map.phi2(ee);
Pierre Kraemer's avatar
Pierre Kraemer committed
256 257
					if (!m.isMarked(ee))
					{
258 259 260 261
						if(good(ee))
							tableIndices.push_back(map.getEmbedding(ee, VERTEX_ORBIT));
						if(good(f))
							tableIndices.push_back(map.getEmbedding(map.phi1(ee), VERTEX_ORBIT));
Pierre Kraemer's avatar
Pierre Kraemer committed
262 263 264 265 266 267 268 269 270 271
						m.markOrbit(EDGE_ORBIT, f);

						bound.push_back(f);
						++nb;
						if (nb > LIST_SIZE)
						{
							bound.pop_front();
							--nb;
						}
					}
272
					ee = map.phi1(f);
Pierre Kraemer's avatar
Pierre Kraemer committed
273 274 275 276 277 278 279 280 281 282
				} while (ee != e);
				bound.pop_back();
				--nb;
			} while (!bound.empty());
		}
	}
#undef LIST_SIZE
}

template<typename PFP>
Sylvain Thery's avatar
Sylvain Thery committed
283
void MapRender_VBO::initPoints(typename PFP::MAP& map, const FunctorSelect& good, std::vector<GLuint>& tableIndices, unsigned int thread)
Pierre Kraemer's avatar
Pierre Kraemer committed
284
{
Sylvain Thery's avatar
Sylvain Thery committed
285
	CellMarker m(map, VERTEX_ORBIT,thread) ;
286
	tableIndices.reserve(map.getNbDarts()/5);
Pierre Kraemer's avatar
Pierre Kraemer committed
287

288
	for(Dart d = map.begin(); d != map.end(); map.next(d))
Pierre Kraemer's avatar
Pierre Kraemer committed
289
	{
290
		if(!m.isMarked(d) && good(d))
Pierre Kraemer's avatar
Pierre Kraemer committed
291
		{
292
			tableIndices.push_back(map.getEmbedding(d, VERTEX_ORBIT));
Pierre Kraemer's avatar
Pierre Kraemer committed
293 294 295 296 297 298
			m.mark(d) ;
		}
	}
}

template<typename PFP>
Sylvain Thery's avatar
Sylvain Thery committed
299
void MapRender_VBO::initPrimitives(typename PFP::MAP& map, const FunctorSelect& good, int prim, bool optimized, unsigned int thread)
Pierre Kraemer's avatar
Pierre Kraemer committed
300 301 302 303 304 305 306 307
{
	std::vector<GLuint> tableIndices;

	// indice du VBO a utiliser
	int vbo_ind = 0;
	switch(prim)
	{
		case FLAT_TRIANGLES:
Sylvain Thery's avatar
Sylvain Thery committed
308
			initFlatTriangles<PFP>(map,good,thread);
Pierre Kraemer's avatar
Pierre Kraemer committed
309 310 311 312
			break;

		case TRIANGLES:
			if(optimized)
Sylvain Thery's avatar
Sylvain Thery committed
313
				initTrianglesOptimized<PFP>(map,good,tableIndices,thread);
Pierre Kraemer's avatar
Pierre Kraemer committed
314
			else
Sylvain Thery's avatar
Sylvain Thery committed
315
				initTriangles<PFP>(map,good,tableIndices,thread) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
316 317 318 319 320
			m_nbIndicesTri = tableIndices.size();
			vbo_ind = m_VBOBuffers[TRIANGLE_INDICES];
			break;
		case LINES:
			if(optimized)
Sylvain Thery's avatar
Sylvain Thery committed
321
				initLinesOptimized<PFP>(map,good,tableIndices,thread);
Pierre Kraemer's avatar
Pierre Kraemer committed
322
			else
Sylvain Thery's avatar
Sylvain Thery committed
323
				initLines<PFP>(map,good,tableIndices,thread) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
324 325 326 327
			m_nbIndicesLines = tableIndices.size();
			vbo_ind = m_VBOBuffers[LINE_INDICES];
			break;
		case POINTS:
Sylvain Thery's avatar
Sylvain Thery committed
328
			initPoints<PFP>(map,good,tableIndices,thread);
Pierre Kraemer's avatar
Pierre Kraemer committed
329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346
			m_nbIndicesPoints = tableIndices.size();
			vbo_ind = m_VBOBuffers[POINT_INDICES];
			break;
		default:
			std::cerr << "problem initializing VBO indices" << std::endl;
			break;
	}
	int size = tableIndices.size();

	// setup du buffer d'indices
	glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, vbo_ind);
	glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER, size*sizeof(GLuint), &(tableIndices[0]), GL_STREAM_DRAW);
}




template<typename PFP>
Sylvain Thery's avatar
Sylvain Thery committed
347
void MapRender_VBO::initFlatTriangles(typename PFP::MAP& map, const FunctorSelect& good, unsigned int thread)
Pierre Kraemer's avatar
Pierre Kraemer committed
348 349
{
	std::vector<Geom::Vec3f> tableFlat;
350
	tableFlat.reserve(3*map.getNbDarts()); // 3 in case of polygonal faces (less chance of realloc, but bigger allocation)
Pierre Kraemer's avatar
Pierre Kraemer committed
351 352 353 354 355 356 357

	// map VBO of points for vertices positions
	glBindBufferARB(GL_ARRAY_BUFFER, m_VBOBuffers[POSITIONS_BUFFER]);
	Geom::Vec3f* tablePos = reinterpret_cast<Geom::Vec3f*>(glMapBuffer(GL_ARRAY_BUFFER,GL_READ_ONLY));

	m_nbFlatElts=0;
	// traversal of map for creating buffers
Sylvain Thery's avatar
Sylvain Thery committed
358
	DartMarker m(map,thread);
359
	for(Dart dd = map.begin(); dd != map.end(); map.next(dd))
Pierre Kraemer's avatar
Pierre Kraemer committed
360
	{
361
		if(!m.isMarked(dd) && good(dd))
Pierre Kraemer's avatar
Pierre Kraemer committed
362 363
		{
			Dart a = dd;
364 365
			Dart b = map.phi1(a);
			Dart c = map.phi1(b);
Pierre Kraemer's avatar
Pierre Kraemer committed
366

367 368 369
			Geom::Vec3f& P = tablePos[map.getEmbedding(a, VERTEX_ORBIT)];
			Geom::Vec3f& Q = tablePos[map.getEmbedding(b, VERTEX_ORBIT)];
			Geom::Vec3f& R = tablePos[map.getEmbedding(c, VERTEX_ORBIT)];
Pierre Kraemer's avatar
Pierre Kraemer committed
370 371 372 373 374 375 376 377 378

			Geom::Vec3f U = Q-P;
			Geom::Vec3f V = R-P;
			Geom::Vec3f N = U^V;
			N.normalize();

			// loop to cut a polygon in triangle on the fly (works only with convex faces)
			do
			{
379
				tableFlat.push_back(tablePos[map.getEmbedding(a, VERTEX_ORBIT)]);
Pierre Kraemer's avatar
Pierre Kraemer committed
380
				tableFlat.push_back(N);
381
				tableFlat.push_back(tablePos[map.getEmbedding(b, VERTEX_ORBIT)]);
Pierre Kraemer's avatar
Pierre Kraemer committed
382
				tableFlat.push_back(N);
383
				tableFlat.push_back(tablePos[map.getEmbedding(c, VERTEX_ORBIT)]);
Pierre Kraemer's avatar
Pierre Kraemer committed
384 385
				tableFlat.push_back(N);
				b = c;
386
				c = map.phi1(b);
Pierre Kraemer's avatar
Pierre Kraemer committed
387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411
			} while (c != dd);
			m.markOrbit(FACE_ORBIT, dd);
		}
	}
	glUnmapBuffer(GL_ARRAY_BUFFER);

	m_nbFlatElts = tableFlat.size()/2;

	//creating VBO for flat
	glBindBufferARB(GL_ARRAY_BUFFER, m_VBOBuffers[FLAT_BUFFER]);
	glBufferDataARB(GL_ARRAY_BUFFER, tableFlat.size() * sizeof(Geom::Vec3f), (char*)(&(tableFlat[0])), GL_STREAM_DRAW);

}





} // namespace VBO

} // namespace Render

} // namespace Algo

} // namespace CGoGN