region.cc
Go to the documentation of this file.
1 /*
2  region.cc
3  data structures supporting multi-resolution ray tracing in world class.
4  Copyright Richard Vaughan 2008
5 */
6 
7 #include "region.hh"
8 #include <pthread.h>
9 using namespace Stg;
10 
11 Stg::Region::Region() : cells(), count(0), superregion(NULL)
12 {
13 }
14 
16 {
17 }
18 
20 {
21  ++count;
23 }
24 
26 {
27  --count;
29 
30  // if there's nothing in this region, we can garbage collect the
31  // cells to keep memory usage under control
32  if (count == 0)
33  cells.clear();
34 }
35 
37  : count(0), origin(origin), regions(), world(world)
38 {
39  for (int32_t c = 0; c < SUPERREGIONSIZE; ++c)
40  regions[c].superregion = this;
41 }
42 
44 {
45 }
46 
48 {
49  ++count;
50 }
51 
53 {
54  --count;
55 }
56 
58 {
59  // printf( "SR origin (%d,%d) this %p\n", origin.x, origin.y, this );
60 
61  glPushMatrix();
62  GLfloat scale = 1.0 / world->Resolution();
63  glScalef(scale, scale, 1.0); // XX TODO - this seems slightly
64  glTranslatef(origin.x << SRBITS, origin.y << SRBITS, 0);
65 
66  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
67 
68  // outline superregion
69  glColor3f(0, 0, 1);
70  glRecti(0, 0, 1 << SRBITS, 1 << SRBITS);
71 
72  // outline regions
73  const Region *r = &regions[0];
74  std::vector<GLfloat> rects(1000);
75 
76  for (int y = 0; y < SUPERREGIONWIDTH; ++y)
77  for (int x = 0; x < SUPERREGIONWIDTH; ++x) {
78  if (r->count) // region contains some occupied cells
79  {
80  // outline the region
81  glColor3f(0, 1, 0);
82  glRecti(x << RBITS, y << RBITS, (x + 1) << RBITS, (y + 1) << RBITS);
83 
84  // show how many cells are occupied
85  // snprintf( buf, 15, "%lu", r->count );
86  // Gl::draw_string( x<<RBITS, y<<RBITS, 0, buf );
87 
88  // draw a rectangle around each occupied cell
89  for (int p = 0; p < REGIONWIDTH; ++p)
90  for (int q = 0; q < REGIONWIDTH; ++q) {
91  const Cell &c = r->cells[p + (q * REGIONWIDTH)];
92 
93  if (c.blocks[0].size()) // layer 0
94  {
95  const GLfloat xx = p + (x << RBITS);
96  const GLfloat yy = q + (y << RBITS);
97 
98  rects.push_back(xx);
99  rects.push_back(yy);
100  rects.push_back(xx + 1);
101  rects.push_back(yy);
102  rects.push_back(xx + 1);
103  rects.push_back(yy + 1);
104  rects.push_back(xx);
105  rects.push_back(yy + 1);
106  }
107 
108  if (c.blocks[1].size()) // layer 1
109  {
110  const GLfloat xx = p + (x << RBITS);
111  const GLfloat yy = q + (y << RBITS);
112  const double dx = 0.1;
113 
114  rects.push_back(xx + dx);
115  rects.push_back(yy + dx);
116  rects.push_back(xx + 1 - dx);
117  rects.push_back(yy + dx);
118  rects.push_back(xx + 1 - dx);
119  rects.push_back(yy + 1 - dx);
120  rects.push_back(xx + dx);
121  rects.push_back(yy + 1 - dx);
122  }
123  }
124  }
125  ++r; // next region quickly
126  }
127 
128  if (rects.size()) {
129  assert(rects.size() % 8 == 0); // should be full of squares
130  glVertexPointer(2, GL_FLOAT, 0, &rects[0]);
131  glDrawArrays(GL_QUADS, 0, rects.size() / 2);
132  }
133 
134  // char buf[32];
135  // snprintf( buf, 15, "%lu", count );
136  // Gl::draw_string( 1<<SBITS, 1<<SBITS, 0, buf );
137 
138  glPopMatrix();
139 }
140 
141 static inline const std::vector<GLfloat> DrawBlock(GLfloat x, GLfloat y, GLfloat zmin, GLfloat zmax)
142 {
143  std::vector<GLfloat> v(60);
144 
145  // TOP
146  v[0] = x;
147  v[1] = y;
148  v[2] = zmax;
149  v[3] = 1 + x;
150  v[4] = y;
151  v[5] = zmax;
152  v[6] = 1 + x;
153  v[7] = 1 + y;
154  v[8] = zmax;
155  v[9] = x;
156  v[10] = 1 + y;
157  v[11] = zmax;
158 
159  // sides
160  v[12] = x;
161  v[13] = y;
162  v[14] = zmax;
163  v[15] = x;
164  v[16] = 1 + y;
165  v[17] = zmax;
166  v[18] = x;
167  v[19] = 1 + y;
168  v[20] = zmin;
169  v[21] = x;
170  v[22] = y;
171  v[23] = zmin;
172  v[24] = 1 + x;
173  v[25] = y;
174  v[26] = zmax;
175  v[27] = x;
176  v[28] = y;
177  v[29] = zmax;
178  v[30] = x;
179  v[31] = y;
180  v[32] = zmin;
181  v[33] = 1 + x;
182  v[34] = y;
183  v[35] = zmin;
184  v[36] = 1 + x;
185  v[37] = 1 + y;
186  v[38] = zmax;
187  v[39] = 1 + x;
188  v[40] = y;
189  v[41] = zmax;
190  v[42] = 1 + x;
191  v[43] = y;
192  v[44] = zmin;
193  v[45] = 1 + x;
194  v[46] = 1 + y;
195  v[47] = zmin;
196  v[48] = x;
197  v[49] = 1 + y;
198  v[50] = zmax;
199  v[51] = 1 + x;
200  v[52] = 1 + y;
201  v[53] = zmax;
202  v[54] = 1 + x;
203  v[55] = 1 + y;
204  v[56] = zmin;
205  v[57] = x;
206  v[58] = 1 + y;
207  v[59] = zmin;
208 
209  return v;
210 }
211 
212 void SuperRegion::DrawVoxels(unsigned int layer) const
213 {
214  glPushMatrix();
215  GLfloat scale = 1.0 / world->Resolution();
216  glScalef(scale, scale, 1.0); // XX TODO - this seems slightly
217  glTranslatef(origin.x << SRBITS, origin.y << SRBITS, 0);
218 
219  glEnable(GL_DEPTH_TEST);
220  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
221 
222  std::vector<GLfloat> verts(1000);
223  std::vector<GLfloat> colors(1000);
224 
225  const Region *r = &regions[0];
226 
227  for (int y = 0; y < SUPERREGIONWIDTH; ++y)
228  for (int x = 0; x < SUPERREGIONWIDTH; ++x) {
229  if (r->count) // not an empty region
230  for (int p = 0; p < REGIONWIDTH; ++p)
231  for (int q = 0; q < REGIONWIDTH; ++q) {
232  const std::vector<Block *> &blocks = r->cells[p + (q * REGIONWIDTH)].blocks[layer];
233 
234  if (blocks.size()) // not an empty cell
235  {
236  const GLfloat xx(p + (x << RBITS));
237  const GLfloat yy(q + (y << RBITS));
238 
239  FOR_EACH (it, blocks) {
240  Block *block = *it;
241  Color c = block->group->mod.GetColor();
242 
243  const std::vector<GLfloat> v =
244  DrawBlock(xx, yy, block->global_z.min, block->global_z.max);
245  verts.insert(verts.end(), v.begin(), v.end());
246 
247  for (unsigned int i = 0; i < 20; i++) {
248  colors.push_back(c.r);
249  colors.push_back(c.g);
250  colors.push_back(c.b);
251  }
252  }
253  }
254  }
255  ++r;
256  }
257 
258  if (verts.size()) {
259  assert(verts.size() % 60 == 0); // should be full of blocks, each with 20 3D vertices
260 
261  glEnableClientState(GL_COLOR_ARRAY);
262 
263  glVertexPointer(3, GL_FLOAT, 0, &verts[0]);
264  glColorPointer(3, GL_FLOAT, 0, &colors[0]);
265 
266  glDrawArrays(GL_QUADS, 0, verts.size() / 3);
267 
268  glDisableClientState(GL_COLOR_ARRAY);
269  }
270 
271  glPopMatrix();
272 }
273 
274 void Stg::Cell::AddBlock(Block *b, unsigned int layer)
275 {
276  assert(b);
277  assert(layer < 2);
278 
279  // printf( "cell %p add block %p vec %u\n", this, b, (unsigned
280  // int)blocks[layer].size() );
281  // printf( " before " );
282  // for( size_t i=0; i<CELLBLOCKRECORD_COUNT; i++ )
283  // printf("(%p,%d)",
284  // cbrecords[layer][i].block,
285  // //cbrecords[layer][i].block->group->mod.Token() : "NULL",
286  // (int)cbrecords[layer][i].used );
287  // puts("");
288 
289  // CellBlockRecord* cbr = &cbrecords[layer][0];
290  // while( cbr->used ) ++cbr;
291 
292  // // bounds check
293  // assert( &cbrecords[layer][0] - cbr < CELLBLOCKRECORD_COUNT *
294  // sizeof(CellBlockRecord*));
295 
296  // // cbr now points to an unused record
297  // cbr->block = b;
298  // cbr->used = true;
299 
300  // printf( " after " );
301  // for( size_t i=0; i<CELLBLOCKRECORD_COUNT; i++ )
302  // printf("(%p,%d)",
303  // cbrecords[layer][i].block,// ?
304  // // cbrecords[layer][i].block->group->mod.Token() : "NULL",
305  // (int)cbrecords[layer][i].used );
306  // puts("");
307 
308  blocks[layer].push_back(b);
309  b->rendered_cells[layer].push_back(this);
310  region->AddBlock();
311 }
312 
313 void Stg::Cell::RemoveBlock(Block *b, unsigned int layer)
314 {
315  assert(b);
316  assert(layer < 2);
317 
318  // printf( "cell %p remove block %p vec %u\n", this, b, (unsigned
319  // int)blocks[layer].size() );
320  // printf( " before " );
321  // for( size_t i=0; i<CELLBLOCKRECORD_COUNT; i++ )
322  // printf("(%p,%d)",
323  // cbrecords[layer][i].block,
324  // //cbrecords[layer][i].block->group->mod.Token() : "NULL",
325  // (int)cbrecords[layer][i].used );
326  // puts("");
327 
328  // // zip along the cbrecords array until we find block b
329  // CellBlockRecord* cbr = &cbrecords[layer][0];
330  // while( cbr->block != b ) ++cbr;
331 
332  // // found check
333  // assert( cbr->block == b );
334  // // bounds check
335  // assert( &cbrecords[layer][0] - cbr < CELLBLOCKRECORD_COUNT *
336  // sizeof(CellBlockRecord*));
337 
338  // // cbr now points to the record for block b: invalidate the record
339  // assert( cbr->block == b );
340 
341  // // mark the cbr as available for reuse
342  // cbr->used = false;
343 
344  // printf( " after " );
345  // for( size_t i=0; i<CELLBLOCKRECORD_COUNT; i++ )
346  // printf("(%p,%d)",
347  // cbrecords[layer][i].block,// ?
348  // // cbrecords[layer][i].block->group->mod.Token() : "NULL",
349  // (int)cbrecords[layer][i].used );
350  // puts("");
351 
352  std::vector<Block *> &blks(blocks[layer]);
353  const size_t len(blks.size());
354  if (len) {
355 #if 0
356  // Use conventional STL style
357 
358  // this special-case test is faster for worlds with simple models,
359  // which are the ones we want to be really fast. It's a small
360  // extra cost for worlds with several models in each cell. It
361  // gives a 5% overall speed increase in fasr.world.
362 
363  if( (blks.size() == 1) &&
364  (blks[0] == b) ) // special but common case
365  {
366  blks.clear(); // cheap
367  }
368  else // the general but relatively expensive case
369  {
370  EraseAll( b, blks );
371  }
372 #else
373  // attempt faster removal loop
374  // O(n) * low constant array element removal
375  // this C-style pointer work looks to be very slightly faster than the STL
376  // way
377  Block **start = &blks[0]; // start of array
378  Block **r = &blks[0]; // read from here
379  Block **w = &blks[0]; // write to here
380 
381  while (r < start + len) // scan down array, skipping 'this'
382  {
383  if (*r != b)
384  *w++ = *r;
385  ++r;
386  }
387  blks.resize(w - start);
388 #endif
389  }
390 
391  region->RemoveBlock();
392 }
float scale
Definition: make_rsn.c:26
std::vector< Block * > blocks[2]
Definition: region.hh:47
double Resolution() const
Definition: stage.hh:1108
double max
largest value in range, initially zero
Definition: stage.hh:412
World class
Definition: stage.hh:764
The Stage library uses its own namespace.
Definition: canvas.hh:8
Color GetColor() const
Definition: stage.hh:2233
const uint32_t SRBITS(RBITS+SBITS)
Model & mod
Definition: stage.hh:1216
void DrawVoxels(unsigned int layer) const
Definition: region.cc:212
Region regions[SUPERREGIONSIZE]
Definition: region.hh:102
void EraseAll(T thing, C &cont)
Definition: stage.hh:584
double min
smallest value in range, initially zero
Definition: stage.hh:410
std::vector< Cell > cells
Definition: region.hh:70
void AddBlock(Block *b, unsigned int index)
Definition: region.cc:274
SuperRegion * superregion
Definition: region.hh:94
void DrawOccupancy(void) const
Definition: region.cc:57
Bounds global_z
z extent in global coordinates.
Definition: stage.hh:1194
void RemoveBlock()
Definition: region.cc:52
void RemoveBlock()
Definition: region.cc:25
double r
Definition: stage.hh:216
const uint32_t RBITS(5)
unsigned long count
Definition: region.hh:100
void RemoveBlock(Block *b, unsigned int index)
Definition: region.cc:313
double b
Definition: stage.hh:216
double g
Definition: stage.hh:216
const int32_t REGIONWIDTH(1<< RBITS)
std::vector< Cell * > rendered_cells[2]
Definition: stage.hh:1199
const int32_t SUPERREGIONSIZE(SUPERREGIONWIDTH *SUPERREGIONWIDTH)
void AddBlock()
Definition: region.cc:19
World * world
Definition: region.hh:103
point_int_t origin
Definition: region.hh:101
#define FOR_EACH(I, C)
Definition: stage.hh:580
void AddBlock()
Definition: region.cc:47
SuperRegion(World *world, point_int_t origin)
Definition: region.cc:36
static const std::vector< GLfloat > DrawBlock(GLfloat x, GLfloat y, GLfloat zmin, GLfloat zmax)
Definition: region.cc:141
unsigned long count
Definition: region.hh:71
BlockGroup * group
The BlockGroup to which this Block belongs.
Definition: stage.hh:1190
const int32_t SUPERREGIONWIDTH(1<< SBITS)


stage
Author(s): Richard Vaughan , Brian Gerkey , Reed Hedges , Andrew Howard , Toby Collett , Pooya Karimian , Jeremy Asher , Alex Couture-Beil , Geoff Biggs , Rich Mattes , Abbas Sadat
autogenerated on Mon Feb 28 2022 23:48:56