block.cc
Go to the documentation of this file.
1 #include "region.hh"
2 #include "worldfile.hh"
3 
4 using namespace Stg;
5 using std::vector;
6 
7 static void canonicalize_winding(vector<point_t>& pts);
8 
9 
14  const std::vector<point_t>& pts,
15  meters_t zmin,
16  meters_t zmax,
17  Color color,
18  bool inherit_color,
19  bool wheel ) :
20  mod( mod ),
21  mpts(),
22  pts(pts),
23  local_z( zmin, zmax ),
24  color( color ),
25  inherit_color( inherit_color ),
26  wheel(wheel),
27  rendered_cells()
28 {
29  assert( mod );
30  canonicalize_winding(this->pts);
31 }
32 
35  Worldfile* wf,
36  int entity)
37  : mod( mod ),
38  mpts(),
39  pts(),
40  local_z(),
41  color(),
42  inherit_color(true),
43  wheel(),
45 {
46  assert(mod);
47  assert(wf);
48  assert(entity);
49 
50  Load( wf, entity );
52 }
53 
55 {
56  if( mapped )
57  {
58  UnMap(0);
59  UnMap(1);
60  }
61 }
62 
63 void Block::Translate( double x, double y )
64 {
65  FOR_EACH( it, pts )
66  {
67  it->x += x;
68  it->y += y;
69  }
70 
72 }
73 
75 {
76  double min = billion;
77  double max = -billion;
78 
79  FOR_EACH( it, pts )
80  {
81  if( it->y > max ) max = it->y;
82  if( it->y < min ) min = it->y;
83  }
84 
85  // return the value half way between max and min
86  return( min + (max - min)/2.0 );
87 }
88 
90 {
91  double min = billion;
92  double max = -billion;
93 
94  FOR_EACH( it, pts )
95  {
96  if( it->x > max ) max = it->x;
97  if( it->x < min ) min = it->x;
98  }
99 
100  // return the value half way between maxx and min
101  return( min + (max - min)/2.0 );
102 }
103 
104 void Block::SetCenter( double x, double y )
105 {
106  // move the block by the distance required to bring its center to
107  // the requested position
108  Translate( x-CenterX(), y-CenterY() );
109 }
110 
111 void Block::SetCenterY( double y )
112 {
113  // move the block by the distance required to bring its center to
114  // the requested position
115  Translate( 0, y-CenterY() );
116 }
117 
118 void Block::SetCenterX( double x )
119 {
120  // move the block by the distance required to bring its center to
121  // the requested position
122  Translate( x-CenterX(), 0 );
123 }
124 
125 void Block::SetZ( double min, double max )
126 {
127  local_z.min = min;
128  local_z.max = max;
129 
130  // force redraw
132 }
133 
135 {
136  return( inherit_color ? mod->color : color );
137 }
138 
139 void Block::AppendTouchingModels( std::set<Model*>& touchers )
140 {
141  unsigned int layer = mod->world->updates % 2;
142 
143  // for every cell we are rendered into
144  FOR_EACH( cell_it, rendered_cells[layer] )
145  // for every block rendered into that cell
146  FOR_EACH( block_it, (*cell_it)->GetBlocks(layer) )
147  {
148  if( !mod->IsRelated( (*block_it)->mod ))
149  touchers.insert( (*block_it)->mod );
150  }
151 }
152 
154 {
155  //printf( "model %s block %p test collision...\n", mod->Token(), this );
156 
157  // find the set of cells we would render into given the current global pose
158  //GenerateCandidateCells();
159 
160  if( mod->vis.obstacle_return )
161  {
162  if ( global_z.min < 0 )
163  return mod->world->GetGround();
164 
165  unsigned int layer = mod->world->updates % 2;
166 
167  // for every cell we may be rendered into
168  FOR_EACH( cell_it, rendered_cells[layer] )
169  {
170  // for every block rendered into that cell
171  FOR_EACH( block_it, (*cell_it)->GetBlocks(layer) )
172  {
173  Block* testblock = *block_it;
174  Model* testmod = testblock->mod;
175 
176  //printf( " testing block %p of model %s\n", testblock, testmod->Token() );
177 
178  // if the tested model is an obstacle and it's not attached to this model
179  if( (testmod != this->mod) &&
180  testmod->vis.obstacle_return &&
181  (!mod->IsRelated( testmod )) &&
182  // also must intersect in the Z range
183  testblock->global_z.min <= global_z.max &&
184  testblock->global_z.max >= global_z.min )
185  {
186  //puts( "HIT");
187  return testmod; // bail immediately with the bad news
188  }
189  }
190  }
191  }
192 
193  //printf( "model %s block %p collision done. no hits.\n", mod->Token(), this );
194  return NULL; // no hit
195 }
196 
197 void Block::Map( unsigned int layer )
198 {
199  // calculate the local coords of the block vertices
200  const size_t pt_count(pts.size());
201 
202  if( mpts.size() == 0 )
203  {
204  // no valid cache of model coord points, so generate them
205  mpts.resize( pts.size() );
206 
207  for( size_t i=0; i<pt_count; ++i )
208  mpts[i] = BlockPointToModelMeters( pts[i] );
209  }
210 
211  // now calculate the global pixel coords of the block vertices
212  const std::vector<point_int_t> gpts = mod->LocalToPixels( mpts );
213 
214  // and render this block's polygon into the world
215  mod->world->MapPoly( gpts, this, layer );
216 
217  // update the block's absolute z bounds at this rendering
218  Pose gpose( mod->GetGlobalPose() );
219  gpose.z += mod->geom.pose.z;
220  double scalez( mod->geom.size.z / mod->blockgroup.GetSize().z );
221  meters_t z = gpose.z - mod->blockgroup.GetOffset().z;
222  global_z.min = (scalez * local_z.min) + z;
223  global_z.max = (scalez * local_z.max) + z;
224 
225  mapped = true;
226 }
227 
228 #include <algorithm>
229 #include <functional>
230 
231 void Block::UnMap( unsigned int layer )
232 {
233  FOR_EACH( it, rendered_cells[layer] )
234  (*it)->RemoveBlock(this, layer );
235 
236  rendered_cells[layer].clear();
237  mapped = false;
238 }
239 
241 {
242  Size bgsize = mod->blockgroup.GetSize();
243  point3_t bgoffset = mod->blockgroup.GetOffset();
244 
245  return point_t( (bpt.x - bgoffset.x) * (mod->geom.size.x/bgsize.x),
246  (bpt.y - bgoffset.y) * (mod->geom.size.y/bgsize.y));
247 }
248 
250 {
251  // this doesn't happen often, so this simple strategy isn't too wasteful
252  mpts.clear();
253 }
254 
255 void swap( int& a, int& b )
256 {
257  int tmp = a;
258  a = b;
259  b = tmp;
260 }
261 
262 void Block::Rasterize( uint8_t* data,
263  unsigned int width,
264  unsigned int height,
265  meters_t cellwidth,
266  meters_t cellheight )
267 {
268  //printf( "rasterize block %p : w: %u h: %u scale %.2f %.2f offset %.2f %.2f\n",
269  // this, width, height, scalex, scaley, offsetx, offsety );
270 
271  const size_t pt_count = pts.size();
272  for( size_t i=0; i<pt_count; ++i )
273  {
274  // convert points from local to model coords
275  point_t mpt1 = BlockPointToModelMeters( pts[i] );
276  point_t mpt2 = BlockPointToModelMeters( pts[(i+1)%pt_count] );
277 
278  // record for debug visualization
279  mod->rastervis.AddPoint( mpt1.x, mpt1.y );
280 
281  // shift to the bottom left of the model
282  mpt1.x += mod->geom.size.x/2.0;
283  mpt1.y += mod->geom.size.y/2.0;
284  mpt2.x += mod->geom.size.x/2.0;
285  mpt2.y += mod->geom.size.y/2.0;
286 
287  // convert from meters to cells
288  point_int_t a( floor( mpt1.x / cellwidth ),
289  floor( mpt1.y / cellheight ));
290  point_int_t b( floor( mpt2.x / cellwidth ),
291  floor( mpt2.y / cellheight ) );
292 
293  bool steep = abs( b.y-a.y ) > abs( b.x-a.x );
294  if( steep )
295  {
296  swap( a.x, a.y );
297  swap( b.x, b.y );
298  }
299 
300  if( a.x > b.x )
301  {
302  swap( a.x, b.x );
303  swap( a.y, b.y );
304  }
305 
306  double dydx = (double) (b.y - a.y) / (double) (b.x - a.x);
307  double y = a.y;
308  for(int x=a.x; x<=b.x; ++x)
309  {
310  if( steep )
311  {
312  if( ! (floor(y) >= 0) ) continue;
313  if( ! (floor(y) < (int)width) ) continue;
314  if( ! (x >= 0) ) continue;
315  if( ! (x < (int)height) ) continue;
316  }
317  else
318  {
319  if( ! (x >= 0) ) continue;
320  if( ! (x < (int)width) ) continue;
321  if( ! (floor(y) >= 0) ) continue;
322  if( ! (floor(y) < (int)height) ) continue;
323  }
324 
325  if( steep )
326  data[ (int)floor(y) + (x * width)] = 1;
327  else
328  data[ x + ((int)floor(y) * width)] = 1;
329  y += dydx;
330  }
331  }
332 }
333 
335 {
336  // draw the top of the block - a polygon at the highest vertical
337  // extent
338  glBegin( GL_POLYGON);
339  FOR_EACH( it, pts )
340  glVertex3f( it->x, it->y, local_z.max );
341  glEnd();
342 }
343 
345 {
346  // construct a strip that wraps around the polygon
347  glBegin(GL_QUAD_STRIP);
348 
349  FOR_EACH( it, pts )
350  {
351  glVertex3f( it->x, it->y, local_z.max );
352  glVertex3f( it->x, it->y, local_z.min );
353  }
354  // close the strip
355  glVertex3f( pts[0].x, pts[0].y, local_z.max );
356  glVertex3f( pts[0].x, pts[0].y, local_z.min );
357  glEnd();
358 }
359 
361 {
362  glBegin(GL_POLYGON);
363  FOR_EACH( it, pts )
364  glVertex2f( it->x, it->y );
365  glEnd();
366 }
367 
368 void Block::DrawSolid( bool topview )
369 {
370  // if( wheel )x
371  // {
372  // glPushMatrix();
373 
374  // glRotatef( 90,0,1,0 );
375  // glRotatef( 90,1,0,0 );
376 
377  // glTranslatef( -local_z.max /2.0, 0, 0 );
378 
379 
380  // GLUquadric* quadric = gluNewQuadric();
381  // gluQuadricDrawStyle( quadric, GLU_FILL );
382  // gluCylinder( quadric, local_z.max, local_z.max, size.x, 16, 16 );
383  // gluDeleteQuadric( quadric );
384 
385  // glPopMatrix();
386  // }
387  // else
388  {
389  if( ! topview )
390  DrawSides();
391 
392  DrawTop();
393  }
394 }
395 
396 void Block::Load( Worldfile* wf, int entity )
397 {
398  const size_t pt_count = wf->ReadInt( entity, "points", 0);
399 
400  char key[128];
401  for( size_t p=0; p<pt_count; ++p )
402  {
403  snprintf(key, sizeof(key), "point[%d]", (int)p );
404 
405  point_t pt( 0, 0 );
406  wf->ReadTuple( entity, key, 0, 2, "ll", &pt.x, &pt.y );
407  pts.push_back( pt );
408  }
409 
410 
411  wf->ReadTuple( entity, "z", 0, 2, "ll", &local_z.min, &local_z.max );
412  //local_z.min = wf->ReadTupleLength( entity, "z", 0, 0.0 );
413  //local_z.max = wf->ReadTupleLength( entity, "z", 1, 1.0 );
414 
415  const std::string& colorstr = wf->ReadString( entity, "color", "" );
416 
417  if( colorstr != "" )
418  {
419  color = Color( colorstr );
420  inherit_color = false;
421  }
422  else
423  inherit_color = true;
424 
425  wheel = wf->ReadInt( entity, "wheel", wheel );
426 }
427 
429 // utility functions to ensure block winding is consistent and matches OpenGL's default
430 
431 static
433 void positivize(radians_t& angle)
434 {
435  while (angle < 0) angle += 2 * M_PI;
436 }
437 
438 static
440 void pi_ize(radians_t& angle)
441 {
442  while (angle < -M_PI) angle += 2 * M_PI;
443  while (M_PI < angle) angle -= 2 * M_PI;
444 }
445 
446 static
449 {
450  radians_t a1 = atan2(v1.y, v1.x);
451  positivize(a1);
452 
453  radians_t a2 = atan2(v2.y, v2.x);
454  positivize(a2);
455 
456  radians_t angle_change = a2 - a1;
457  pi_ize(angle_change);
458 
459  return angle_change;
460 }
461 
462 static
464 vector<point_t> find_vectors(vector<point_t> const& pts)
465 {
466  vector<point_t> vs;
467  assert(2 <= pts.size());
468  for (unsigned i = 0, n = pts.size(); i < n; ++i)
469  {
470  unsigned j = (i + 1) % n;
471  vs.push_back(point_t(pts[j].x - pts[i].x, pts[j].y - pts[i].y));
472  }
473  assert(vs.size() == pts.size());
474  return vs;
475 }
476 
477 static
480 radians_t angles_sum(vector<point_t> const& vs)
481 {
482  radians_t angle_sum = 0;
483  for (unsigned i = 0, n = vs.size(); i < n; ++i)
484  {
485  unsigned j = (i + 1) % n;
486  angle_sum += angle_change(vs[i], vs[j]);
487  }
488  return angle_sum;
489 }
490 
491 static
493 bool is_canonical_winding(vector<point_t> const& ps)
494 {
495  // reuse point_t as vector
496  vector<point_t> vs = find_vectors(ps);
497  radians_t sum = angles_sum(vs);
498  bool bCanon = 0 < sum;
499 
500  return bCanon;
501 }
502 
503 static
507 // Note that a simple line that doubles back on itself has an
508 // angle sum of 0, but that's intrinsic to a line - its winding could
509 // be either way.
510 void canonicalize_winding(vector<point_t>& ps)
511 {
512  if (not is_canonical_winding(ps))
513  {
514  std::reverse(ps.begin(), ps.end());
515  }
516 }
Color color
Definition: stage.hh:1275
Bounds local_z
z extent in local coords
Definition: stage.hh:1274
Model class
Definition: stage.hh:1742
meters_t y
Definition: stage.hh:485
void swap(int &a, int &b)
Definition: block.cc:255
meters_t x
Definition: stage.hh:485
static radians_t angle_change(point_t v1, point_t v2)
util; How much was v1 rotated to get to v2?
Definition: block.cc:448
static bool is_canonical_winding(vector< point_t > const &ps)
Util.
Definition: block.cc:493
void DrawSides()
Definition: block.cc:344
double CenterY()
Definition: block.cc:74
uint64_t updates
the number of simulated time steps executed so far
Definition: stage.hh:912
double max
largest value in range, initially zero
Definition: stage.hh:435
The Stage library uses its own namespace.
Definition: canvas.hh:8
void DrawTop()
Definition: block.cc:334
std::vector< point_t > mpts
cache of this->pts in model coordindates
Definition: stage.hh:1270
meters_t x
Definition: stage.hh:228
Block(Model *mod, const std::vector< point_t > &pts, meters_t zmin, meters_t zmax, Color color, bool inherit_color, bool wheel)
Definition: block.cc:13
const Color & GetColor()
Definition: block.cc:134
const std::string ReadString(int entity, const char *name, const std::string &value)
Definition: worldfile.cc:1376
meters_t z
Definition: stage.hh:485
Geom geom
Definition: stage.hh:1883
double CenterX()
Definition: block.cc:89
int ReadTuple(const int entity, const char *name, const unsigned int first, const unsigned int num, const char *format,...)
Definition: worldfile.cc:1506
double min
smallest value in range, initially zero
Definition: stage.hh:433
const double billion
Definition: stage.hh:145
void Map(unsigned int layer)
Definition: block.cc:197
Size size
extent
Definition: stage.hh:395
bool inherit_color
Definition: stage.hh:1276
void SetCenter(double x, double y)
Definition: block.cc:104
void DrawSolid(bool topview)
Definition: block.cc:368
bool wheel
Definition: stage.hh:1277
meters_t z
location in 3 axes
Definition: stage.hh:251
static void canonicalize_winding(vector< point_t > &pts)
Definition: block.cc:510
void Load(Worldfile *wf, int entity)
Definition: block.cc:396
Bounds global_z
Definition: stage.hh:1283
bool IsRelated(const Model *testmod) const
Definition: model.cc:570
std::vector< point_t > pts
points defining a polygonx
Definition: stage.hh:1272
Pose GetGlobalPose() const
Definition: model.cc:1379
std::vector< point_int_t > LocalToPixels(const std::vector< point_t > &local) const
Definition: model.cc:600
Pose pose
position
Definition: stage.hh:394
void SetCenterY(double y)
Definition: block.cc:111
const Size & GetSize()
Definition: stage.hh:1323
meters_t y
Definition: stage.hh:473
double meters_t
Definition: stage.hh:174
meters_t x
Definition: stage.hh:473
meters_t y
Definition: stage.hh:228
Model * TestCollision()
Definition: block.cc:153
void SetZ(double min, double max)
Definition: block.cc:125
void AppendTouchingModels(std::set< Model * > &touchers)
Definition: block.cc:139
static void pi_ize(radians_t &angle)
util; puts angle into -pi/2, pi/2
Definition: block.cc:440
meters_t z
Definition: stage.hh:228
static vector< point_t > find_vectors(vector< point_t > const &pts)
util; find vectors between adjacent points, pts[next] - pts[cur]
Definition: block.cc:464
void AddPoint(meters_t x, meters_t y)
Definition: model.cc:1156
class Stg::Model::Visibility vis
void Rasterize(uint8_t *data, unsigned int width, unsigned int height, meters_t cellwidth, meters_t cellheight)
Definition: block.cc:262
BlockGroup blockgroup
Definition: stage.hh:1773
Stg::Model::RasterVis rastervis
static void positivize(radians_t &angle)
util; puts angle into [0, 2pi)
Definition: block.cc:433
std::vector< Cell * > rendered_cells[2]
Definition: stage.hh:1291
World * world
Definition: stage.hh:2017
void InvalidateModelPointCache()
Definition: block.cc:249
void Translate(double x, double y)
Definition: block.cc:63
int ReadInt(int entity, const char *name, int value)
Definition: worldfile.cc:1398
static radians_t angles_sum(vector< point_t > const &vs)
Definition: block.cc:480
void SetCenterX(double y)
Definition: block.cc:118
#define FOR_EACH(I, C)
Definition: stage.hh:616
const point3_t & GetOffset()
Definition: stage.hh:1324
~Block()
Definition: block.cc:54
size_t pt_count
the number of points
Definition: stage.hh:1271
Color color
Definition: stage.hh:1859
point_t BlockPointToModelMeters(const point_t &bpt)
Definition: block.cc:240
bool mapped
Definition: stage.hh:1284
void DrawFootPrint()
Definition: block.cc:360
Model * mod
model to which this block belongs
Definition: stage.hh:1269
double radians_t
Definition: stage.hh:177
void MapPoly(const std::vector< point_int_t > &poly, Block *block, unsigned int layer)
Definition: world.cc:1021
void BuildDisplayList(Model *mod)
Definition: blockgroup.cc:146
Model * GetGround()
Definition: stage.hh:1193
void UnMap(unsigned int layer)
Definition: block.cc:231


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 Jun 10 2019 15:06:09