blockgroup.cc
Go to the documentation of this file.
1 
2 #include "stage.hh"
3 #include "worldfile.hh"
4 
5 #include <cmath>
6 #include <libgen.h> // for dirname(3)
7 #include <limits.h> // for _POSIX_PATH_MAX
8 #include <limits>
9 
10 using namespace Stg;
11 using namespace std;
12 
13 BlockGroup::BlockGroup(Model &mod) : blocks(), displaylist(0), mod(mod)
14 { /* empty */
15 }
16 
18 {
19  Clear();
20 }
21 
22 void BlockGroup::AppendBlock(const Block &block)
23 {
24  blocks.push_back(block);
25 }
26 
28 {
29  // FOR_EACH( it, blocks )
30  // delete *it;
31 
32  blocks.clear();
33 }
34 
35 void BlockGroup::AppendTouchingModels(std::set<Model *> &v)
36 {
37  FOR_EACH (it, blocks)
38  it->AppendTouchingModels(v);
39 }
40 
42 {
43  Model *hitmod = NULL;
44 
45  FOR_EACH (it, blocks)
46  if ((hitmod = it->TestCollision()))
47  break; // bail on the earliest collision
48 
49  return hitmod; // NULL if no collision
50 }
51 
54 {
55  // assuming the blocks currently fit in a square +/- one billion units
56  double minx, miny, maxx, maxy, minz, maxz;
57  minx = miny = minz = billion;
58  maxx = maxy = maxz = -billion;
59 
60  FOR_EACH (it, blocks) {
61  // examine all the points in the polygon
62  FOR_EACH (pit, it->pts) {
63  if (pit->x < minx)
64  minx = pit->x;
65  if (pit->y < miny)
66  miny = pit->y;
67  if (pit->x > maxx)
68  maxx = pit->x;
69  if (pit->y > maxy)
70  maxy = pit->y;
71  }
72 
73  if (it->local_z.min < minz)
74  minz = it->local_z.min;
75  if (it->local_z.max > maxz)
76  maxz = it->local_z.max;
77  }
78 
79  return bounds3d_t(Bounds(minx, maxx), Bounds(miny, maxy), Bounds(minz, maxz));
80 }
81 
82 // scale all blocks to fit into the bounding box of this group's model
84 {
85  const bounds3d_t b = BoundingBox();
86 
87 // Prevents creating (-)NaNs when dividing by size.{x,y,z}:
88 #define ENSURE_NOT_ZERO(x) \
89  ((std::fabs(x) >= std::numeric_limits<double>::epsilon()) \
90  ? (x) \
91  : std::numeric_limits<double>::epsilon())
92  const Size size(ENSURE_NOT_ZERO(b.x.max - b.x.min), ENSURE_NOT_ZERO(b.y.max - b.y.min),
93  ENSURE_NOT_ZERO(b.z.max - b.z.min));
94 
95  const Size offset(b.x.min + size.x / 2.0, b.y.min + size.y / 2.0, 0);
96 
97  // now scale the blocks to fit in the model's 3d bounding box, so
98  // that the original points are now in model coordinates
99  const Size modsize = mod.geom.size;
100 
101  FOR_EACH (it, blocks) {
102  // polygon edges
103  FOR_EACH (pit, it->pts) {
104  pit->x = (pit->x - offset.x) * (modsize.x / size.x);
105  pit->y = (pit->y - offset.y) * (modsize.y / size.y);
106  }
107 
108  // vertical bounds
109  it->local_z.min = (it->local_z.min - offset.z) * (modsize.z / size.z);
110  it->local_z.max = (it->local_z.max - offset.z) * (modsize.z / size.z);
111  }
112 }
113 
114 void BlockGroup::Map(unsigned int layer)
115 {
116  //static size_t count = 0;
117  //printf( "BlockGroup::Map %lu (%lu)\n", ++count, blocks.size() );
118 
119  FOR_EACH (it, blocks)
120  it->Map(layer);
121 }
122 
123 void BlockGroup::UnMap(unsigned int layer)
124 {
125  //static size_t count = 0;
126  //printf( "BlockGroup::UnMap %lu (%lu)\n", ++count, blocks.size() );
127 
128  FOR_EACH (it, blocks)
129  it->UnMap(layer);
130 
131 
132 }
133 
134 void BlockGroup::DrawSolid(const Geom &geom)
135 {
136  glPushMatrix();
137 
138  Gl::pose_shift(geom.pose);
139 
140  FOR_EACH (it, blocks)
141  it->DrawSolid(false);
142 
143  glPopMatrix();
144 }
145 
147 {
148  FOR_EACH (it, blocks)
149  it->DrawFootPrint();
150 }
151 
152 // tesselation callbacks used in BlockGroup::BuildDisplayListTess()------------
153 
154 static void errorCallback(GLenum errorCode)
155 {
156  const GLubyte *estring;
157 
158  estring = gluErrorString(errorCode);
159  fprintf(stderr, "Tessellation Error: %s\n", estring);
160  exit(0);
161 }
162 
163 static void combineCallback(GLdouble coords[3],
164  GLdouble **, // GLdouble *vertex_data[4],
165  GLfloat *, // GLfloat weight[4],
166  GLdouble **new_vertex)
167 {
168  *new_vertex = new GLdouble[3];
169  memcpy(*new_vertex, coords, 3 * sizeof(GLdouble));
170 
171  // @todo: fix the leak of this vertex buffer. it's not a lot of
172  // data, and doesn't happen much, but it would be tidy.
173 }
174 
175 // render each block as a polygon extruded into Z
177 {
178  static GLUtesselator *tobj = NULL;
179 
180  if (!mod.world->IsGUI())
181  return;
182 
183  if (displaylist == 0) {
184  CalcSize(); // todo: is this redundant? count calls per model to figure this
185  // out.
186 
187  displaylist = glGenLists(1);
188  assert(displaylist != 0);
189 
190  // Stage polygons need not be convex, so we have to tesselate them for
191  // rendering in OpenGL.
192  tobj = gluNewTess();
193  assert(tobj != NULL);
194 
195  // these use the standard GL calls
196  gluTessCallback(tobj, GLU_TESS_VERTEX, (GLvoid(*)()) & glVertex3dv);
197  gluTessCallback(tobj, GLU_TESS_EDGE_FLAG, (GLvoid(*)()) & glEdgeFlag);
198  gluTessCallback(tobj, GLU_TESS_BEGIN, (GLvoid(*)()) & glBegin);
199  gluTessCallback(tobj, GLU_TESS_END, (GLvoid(*)()) & glEnd);
200 
201  // these are custom, defined above.
202  gluTessCallback(tobj, GLU_TESS_ERROR, (GLvoid(*)()) & errorCallback);
203  gluTessCallback(tobj, GLU_TESS_COMBINE, (GLvoid(*)()) & combineCallback);
204  }
205 
206  std::vector<std::vector<GLdouble> > contours;
207 
208  FOR_EACH (blk, blocks) {
209  std::vector<GLdouble> verts;
210  FOR_EACH (it, blk->pts) {
211  verts.push_back(it->x);
212  verts.push_back(it->y);
213  verts.push_back(blk->local_z.max);
214  }
215  contours.push_back(verts);
216  }
217 
218  glNewList(displaylist, GL_COMPILE);
219 
221 
222  // draw filled polys
223  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
224  glEnable(GL_POLYGON_OFFSET_FILL);
225  glPolygonOffset(0.5, 0.5);
226 
228 
229  gluTessBeginPolygon(tobj, NULL);
230 
231  FOR_EACH (contour, contours) {
232  gluTessBeginContour(tobj);
233  for (size_t v = 0; v < contour->size(); v += 3)
234  gluTessVertex(tobj, &(*contour)[v], &(*contour)[v]);
235  gluTessEndContour(tobj);
236  }
237 
238  gluTessEndPolygon(tobj);
239 
240  FOR_EACH (blk, blocks)
241  blk->DrawSides();
242 
243  mod.PopColor();
244 
245  // now outline the polys
246  glDisable(GL_POLYGON_OFFSET_FILL);
247  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
248  glDepthMask(GL_FALSE);
249 
250  Color c = mod.color;
251  c.r /= 2.0;
252  c.g /= 2.0;
253  c.b /= 2.0;
254  mod.PushColor(c);
255 
256  gluTessBeginPolygon(tobj, NULL);
257 
258  FOR_EACH (contour, contours) {
259  gluTessBeginContour(tobj);
260  for (size_t v = 0; v < contour->size(); v += 3)
261  gluTessVertex(tobj, &(*contour)[v], &(*contour)[v]);
262  gluTessEndContour(tobj);
263  }
264 
265  gluTessEndPolygon(tobj);
266 
267  FOR_EACH (blk, blocks)
268  blk->DrawSides();
269 
270  glDepthMask(GL_TRUE);
271  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
272 
273  mod.PopColor();
274 
275  glEndList();
276 }
277 
279 {
280  if (displaylist == 0 || mod.rebuild_displaylist) {
283  }
284 
285  glCallList(displaylist);
286 }
287 
288 void BlockGroup::LoadBlock(Worldfile *wf, int entity)
289 {
290  AppendBlock(Block(this, wf, entity));
291  // CalcSize(); // adjust the blocks so they fit in our bounding box
292 }
293 
294 void BlockGroup::LoadBitmap(const std::string &bitmapfile, Worldfile *wf)
295 {
296  PRINT_DEBUG1("attempting to load bitmap \"%s\n", bitmapfile.c_str());
297 
298  std::string full;
299 
300  if (bitmapfile[0] == '/')
301  full = bitmapfile;
302  else {
303  char *workaround_const = strdup(wf->filename.c_str());
304  full = std::string(dirname(workaround_const)) + "/" + bitmapfile;
305  free(workaround_const);
306  }
307 
308  char buf[512];
309  snprintf(buf, 512, "[Image \"%s\"", bitmapfile.c_str());
310  fputs(buf, stdout);
311  fflush(stdout);
312 
313  PRINT_DEBUG1("attempting to load image %s", full.c_str());
314 
315  Color col(1.0, 0.0, 1.0, 1.0);
316 
317  std::vector<std::vector<point_t> > polys;
318 
319  if (polys_from_image_file(full, polys)) {
320  PRINT_ERR1("failed to load polys from image file \"%s\"", full.c_str());
321  return;
322  }
323 
324  FOR_EACH (it, polys)
325  AppendBlock(Block(this, *it, Bounds(0, 1)));
326 
327  CalcSize();
328 
329  fputs("]", stdout);
330 }
331 
332 void BlockGroup::Rasterize(uint8_t *data, unsigned int width, unsigned int height,
333  meters_t cellwidth, meters_t cellheight)
334 {
335  FOR_EACH (it, blocks)
336  it->Rasterize(data, width, height, cellwidth, cellheight);
337 }
virtual void PushColor(Color col)
Definition: stage.hh:2059
Model class
Definition: stage.hh:1651
void BuildDisplayList()
Definition: blockgroup.cc:176
Bounds y
volume extent along y axis, initially zero
Definition: stage.hh:429
double max
largest value in range, initially zero
Definition: stage.hh:412
void AppendTouchingModels(std::set< Model *> &touchers)
Definition: blockgroup.cc:35
The Stage library uses its own namespace.
Definition: canvas.hh:8
bounds3d_t BoundingBox() const
Definition: blockgroup.cc:53
meters_t x
Definition: stage.hh:243
Model * TestCollision()
Definition: model.cc:661
Model & mod
Definition: stage.hh:1216
Geom geom
Definition: stage.hh:1777
double min
smallest value in range, initially zero
Definition: stage.hh:410
const double billion
Definition: stage.hh:148
Size size
extent
Definition: stage.hh:379
int displaylist
OpenGL displaylist that renders this blockgroup.
Definition: stage.hh:1213
virtual void PopColor()
Definition: stage.hh:2061
void DrawFootPrint(const Geom &geom)
Definition: blockgroup.cc:146
static void errorCallback(GLenum errorCode)
Definition: blockgroup.cc:154
Geom GetGeom() const
Definition: stage.hh:2247
char * dirname(char *path)
Definition: dirname.c:31
double r
Definition: stage.hh:216
static void combineCallback(GLdouble coords[3], GLdouble **, GLfloat *, GLdouble **new_vertex)
Definition: blockgroup.cc:163
std::vector< Block > blocks
Contains the blocks in this group.
Definition: stage.hh:1212
std::string filename
Definition: worldfile.hh:436
Pose pose
position
Definition: stage.hh:378
void LoadBitmap(const std::string &bitmapfile, Worldfile *wf)
Definition: blockgroup.cc:294
double meters_t
Definition: stage.hh:191
meters_t y
Definition: stage.hh:243
void pose_shift(const Pose &pose)
Definition: gl.cc:13
meters_t z
Definition: stage.hh:243
double b
Definition: stage.hh:216
int polys_from_image_file(const std::string &filename, std::vector< std::vector< point_t > > &polys)
rotated rectangle
Definition: stage.cc:86
virtual bool IsGUI() const
Definition: stage.hh:1056
void Map(unsigned int layer)
Definition: blockgroup.cc:114
double g
Definition: stage.hh:216
Bounds x
volume extent along x axis, intially zero
Definition: stage.hh:427
void LoadBlock(Worldfile *wf, int entity)
Definition: blockgroup.cc:288
void Rasterize(uint8_t *data, unsigned int width, unsigned int height, meters_t cellwidth, meters_t cellheight)
Definition: blockgroup.cc:332
BlockGroup(Model &mod)
Definition: blockgroup.cc:13
#define ENSURE_NOT_ZERO(x)
#define PRINT_DEBUG1(m, a)
Definition: stage.hh:645
Bounds z
volume extent along z axis, initially zero
Definition: stage.hh:431
void CallDisplayList()
Definition: blockgroup.cc:278
World * world
Pointer to the world in which this model exists.
Definition: stage.hh:1901
bool rebuild_displaylist
iff true, regenerate block display list before redraw
Definition: stage.hh:1840
#define PRINT_ERR1(m, a)
Definition: stage.hh:591
void UnMap(unsigned int layer)
Definition: blockgroup.cc:123
friend class Block
Definition: stage.hh:1207
void DrawSolid(const Geom &geom)
Definition: blockgroup.cc:134
#define FOR_EACH(I, C)
Definition: stage.hh:580
Model * TestCollision()
Definition: blockgroup.cc:41
Color color
Definition: stage.hh:1753
void AppendBlock(const Block &block)
Definition: blockgroup.cc:22


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:55