00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "viewport.h"
00036
00037 #include <math.h>
00038
00039 #include "geometry/geometry_2d.h"
00040
00041 #include "perf/perf.h"
00042 #include "wave-glut/glut_2d.h"
00043 #include "wave-glut/wave-glut.h"
00044
00045
00046 namespace view {
00047
00048
00049
00050 Host::~Host(void) throw() { }
00051 Manager::~Manager(void) throw() { }
00052
00053
00054 typedef rect2d_t<float> rectf_t;
00055
00056
00057
00058 struct viewport_record_t {
00059
00060 viewport_record_t(void) throw() { this->clear(); }
00061 void clear(void) throw() {
00062 id = -1;
00063 normalizedRect.clear();
00064 pixelRect.clear();
00065 renderInfo.clear();
00066 host = NULL;
00067 }
00068
00069
00070 int id;
00071 rectf_t normalizedRect;
00072 recti_t pixelRect;
00073 render_info_t renderInfo;
00074 smart_ptr<Host> host;
00075 };
00076
00077
00078 typedef std::vector<viewport_record_t> view_vec_t;
00079
00080
00081
00082 static const float s_epsilon = 1.0e-8;
00083
00084
00085
00086
00087
00088
00089
00090
00091 static void
00092 getPixelRectFromNormalized
00093 (
00094 IN int width,
00095 IN int height,
00096 IN const rectf_t& rf,
00097 OUT recti_t& ri
00098 )
00099 {
00100 ASSERT(width > 0, "bad width: %d", width);
00101 ASSERT(height > 0, "bad height: %d", height);
00102 ASSERT(rf.isValid(), "invalid?");
00103 ASSERT(rf.left >= -s_epsilon && rf.top >= -s_epsilon &&
00104 rf.right <= 1.0 + s_epsilon && rf.bottom <= 1.0 + s_epsilon,
00105 "Malformed input");
00106
00107 ri.left = (int) (rf.left * width + 0.5);
00108 ri.top = (int) (rf.top * height + 0.5);
00109 ri.right = (int) (rf.right * width + 0.5);
00110 ri.bottom = (int) (rf.bottom * height + 0.5);
00111
00112 ASSERT(ri.isValid(), "invalid?");
00113 ASSERT(ri.left >= 0 && ri.right <= width &&
00114 ri.top >= 0 && ri.bottom <= height,
00115 "Malformed output");
00116 }
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126 class Mgr : public Manager {
00127 public:
00128 ~Mgr(void) throw() { }
00129
00130
00131 void initialize(void);
00132
00133
00134 int getViewportCount(void) const { return m_viewports.size(); }
00135 int getOwnerOfCoordinate(IN int x, IN int y,
00136 IN int width, IN int height,
00137 OUT int& ownerX, OUT int& ownerY);
00138 void render(IN int width, IN int height);
00139 bool createViewport(IN int id, IN smart_ptr<Host> host);
00140 bool removeViewport(IN int id);
00141
00142 private:
00143
00144 void updateGeometries(void);
00145 view_vec_t::iterator findViewport(IN int id);
00146
00147
00148 view_vec_t m_viewports;
00149 };
00150
00151
00152
00153 void
00154 Mgr::initialize
00155 (
00156 void
00157 )
00158 {
00159 }
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169 void
00170 Mgr::render
00171 (
00172 IN int width,
00173 IN int height
00174 )
00175 {
00176 perf::Timer timer("view::Manager::render");
00177
00178 ASSERT(width > 0, "bad width: %d", width);
00179 ASSERT(height > 0, "bad height: %d", height);
00180
00181
00182
00183 int oldVP[4];
00184 glGetIntegerv(GL_VIEWPORT, (GLint *) oldVP);
00185
00186
00187 for (view_vec_t::iterator i = m_viewports.begin();
00188 i != m_viewports.end(); ++i) {
00189
00190 viewport_record_t& vr = *i;
00191 render_info_t& ri = vr.renderInfo;
00192 recti_t& rc = vr.pixelRect;
00193
00194 getPixelRectFromNormalized(width, height, vr.normalizedRect,
00195 rc);
00196
00197
00198 ri.width = rc.right - rc.left + 1;
00199 ri.height = rc.bottom - rc.top + 1;
00200 ASSERT(ri.width > 0, "bad viewport width: %d", ri.width);
00201 ASSERT(ri.height > 0, "bad viewport height: %d", ri.height);
00202 }
00203
00204
00205 for (view_vec_t::iterator i = m_viewports.begin();
00206 i != m_viewports.end(); ++i) {
00207
00208 viewport_record_t& vr = *i;
00209 render_info_t& ri = vr.renderInfo;
00210 recti_t& rc = vr.pixelRect;
00211
00212
00213
00214 int oglY = height - rc.bottom;
00215
00216 glViewport(rc.left, oglY, ri.width, ri.height);
00217
00218
00219 ASSERT(vr.host, "null host");
00220 vr.host->render3D(vr.id, vr.renderInfo);
00221 }
00222
00223
00224 glut::push2D(width, height);
00225 for (view_vec_t::iterator i = m_viewports.begin();
00226 i != m_viewports.end(); ++i) {
00227
00228 viewport_record_t& vr = *i;
00229 rectf_t& nr = vr.normalizedRect;
00230 render_info_t& ri = vr.renderInfo;
00231 recti_t& rc = vr.pixelRect;
00232
00233
00234 int oglY = height - rc.bottom;
00235 glViewport(rc.left, oglY, ri.width, ri.height);
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246 glMatrixMode(GL_MODELVIEW);
00247 glPushMatrix();
00248
00249 float xScale = 1.0 / (nr.right - nr.left);
00250 float yScale = 1.0 / (nr.bottom - nr.top);
00251 glScalef(xScale, yScale, 1);
00252
00253
00254 ASSERT(vr.host, "null host");
00255 vr.host->render2D(vr.id, vr.renderInfo);
00256
00257
00258 glMatrixMode(GL_MODELVIEW);
00259 glPopMatrix();
00260 }
00261 glut::pop2D();
00262
00263
00264 glViewport(oldVP[0], oldVP[1], oldVP[2], oldVP[3]);
00265 }
00266
00267
00268
00269 int
00270 Mgr::getOwnerOfCoordinate
00271 (
00272 IN int x,
00273 IN int y,
00274 IN int width,
00275 IN int height,
00276 OUT int& ownerX,
00277 OUT int& ownerY
00278 )
00279 {
00280
00281
00282 ASSERT(width > 0, "bad width: %d", width);
00283 ASSERT(height > 0, "bad height: %d", height);
00284
00285
00286
00287 for (view_vec_t::iterator i = m_viewports.begin();
00288 i != m_viewports.end(); ++i) {
00289
00290 viewport_record_t& vr = *i;
00291
00292 recti_t rc;
00293 getPixelRectFromNormalized(width, height, vr.normalizedRect,
00294 rc);
00295
00296 if (rc.contains(x, y)) {
00297
00298
00299 ownerX = x - rc.left;
00300 ownerY = y - rc.top;
00301
00302 return vr.id;
00303 }
00304 }
00305
00306
00307
00308 return -1;
00309 }
00310
00311
00312
00313 bool
00314 Mgr::createViewport
00315 (
00316 IN int id,
00317 IN smart_ptr<Host> host
00318 )
00319 {
00320 ASSERT(host, "null");
00321
00322
00323
00324
00325 if (id < 1) {
00326 DPRINTF("Invalid id: %d", id);
00327 return false;
00328 }
00329
00330
00331 view_vec_t::iterator i = this->findViewport(id);
00332 if (m_viewports.end() != i) {
00333 DPRINTF("Viewport with id already exists: %d", id);
00334 return false;
00335 }
00336
00337
00338 viewport_record_t vr;
00339 vr.id = id;
00340 vr.host = host;
00341
00342
00343 m_viewports.push_back(vr);
00344
00345
00346 this->updateGeometries();
00347
00348
00349 return true;
00350 }
00351
00352
00353
00354 bool
00355 Mgr::removeViewport
00356 (
00357 IN int id
00358 )
00359 {
00360 view_vec_t::iterator i = this->findViewport(id);
00361 if (m_viewports.end() == i) {
00362 DPRINTF("Viewport ID not found? %d", id);
00363 return false;
00364 }
00365
00366 m_viewports.erase(i);
00367 this->updateGeometries();
00368 return true;
00369 }
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379 void
00380 Mgr::updateGeometries
00381 (
00382 void
00383 )
00384 {
00385
00386
00387
00388
00389
00390
00391
00392 int N = m_viewports.size();
00393 if (!N)
00394 return;
00395
00396
00397 int width = (int) (sqrt(1.0 * N) + 0.5);
00398 ASSERT(width > 0, "bad width: %d", width);
00399
00400
00401 int height = N / width;
00402 if (width * height < N) {
00403 ++height;
00404 }
00405 ASSERT(height > 0, "bad height: %d", height);
00406
00407
00408
00409
00410
00411
00412
00413 if (width * height < N ||
00414 width * (height - 1) >= N) {
00415 ASSERT(false, "bad layout");
00416 }
00417
00418
00419 float dx = 1.0 / width;
00420 float dy = 1.0 / height;
00421
00422
00423 view_vec_t::iterator iv = m_viewports.begin();
00424 for (int j = 0; j < height; ++j) {
00425 for (int i = 0; i < width; ++i) {
00426 if (m_viewports.end() == iv) {
00427 break;
00428 }
00429
00430 viewport_record_t& vr = *iv;
00431 vr.normalizedRect.left = i * dx;
00432 vr.normalizedRect.top = j * dy;
00433 vr.normalizedRect.right = (i + 1) * dx;
00434 vr.normalizedRect.bottom = (j + 1) * dy;
00435
00436
00437
00438
00439 ++iv;
00440 }
00441 }
00442 }
00443
00444
00445
00446 view_vec_t::iterator
00447 Mgr::findViewport
00448 (
00449 IN int id
00450 )
00451 {
00452 ASSERT(id > 0, "Bad id: %d", id);
00453
00454 for (view_vec_t::iterator i = m_viewports.begin();
00455 i != m_viewports.end(); ++i) {
00456 const viewport_record_t& vr = *i;
00457 if (vr.id == id) {
00458 return i;
00459 }
00460 }
00461
00462
00463 return m_viewports.end();
00464 }
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474 smart_ptr<Manager>
00475 Manager::create
00476 (
00477 void
00478 )
00479 {
00480 smart_ptr<Mgr> local = new Mgr;
00481 ASSERT(local, "out of memory");
00482
00483 local->initialize();
00484
00485 return local;
00486 }
00487
00488
00489 };
00490