mapRender.hpp 17.1 KB
Newer Older
1 2 3
/*******************************************************************************
* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps  *
* version 0.1                                                                  *
4
* Copyright (C) 2009-2012, IGG Team, LSIIT, University of Strasbourg           *
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
*                                                                              *
* 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.           *
*                                                                              *
20
* Web site: http://cgogn.unistra.fr/                                           *
21 22 23
* Contact information: cgogn@unistra.fr                                        *
*                                                                              *
*******************************************************************************/
24

25
#include "Topology/generic/attributeHandler.h"
26 27
#include "Topology/generic/dartmarker.h"
#include "Topology/generic/cellmarker.h"
28
#include "Topology/generic/traversor/traversorCell.h"
29

Thery Sylvain's avatar
Thery Sylvain committed
30
//#include "Utils/vbo.h"
31

32 33 34
#include "Geometry/intersection.h"
#include "Algo/Geometry/normal.h"

35 36 37 38 39 40 41 42 43
namespace CGoGN
{

namespace Algo
{

namespace Render
{

Sylvain Thery's avatar
Sylvain Thery committed
44
namespace GL2
45 46
{

47 48
inline bool MapRender::cmpVP(VertexPoly* lhs, VertexPoly* rhs)
{
Sylvain Thery's avatar
Sylvain Thery committed
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
//	 return lhs->value < rhs->value;

	if (fabs(lhs->value - rhs->value)<0.2f)
			return lhs->length < rhs->length;
	return lhs->value < rhs->value;
}

template<typename VEC3>
bool MapRender::inTriangle(const VEC3& P, const VEC3& normal, const VEC3& Ta,  const VEC3& Tb, const VEC3& Tc)
{
	typedef typename VEC3::DATA_TYPE T ;

	if (Geom::tripleProduct(P-Ta, (Tb-Ta), normal) >= T(0))
		return false;

	if (Geom::tripleProduct(P-Tb, (Tc-Tb), normal) >= T(0))
		return false;

	if (Geom::tripleProduct(P-Tc, (Ta-Tc), normal) >= T(0))
		return false;

	return true;
71 72
}

73
template<typename PFP>
74
void MapRender::recompute2Ears(const VertexAttribute<typename PFP::VEC3, typename PFP::MAP::IMPL>& position, VertexPoly* vp, const typename PFP::VEC3& normalPoly, VPMS& ears, bool convex)
75
{
76 77
	typedef typename PFP::VEC3 VEC3;

78 79 80
	VertexPoly* vprev = vp->prev;
	VertexPoly* vp2 = vp->next;
	VertexPoly* vnext = vp2->next;
81 82 83 84
	const VEC3& Ta = position[vp->id];
	const VEC3& Tb = position[vp2->id];
	const VEC3& Tc = position[vprev->id];
	const VEC3& Td = position[vnext->id];
85 86

	// compute angle
87 88 89
	VEC3 v1= Tb - Ta;
	VEC3 v2= Tc - Ta;
	VEC3 v3= Td - Tb;
90

91 92 93 94
	v1.normalize();
	v2.normalize();
	v3.normalize();

Sylvain Thery's avatar
Sylvain Thery committed
95 96 97 98 99
//	float dotpr1 = 1.0f - (v1*v2);
//	float dotpr2 = 1.0f + (v1*v3);
	float dotpr1 = acos(v1*v2) / (M_PI/2.0f);
	float dotpr2 = acos(-(v1*v3)) / (M_PI/2.0f);

100

101
	if (!convex)	// if convex no need to test if vertex is an ear (yes)
102
	{
103 104
		VEC3 nv1 = v1^v2;
		VEC3 nv2 = v1^v3;
105 106 107 108 109

		if (nv1*normalPoly < 0.0)
			dotpr1 = 10.0f - dotpr1;// not an ears  (concave)
		if (nv2*normalPoly < 0.0)
			dotpr2 = 10.0f - dotpr2;// not an ears  (concave)
110

Sylvain Thery's avatar
Sylvain Thery committed
111
		bool finished = (dotpr1>=5.0f) && (dotpr2>=5.0f);
112
		for (VPMS::reverse_iterator it = ears.rbegin(); (!finished)&&(it != ears.rend())&&((*it)->value > 5.0f); ++it)
113
		{
114
			int id = (*it)->id;
115
			const VEC3& P = position[id];
116

Sylvain Thery's avatar
Sylvain Thery committed
117
			if ((dotpr1 < 5.0f) && (id !=vprev->id))
118
				if (inTriangle<VEC3>(P, normalPoly,Tb,Tc,Ta))
119
					dotpr1 = 5.0f;// not an ears !
120

Sylvain Thery's avatar
Sylvain Thery committed
121
			if ((dotpr2 < 5.0f) && (id !=vnext->id) )
122
				if (inTriangle<VEC3>(P, normalPoly,Td,Ta,Tb))
123 124
					dotpr2 = 5.0f;// not an ears !

Sylvain Thery's avatar
Sylvain Thery committed
125
			finished = ((dotpr1 >= 5.0f)&&(dotpr2 >= 5.0f));
126 127
		}
	}
128 129

	vp->value  = dotpr1;
Sylvain Thery's avatar
Sylvain Thery committed
130
	vp->length = (Tb-Tc).norm2();
131
	vp->ear = ears.insert(vp);
132
	vp2->value = dotpr2;
Sylvain Thery's avatar
Sylvain Thery committed
133
	vp->length = (Td-Ta).norm2();
134
	vp2->ear = ears.insert(vp2);
135 136 137
}

template<typename PFP>
138
float MapRender::computeEarAngle(const typename PFP::VEC3& P1, const typename PFP::VEC3& P2,  const typename PFP::VEC3& P3, const typename PFP::VEC3& normalPoly)
139
{
140 141 142 143
	typedef typename PFP::VEC3 VEC3;

	VEC3 v1 = P1-P2;
	VEC3 v2 = P3-P2;
144 145
	v1.normalize();
	v2.normalize();
146

Sylvain Thery's avatar
Sylvain Thery committed
147 148
//	float dotpr = 1.0f - (v1*v2);
	float dotpr = acos(v1*v2) / (M_PI/2.0f);
149

150
	VEC3 vn = v1^v2;
151 152
	if (vn*normalPoly > 0.0f)
		dotpr = 10.0f - dotpr; 		// not an ears  (concave, store at the end for optimized use for intersections)
153 154 155 156 157

	return dotpr;
}

template<typename PFP>
158
bool MapRender::computeEarIntersection(const VertexAttribute<typename PFP::VEC3, typename PFP::MAP::IMPL>& position, VertexPoly* vp, const typename PFP::VEC3& normalPoly)
159
{
160
	typedef typename PFP::VEC3 VEC3;
Sylvain Thery's avatar
Sylvain Thery committed
161

162 163
	VertexPoly* endV = vp->prev;
	VertexPoly* curr = vp->next;
164 165 166
	const VEC3& Ta = position[vp->id];
	const VEC3& Tb = position[curr->id];
	const VEC3& Tc = position[endV->id];
167 168 169 170
	curr = curr->next;

	while (curr != endV)
	{
171
		if (inTriangle<VEC3>(position[curr->id], normalPoly,Tb,Tc,Ta))
172 173 174 175 176 177 178 179 180 181 182
		{
			vp->value = 5.0f;// not an ears !
			return false;
		}
		curr = curr->next;
	}

	return true;
}

template<typename PFP>
183
inline void MapRender::addEarTri(typename PFP::MAP& map, Dart d, std::vector<GLuint>& tableIndices, const VertexAttribute<typename PFP::VEC3, typename PFP::MAP::IMPL>* pos)
184
{
185 186
	typedef typename PFP::VEC3 VEC3;

Sylvain Thery's avatar
Sylvain Thery committed
187 188
	bool(*fn_pt1)(VertexPoly*,VertexPoly*) = &(MapRender::cmpVP);
	VPMS ears(fn_pt1);
189

190
	const VertexAttribute<VEC3, typename PFP::MAP::IMPL>& position = *pos ;
191 192

	// compute normal to polygon
193
	VEC3 normalPoly = Algo::Surface::Geometry::newellNormal<PFP>(map, d, position);
194

195
	// first pass create polygon in chained list with angle computation
196 197
	VertexPoly* vpp = NULL;
	VertexPoly* prem = NULL;
198 199 200 201 202 203 204
	unsigned int nbv = 0;
	unsigned int nbe = 0;
	Dart a = d;
	Dart b = map.phi1(a);
	Dart c = map.phi1(b);
	do
	{
205 206 207
		VEC3 P1 = position[map.template getEmbedding<VERTEX>(a)];
		VEC3 P2 = position[map.template getEmbedding<VERTEX>(b)];
		VEC3 P3 = position[map.template getEmbedding<VERTEX>(c)];
208

209
		float val = computeEarAngle<PFP>(P1, P2, P3, normalPoly);
210
		VertexPoly* vp = new VertexPoly(map.template getEmbedding<VERTEX>(b), val, (P3-P1).norm2(), vpp);
Sylvain Thery's avatar
Sylvain Thery committed
211

212
		if (vp->value < 5.0f)
213
			nbe++;
214
		if (vpp == NULL)
215 216 217 218 219 220
			prem = vp;
		vpp = vp;
		a = b;
		b = c;
		c = map.phi1(c);
		nbv++;
221
	}while (a != d);
222

223
	VertexPoly::close(prem, vpp);
224

225
	bool convex = nbe == nbv;
226 227
	if (convex)
	{
228
		// second pass with no test of intersections with polygons
229 230 231
		vpp = prem;
		for (unsigned int i=0; i< nbv; ++i)
		{
232
			vpp->ear = ears.insert(vpp);
233 234 235 236 237
			vpp = vpp->next;
		}
	}
	else
	{
238
		// second pass test intersections with polygons
239 240 241 242
		vpp = prem;
		for (unsigned int i=0; i< nbv; ++i)
		{
			if (vpp->value <5.0f)
243
				computeEarIntersection<PFP>(position, vpp, normalPoly);
244
			vpp->ear = ears.insert(vpp);
245 246 247 248
			vpp = vpp->next;
		}
	}

249
	// NOW WE HAVE THE POLYGON AND EARS
250 251 252 253
	// LET'S REMOVE THEM
	while (nbv>3)
	{
		// take best (and valid!) ear
Sylvain Thery's avatar
Sylvain Thery committed
254
		VPMS::iterator be_it = ears.begin(); // best ear
255
		VertexPoly* be = *be_it;
256 257 258 259 260 261 262

		tableIndices.push_back(be->id);
		tableIndices.push_back(be->next->id);
		tableIndices.push_back(be->prev->id);
		nbv--;

		if (nbv>3)	// do not recompute if only one triangle left
Sylvain Thery's avatar
Sylvain Thery committed
263 264 265 266 267 268
		{
			//remove ears and two sided ears
			ears.erase(be_it);					// from map of ears
			ears.erase(be->next->ear);
			ears.erase(be->prev->ear);
			be = VertexPoly::erase(be); 	// and remove ear vertex from polygon
269
			recompute2Ears<PFP>(position,be,normalPoly,ears,convex);
Sylvain Thery's avatar
Sylvain Thery committed
270 271 272
			convex = (*(ears.rbegin()))->value < 5.0f;
		}
		else		// finish (no need to update ears)
273
		{
Sylvain Thery's avatar
Sylvain Thery committed
274 275 276
			// remove ear from polygon
			be = VertexPoly::erase(be);
			// last triangle
277
			tableIndices.push_back(be->id);
Sylvain Thery's avatar
Sylvain Thery committed
278
			tableIndices.push_back(be->next->id);
279
			tableIndices.push_back(be->prev->id);
280 281 282 283
			// release memory of last triangle in polygon
			delete be->next;
			delete be->prev;
			delete be;
284 285 286 287
		}
	}
}

288 289 290 291 292 293 294 295
template<typename PFP>
inline void MapRender::addTri(typename PFP::MAP& map, Dart d, std::vector<GLuint>& tableIndices)
{
	Dart a = d;
	Dart b = map.phi1(a);
	Dart c = map.phi1(b);

	// loop to cut a polygon in triangle on the fly (works only with convex faces)
296 297
	do
	{
298 299 300
		tableIndices.push_back(map.template getEmbedding<VERTEX>(d));
		tableIndices.push_back(map.template getEmbedding<VERTEX>(b));
		tableIndices.push_back(map.template getEmbedding<VERTEX>(c));
301 302 303
		b = c;
		c = map.phi1(b);
	} while (c != d);
304 305 306
}

template<typename PFP>
307
void MapRender::initTriangles(typename PFP::MAP& map, std::vector<GLuint>& tableIndices, const VertexAttribute<typename PFP::VEC3, typename PFP::MAP::IMPL>* position, unsigned int thread)
308
{
Pierre Kraemer's avatar
Pierre Kraemer committed
309 310
	tableIndices.reserve(4 * map.getNbDarts() / 3);

311
//	TraversorF<typename PFP::MAP> trav(map, thread);
312 313 314

	if(position == NULL)
	{
315 316
//		for (Dart d = trav.begin(); d != trav.end(); d = trav.next())
		foreachCellMT(VERTEX,d,typename PFP::MAP,map,thread)
317 318 319 320
			addTri<PFP>(map, d, tableIndices);
	}
	else
	{
321 322
//		for (Dart d = trav.begin(); d != trav.end(); d = trav.next())
		foreachCellMT(VERTEX,d,typename PFP::MAP,map,thread)
323 324 325 326 327 328 329
		{
			if(map.faceDegree(d) == 3)
				addTri<PFP>(map, d, tableIndices);
			else
				addEarTri<PFP>(map, d, tableIndices, position);
		}
	}
330 331 332
}

template<typename PFP>
333
void MapRender::initTrianglesOptimized(typename PFP::MAP& map, std::vector<GLuint>& tableIndices, const VertexAttribute<typename PFP::VEC3, typename PFP::MAP::IMPL>* position, unsigned int thread)
334 335
{
#define LIST_SIZE 20
Pierre Kraemer's avatar
Pierre Kraemer committed
336
	DartMarker<typename PFP::MAP> m(map, thread);
337 338 339
	// reserve memory for triangles ( nb indices == nb darts )
	// and a little bit more
	// if lots of polygonal faces, realloc is done by vector
Pierre Kraemer's avatar
Pierre Kraemer committed
340
	tableIndices.reserve(4 * map.getNbDarts() / 3);
341 342 343 344 345 346 347

	for (Dart dd = map.begin(); dd != map.end(); map.next(dd))
	{
		if (!m.isMarked(dd))
		{
			std::list<Dart> bound;

348
			if (!map.template isBoundaryMarked<PFP::MAP::DIMENSION>(dd))
349 350 351 352 353 354 355 356 357 358 359
			{
				if(position == NULL)
					addTri<PFP>(map, dd, tableIndices);
				else
				{
					if(map.faceDegree(dd) == 3)
						addTri<PFP>(map, dd, tableIndices);
					else
						addEarTri<PFP>(map, dd, tableIndices, position);
				}
			}
360
			m.template markOrbit<FACE>(dd);
361 362 363 364 365 366 367 368 369 370 371 372 373
			bound.push_back(dd);
			int nb = 1;
			do
			{
				Dart e = bound.back();
				Dart ee = e;
				do
				{
					Dart f = ee;
					do
					{
						if (!m.isMarked(f))
						{
374
							if ( !map.template isBoundaryMarked<PFP::MAP::DIMENSION>(f))
375 376 377 378 379 380 381 382 383 384 385
							{
								if(position == NULL)
									addTri<PFP>(map, f, tableIndices);
								else
								{
									if(map.faceDegree(f) == 3)
										addTri<PFP>(map, f, tableIndices);
									else
										addEarTri<PFP>(map, f, tableIndices, position);
								}
							}
386
							m.template markOrbit<FACE>(f);
387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408
							bound.push_back(map.phi1(f));
							++nb;
							if (nb > LIST_SIZE)
							{
								bound.pop_front();
								--nb;
							}
						}
						f = map.phi1(map.phi2(f));
					} while (f != ee);
					ee = map.phi1(ee);
				} while (ee != e);

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

template<typename PFP>
409
void MapRender::initLines(typename PFP::MAP& map, std::vector<GLuint>& tableIndices, unsigned int thread)
410 411 412
{
	tableIndices.reserve(map.getNbDarts());

413 414 415
//	TraversorE<typename PFP::MAP> trav(map, thread);
//	for (Dart d = trav.begin(); d != trav.end(); d = trav.next())
	foreachCellMT(EDGE,d,typename PFP::MAP,map,thread)
416
	{
Pierre Kraemer's avatar
Pierre Kraemer committed
417
		tableIndices.push_back(map.template getEmbedding<VERTEX>(d.dart));
418
		tableIndices.push_back(map.template getEmbedding<VERTEX>(map.phi1(d)));
419 420 421 422
	}
}

template<typename PFP>
423
void MapRender::initBoundaries(typename PFP::MAP& map, std::vector<GLuint>& tableIndices, unsigned int thread)
424 425 426
{
	tableIndices.reserve(map.getNbDarts()); //TODO optimisation ?

427 428 429
//	TraversorE<typename PFP::MAP> trav(map, thread);
//	for (Dart d = trav.begin(); d != trav.end(); d = trav.next())
	foreachCellMT(EDGE,d,typename PFP::MAP,map,thread)
430
	{
Pierre Kraemer's avatar
Pierre Kraemer committed
431
		if (map.isBoundaryEdge(d))
432
		{
Pierre Kraemer's avatar
Pierre Kraemer committed
433
			tableIndices.push_back(map.template getEmbedding<VERTEX>(d.dart));
434
			tableIndices.push_back(map.template getEmbedding<VERTEX>(map.phi1(d)));
435 436 437 438 439
		}
	}
}

template<typename PFP>
440
void MapRender::initLinesOptimized(typename PFP::MAP& map, std::vector<GLuint>& tableIndices, unsigned int thread)
441 442
{
#define LIST_SIZE 20
Pierre Kraemer's avatar
Pierre Kraemer committed
443
	DartMarker<typename PFP::MAP> m(map, thread);
444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463

	// reserve memory for edges indices ( nb indices == nb darts)
	tableIndices.reserve(map.getNbDarts());

	for (Dart dd = map.begin(); dd != map.end(); map.next(dd))
	{
		if (!m.isMarked(dd))
		{
			std::list<Dart> bound;
			bound.push_back(dd);
			int nb = 1;
			do
			{
				Dart e = bound.back();
				Dart ee = e;
				do
				{
					Dart f = map.phi2(ee);
					if (!m.isMarked(ee))
					{
464 465
						tableIndices.push_back(map.template getEmbedding<VERTEX>(ee));
						tableIndices.push_back(map.template getEmbedding<VERTEX>(map.phi1(ee)));
466
						m.template markOrbit<EDGE>(f);
467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486

						bound.push_back(f);
						++nb;
						if (nb > LIST_SIZE)
						{
							bound.pop_front();
							--nb;
						}
					}
					ee = map.phi1(f);
				} while (ee != e);
				bound.pop_back();
				--nb;
			} while (!bound.empty());
		}
	}
#undef LIST_SIZE
}

template<typename PFP>
487
void MapRender::initPoints(typename PFP::MAP& map, std::vector<GLuint>& tableIndices, unsigned int thread)
488
{
Pierre Kraemer's avatar
Pierre Kraemer committed
489
	tableIndices.reserve(map.getNbDarts() / 5);
490

491 492 493
//	TraversorV<typename PFP::MAP> trav(map, thread);
//	for (Dart d = trav.begin(); d != trav.end(); d = trav.next())
	foreachCellMT(VERTEX,d,typename PFP::MAP,map,thread)
494
		tableIndices.push_back(map.template getEmbedding<VERTEX>(d));
495 496
}

Pierre Kraemer's avatar
Pierre Kraemer committed
497
template<typename PFP>
498
void MapRender::initPrimitives(typename PFP::MAP& map, int prim, bool optimized, unsigned int thread)
499
{
500
	initPrimitives<PFP>(map, prim, NULL, optimized, thread) ;
501 502 503
}

template <typename PFP>
504
void MapRender::initPrimitives(typename PFP::MAP& map, int prim, const VertexAttribute<typename PFP::VEC3, typename PFP::MAP::IMPL>* position, bool optimized, unsigned int thread)
Pierre Kraemer's avatar
Pierre Kraemer committed
505 506
{
	std::vector<GLuint> tableIndices;
Sylvain Thery's avatar
Sylvain Thery committed
507

Pierre Kraemer's avatar
Pierre Kraemer committed
508 509 510
	switch(prim)
	{
		case POINTS:
511

512
			initPoints<PFP>(map, tableIndices, thread);
Pierre Kraemer's avatar
Pierre Kraemer committed
513 514 515
			break;
		case LINES:
			if(optimized)
516
				initLinesOptimized<PFP>(map, tableIndices, thread);
Pierre Kraemer's avatar
Pierre Kraemer committed
517
			else
518
				initLines<PFP>(map, tableIndices, thread) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
519 520 521
			break;
		case TRIANGLES:
			if(optimized)
522
				initTrianglesOptimized<PFP>(map, tableIndices, position, thread);
Pierre Kraemer's avatar
Pierre Kraemer committed
523
			else
524
				initTriangles<PFP>(map, tableIndices, position, thread) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
525 526 527
			break;
		case FLAT_TRIANGLES:
			break;
528
		case BOUNDARY:
529
			initBoundaries<PFP>(map, tableIndices, thread) ;
530
			break;
Pierre Kraemer's avatar
Pierre Kraemer committed
531 532 533 534
		default:
			CGoGNerr << "problem initializing VBO indices" << CGoGNendl;
			break;
	}
535 536 537

	m_nbIndices[prim] = tableIndices.size();
	m_indexBufferUpToDate[prim] = true;
Sylvain Thery's avatar
Sylvain Thery committed
538

Pierre Kraemer's avatar
Pierre Kraemer committed
539
	// setup du buffer d'indices
540 541
	glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, m_indexBuffers[prim]);
	glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER, m_nbIndices[prim] * sizeof(GLuint), &(tableIndices[0]), GL_STREAM_DRAW);
Pierre Kraemer's avatar
Pierre Kraemer committed
542
}
Sylvain Thery's avatar
Sylvain Thery committed
543

544
template <typename PFP>
545
void MapRender::addPrimitives(typename PFP::MAP& map, int prim, const VertexAttribute<typename PFP::VEC3, typename PFP::MAP::IMPL>* position, bool optimized, unsigned int thread)
546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601
{
	std::vector<GLuint> tableIndices;

	switch(prim)
	{
		case POINTS:

			initPoints<PFP>(map, tableIndices, thread);
			break;
		case LINES:
			if(optimized)
				initLinesOptimized<PFP>(map, tableIndices, thread);
			else
				initLines<PFP>(map, tableIndices, thread) ;
			break;
		case TRIANGLES:
			if(optimized)
				initTrianglesOptimized<PFP>(map, tableIndices, position, thread);
			else
				initTriangles<PFP>(map, tableIndices, position, thread) ;
			break;
		case FLAT_TRIANGLES:
			break;
		case BOUNDARY:
			initBoundaries<PFP>(map, tableIndices, thread) ;
			break;
		default:
			CGoGNerr << "problem initializing VBO indices" << CGoGNendl;
			break;
	}

	m_indexBufferUpToDate[prim] = true;

	glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, m_indexBuffers[prim]);
	GLint sz=0;
	glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_SIZE, &sz);
	GLuint* oldIndices =  reinterpret_cast<GLuint*>(glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_READ_WRITE));

	// allocate new buffer
	GLuint newBuffer;
	glGenBuffers(1,&newBuffer);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, newBuffer);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sz + tableIndices.size() * sizeof(GLuint),NULL, GL_STREAM_DRAW);

	//copy old indices
	glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sz, oldIndices);
	//and new ones
	glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, sz, m_nbIndices[prim] * sizeof(GLuint), &(tableIndices[0]) );

	glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, m_indexBuffers[prim]);
	glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);

	glDeleteBuffers(1,&(m_indexBuffers[prim]));
	m_indexBuffers[prim] = newBuffer;

	m_nbIndices[prim] += tableIndices.size();
Pierre Kraemer's avatar
Pierre Kraemer committed
602
}
Sylvain Thery's avatar
Sylvain Thery committed
603 604

} // namespace GL2
605 606 607 608 609 610

} // namespace Render

} // namespace Algo

} // namespace CGoGN