ape-collision-limits.patch

Aperion, 07/12/2010 07:03 am

Download (7 kB)

collisions.cpp (working copy)
111 111
#ifdef USE_LUA
112 112
	lua=mlua;
113 113
#endif
114
	resizeCells(1000); // previous default value was 10k, lowered it a bit
114 115
	free_collision_box=0;
115 116
	free_collision_tri=0;
116 117
	free_eventsource=0;
......
305 306
	return hash&hashmask;
306 307
}
307 308

  
309
void Collisions::resizeCells(int newsize)
310
{
311
	int oldsize = cells.size();
312

  
313
	cell_t* old_array_start = &cells[0];
314
	cells.resize(newsize);
315
	cell_t* new_array_start = &cells[0];
316
	ptrdiff_t ptr_delta = new_array_start - old_array_start;
317

  
318

  
319
	//adjust pointer values in hashtable
320
	for(size_t i = 0; i < (1 << HASH_SIZE); i++)
321
	{
322
		if( hashtable[i].cellid == UNUSED_CELLID ) continue;
323
		
324
		hashtable[i].cell += ptr_delta;		
325
	}
326
	
327
	
328
	
329
	if(debugMode)
330
	{
331
		Ogre::LogManager::getSingleton().logMessage("COLL: cell limit of " + StringConverter::toString(oldsize) + " reached. Increasing limit by 1000.");
332
		Ogre::LogManager::getSingleton().logMessage("COLL: cell memory is now " + StringConverter::toString(cells.size() * sizeof(cell_t) / 1024.0f) + " kB big");
333
	}
334

  
335
	
336
	if(oldsize > (int)cells.size())
337
	{
338
		for(size_t i = oldsize - 1; i < cells.size(); i++)
339
		{
340
			memset(&cells[i], 0xff, sizeof(cell_t));
341
			//for(int j=0;j<CELL_BLOCKSIZE;j++)
342
			//	cells[i].element[j] = UNUSED_CELLELEMENT;
343
			cells[i].next=0;
344
			cells[i].free=0;
345
		}
346
	}
347
}
348

  
349

  
308 350
int Collisions::removeCollisionTri(int number)
309 351
{
310 352
	if(number>free_collision_tri)
......
382 424

  
383 425
	if (hashtable[pos].cellid==UNUSED_CELLID)
384 426
	{
385
		if (free_cell<MAX_CELLS)
386
		{
387
			//create a new cell
388
			hashtable[pos].cellid=cellid;
389
			hashtable[pos].cell=&cells[free_cell];
390
			cells[free_cell].free=1;
391
			cells[free_cell].element[0]=value;
392
			cells[free_cell].next=0;
393
			if (pos!=hashfunc(cellid)) collision_count++;
394
			if (cells[free_cell].free>largest_cellcount) largest_cellcount=cells[free_cell].free;
395
			free_cell++;
396
		}
397
		else
427
		if (free_cell + 10>=(int)cells.size())
398 428
		{
399
			if(debugMode)
400
				Ogre::LogManager::getSingleton().logMessage("COLL: not enough cells available");
429
			//int oldsize = cells.size();
430
			resizeCells(cells.size() + 1000);
401 431
		}
432
		//create a new cell
433
		hashtable[pos].cellid=cellid;
434
		hashtable[pos].cell=&cells[free_cell];
435
		cells[free_cell].free=1;
436
		cells[free_cell].element[0]=value;
437
		cells[free_cell].next=0;
438
		if (pos!=hashfunc(cellid)) collision_count++;
439
		if (cells[free_cell].free>largest_cellcount) largest_cellcount=cells[free_cell].free;
440
		free_cell++;
402 441
	}
403 442
	else if (hashtable[pos].cellid==cellid)
404 443
	{
......
469 508
	}
470 509
}
471 510

  
472
cell_t *Collisions::hash_find(int cell_x, int cell_z)
511
hash_t *Collisions::hash_find(int cell_x, int cell_z)
473 512
{
474 513
	unsigned int cellid=(cell_x<<16)+cell_z;
475 514
	unsigned int hash=hashfunc(cellid);
......
483 522
		pos++;
484 523
		if (pos==(1<<HASH_SIZE)) pos=0;
485 524
	}
525
	
526
	return &hashtable[pos];
527
}
528

  
529
cell_t *Collisions::cell_find(int cell_x, int cell_z)
530
{
531
#if 1
532
	unsigned int cellid=(cell_x<<16)+cell_z;
533
	unsigned int hash=hashfunc(cellid);
534
	//search the spot
535
	unsigned int pos=hash;
536
	unsigned int stop=hash-1;
537
	if (hash==0) stop=(1<<HASH_SIZE)-1;
538

  
539
	while (pos!=stop && hashtable[pos].cellid!=UNUSED_CELLID && hashtable[pos].cellid!=cellid)
540
	{
541
		pos++;
542
		if (pos==(1<<HASH_SIZE)) pos=0;
543
	}
544
	
486 545
	if (hashtable[pos].cellid==cellid) return hashtable[pos].cell;
487 546
	return NULL;
547
#else
548

  
549
	hash_t *hash = hash_find(cell_x, cell_y);
550
	return (hash->cellid == cellid) ? hash->cell : NULL;
551
#endif
488 552
}
489 553

  
490 554

  
......
685 749
{
686 750
	LogManager::getSingleton().logMessage("COLL: Collision system statistics:");
687 751
	LogManager::getSingleton().logMessage("COLL: Cell size: "+StringConverter::toString((float)CELL_SIZE)+" m");
688
	LogManager::getSingleton().logMessage("COLL: Hashtable occupation: "+StringConverter::toString(free_cell)+"/"+StringConverter::toString(MAX_CELLS)+" ("+StringConverter::toString(100.0f*free_cell/(MAX_CELLS))+"%)");
752
	LogManager::getSingleton().logMessage("COLL: Amount of Cells: " + StringConverter::toString(cells.size()));
753
	LogManager::getSingleton().logMessage("COLL: Cell memory is now " + StringConverter::toString(cells.size() * sizeof(cell_t) / 1024.0f) + " kB big");
754
	LogManager::getSingleton().logMessage("COLL: Hashtable occupation: "+StringConverter::toString(free_cell)+"/"+StringConverter::toString(cells.size())+" ("+StringConverter::toString(100.0f*free_cell/(cells.size()))+"%)");
689 755
	LogManager::getSingleton().logMessage("COLL: Hashtable collisions: "+StringConverter::toString(collision_count));
690 756
	LogManager::getSingleton().logMessage("COLL: Largest cell: "+StringConverter::toString(largest_cellcount)+"/"+StringConverter::toString(CELL_BLOCKSIZE)+" ("+StringConverter::toString(100.0f*largest_cellcount/CELL_BLOCKSIZE)+"%)");
691

  
692 757
}
693 758

  
694 759

  
......
703 768

  
704 769
	refx=(int)(refpos->x/(float)CELL_SIZE);
705 770
	refz=(int)(refpos->z/(float)CELL_SIZE);
706
	cell_t *cell=hash_find(refx, refz);
771
	cell_t *cell=cell_find(refx, refz);
707 772

  
708 773
	collision_tri_t *minctri=0;
709 774
	float minctridist=100.0;
......
901 966
	int refx, refz;
902 967
	refx=(int)(node->AbsPosition.x*inverse_CELL_SIZE);
903 968
	refz=(int)(node->AbsPosition.z*inverse_CELL_SIZE);
904
	cell_t *cell=hash_find(refx, refz);
969
	cell_t *cell=cell_find(refx, refz);
905 970
	//LogManager::getSingleton().logMessage("Checking cell "+StringConverter::toString(refx)+" "+StringConverter::toString(refz)+" total indexes: "+StringConverter::toString(num_cboxes_index[refp]));
906 971

  
907 972
	collision_tri_t *minctri=0;
......
1371 1436
		{
1372 1437
			int cellx = (int)(x/(float)CELL_SIZE);
1373 1438
			int cellz = (int)(z/(float)CELL_SIZE);
1374
			cell_t *cell=hash_find(cellx, cellz);
1439
			cell_t *cell=cell_find(cellx, cellz);
1375 1440
			if(cell)
1376 1441
			{
1377 1442
				float groundheight = -9999;
collisions.h (working copy)
35 35
//how many elements per cell? power of 2 minus 2 is better
36 36
#define CELL_BLOCKSIZE 126
37 37
//how many cells in the pool? Increase in case of sparce distribution of objects
38
#define MAX_CELLS 10000
38
//#define MAX_CELLS 10000 // moved to std::vector, no more limit
39 39
#define UNUSED_CELLID 0xFFFFFFFF
40 40
#define UNUSED_CELLELEMENT 0xFFFFFFFF
41 41
//terrain size is limited to 327km x 327km:
......
83 83

  
84 84
typedef struct _cell
85 85
{
86
	unsigned int cellid;
86 87
	int free;
87 88
	int element[CELL_BLOCKSIZE];
88 89
	void *next;
......
108 109
	//collision hashtable
109 110
	hash_t hashtable[1<<HASH_SIZE];
110 111
	//cell pool
111
	cell_t cells[MAX_CELLS];
112
	std::vector<cell_t> cells;
112 113
	int free_cell;
113 114

  
114 115
	eventsource_t eventsources[MAX_EVENTSOURCE];
......
130 131
private:
131 132
	void hash_add(int cell_x, int cell_z, int value);
132 133
	void hash_free(int cell_x, int cell_z, int value);
133
	cell_t *hash_find(int cell_x, int cell_z);
134
	cell_t *cell_find(int cell_x, int cell_z);
135
	hash_t *hash_find(int cell_x, int cell_z);
134 136
	unsigned int hashfunc(unsigned int cellid);
137
	void resizeCells(int newsize);
135 138
	int collisionVersion;
136 139
	std::map<Ogre::String, ground_model_t> ground_models;
137 140
	void parseGroundConfig(Ogre::ConfigFile *cfg, Ogre::String groundModel=Ogre::String());