00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "nonlinearImager.h"
00016 #include "config_distort.h"
00017
00018 #include "graphicsStateGuardian.h"
00019 #include "matrixLens.h"
00020 #include "graphicsOutput.h"
00021 #include "graphicsEngine.h"
00022 #include "dcast.h"
00023 #include "cPointerCallbackObject.h"
00024 #include "asyncTaskManager.h"
00025 #include "genericAsyncTask.h"
00026
00027
00028
00029
00030
00031
00032 NonlinearImager::
00033 NonlinearImager() {
00034 _engine = (GraphicsEngine *)NULL;
00035 _stale = true;
00036 }
00037
00038
00039
00040
00041
00042
00043 NonlinearImager::
00044 ~NonlinearImager() {
00045 remove_all_screens();
00046 remove_all_viewers();
00047
00048 if (_recompute_task != (AsyncTask *)NULL) {
00049 AsyncTaskManager *task_mgr = AsyncTaskManager::get_global_ptr();
00050 task_mgr->remove(_recompute_task);
00051 }
00052 }
00053
00054
00055
00056
00057
00058
00059
00060
00061 int NonlinearImager::
00062 add_screen(ProjectionScreen *screen) {
00063 return add_screen(NodePath(screen), screen->get_name());
00064 }
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086 int NonlinearImager::
00087 add_screen(const NodePath &screen, const string &name) {
00088 nassertr(!screen.is_empty() &&
00089 screen.node()->is_of_type(ProjectionScreen::get_class_type()), -1);
00090
00091 ProjectionScreen *screen_node = DCAST(ProjectionScreen, screen.node());
00092
00093 _screens.push_back(Screen());
00094 Screen &new_screen = _screens.back();
00095 new_screen._screen = screen;
00096 new_screen._screen_node = screen_node;
00097 new_screen._name = name;
00098 new_screen._buffer = (GraphicsOutput *)NULL;
00099 new_screen._tex_width = 256;
00100 new_screen._tex_height = 256;
00101 new_screen._active = true;
00102
00103
00104 size_t vi;
00105 for (vi = 0; vi < _viewers.size(); ++vi) {
00106 new_screen._meshes.push_back(Mesh());
00107 new_screen._meshes[vi]._last_screen = screen_node->get_last_screen();
00108 }
00109
00110 _stale = true;
00111
00112 if (_dark_room.is_empty()) {
00113 _dark_room = screen.get_top();
00114 } else {
00115 nassertr(_dark_room.is_same_graph(screen), _screens.size() - 1);
00116 }
00117
00118 return _screens.size() - 1;
00119 }
00120
00121
00122
00123
00124
00125
00126
00127
00128 int NonlinearImager::
00129 find_screen(const NodePath &screen) const {
00130 for (size_t i = 0; i < _screens.size(); i++) {
00131 if (_screens[i]._screen == screen) {
00132 return i;
00133 }
00134 }
00135
00136 return -1;
00137 }
00138
00139
00140
00141
00142
00143
00144
00145 void NonlinearImager::
00146 remove_screen(int index) {
00147 nassertv_always(index >= 0 && index < (int)_screens.size());
00148 Screen &screen = _screens[index];
00149 for (size_t vi = 0; vi < screen._meshes.size(); vi++) {
00150 screen._meshes[vi]._mesh.remove_node();
00151 }
00152 _screens.erase(_screens.begin() + index);
00153 }
00154
00155
00156
00157
00158
00159
00160 void NonlinearImager::
00161 remove_all_screens() {
00162 while (!_screens.empty()) {
00163 remove_screen(_screens.size() - 1);
00164 }
00165 }
00166
00167
00168
00169
00170
00171
00172
00173 int NonlinearImager::
00174 get_num_screens() const {
00175 return _screens.size();
00176 }
00177
00178
00179
00180
00181
00182
00183
00184 NodePath NonlinearImager::
00185 get_screen(int index) const {
00186 nassertr(index >= 0 && index < (int)_screens.size(), (ProjectionScreen *)NULL);
00187 return _screens[index]._screen;
00188 }
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198 GraphicsOutput *NonlinearImager::
00199 get_buffer(int index) const {
00200 nassertr(index >= 0 && index < (int)_screens.size(), (GraphicsOutput *)NULL);
00201 return _screens[index]._buffer;
00202 }
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215 void NonlinearImager::
00216 set_texture_size(int index, int width, int height) {
00217 nassertv(index >= 0 && index < (int)_screens.size());
00218
00219 Screen &screen = _screens[index];
00220
00221 screen._tex_width = width;
00222 screen._tex_height = height;
00223
00224 if (screen._buffer != (GraphicsOutput *)NULL) {
00225 bool removed = _engine->remove_window(screen._buffer);
00226 screen._buffer = (GraphicsOutput *)NULL;
00227 nassertv(removed);
00228 }
00229
00230 _stale = true;
00231 }
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243 void NonlinearImager::
00244 set_source_camera(int index, const NodePath &source_camera) {
00245 nassertv(index >= 0 && index < (int)_screens.size());
00246 nassertv(!source_camera.is_empty() &&
00247 source_camera.node()->is_of_type(Camera::get_class_type()));
00248 _screens[index]._source_camera = source_camera;
00249 }
00250
00251
00252
00253
00254
00255
00256
00257
00258 void NonlinearImager::
00259 set_screen_active(int index, bool active) {
00260 nassertv(index >= 0 && index < (int)_screens.size());
00261
00262 Screen &screen = _screens[index];
00263 screen._active = active;
00264
00265 if (!active) {
00266
00267 for (size_t vi = 0; vi < screen._meshes.size(); vi++) {
00268 screen._meshes[vi]._mesh.remove_node();
00269 }
00270
00271
00272 if (screen._buffer != (GraphicsOutput *)NULL) {
00273 bool removed = _engine->remove_window(screen._buffer);
00274 screen._buffer = (GraphicsOutput *)NULL;
00275 nassertv(removed);
00276 }
00277
00278
00279
00280
00281 screen._screen.hide();
00282
00283 } else {
00284
00285 _stale = true;
00286
00287 screen._screen.show();
00288 }
00289 }
00290
00291
00292
00293
00294
00295
00296 bool NonlinearImager::
00297 get_screen_active(int index) const {
00298 nassertr(index >= 0 && index < (int)_screens.size(), false);
00299 return _screens[index]._active;
00300 }
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322 int NonlinearImager::
00323 add_viewer(DisplayRegion *dr) {
00324 GraphicsOutput *window = dr->get_window();
00325 nassertr(window != (GraphicsOutput *)NULL, -1);
00326
00327 GraphicsStateGuardian *gsg = window->get_gsg();
00328 nassertr(gsg != (GraphicsStateGuardian *)NULL, -1);
00329
00330 GraphicsEngine *engine = gsg->get_engine();
00331 nassertr(engine != (GraphicsEngine *)NULL, -1);
00332
00333 nassertr(_viewers.empty() || (engine == _engine), -1);
00334 if (_engine == (GraphicsEngine *)NULL) {
00335 _engine = engine;
00336 }
00337
00338 if (_recompute_task == (AsyncTask *)NULL) {
00339 _recompute_task =
00340 new GenericAsyncTask("nli_recompute", recompute_callback, (void *)this);
00341 AsyncTaskManager *task_mgr = AsyncTaskManager::get_global_ptr();
00342 task_mgr->add(_recompute_task);
00343 }
00344
00345 int previous_vi = find_viewer(dr);
00346 if (previous_vi >= 0) {
00347 return previous_vi;
00348 }
00349
00350 size_t vi = _viewers.size();
00351 _viewers.push_back(Viewer());
00352 Viewer &viewer = _viewers[vi];
00353
00354 viewer._dr = dr;
00355
00356
00357 viewer._viewer = dr->get_camera();
00358 if (viewer._viewer.is_empty()) {
00359 viewer._viewer_node = (LensNode *)NULL;
00360 } else {
00361 viewer._viewer_node = DCAST(LensNode, viewer._viewer.node());
00362 }
00363
00364
00365
00366 viewer._internal_camera = new Camera("internal_camera");
00367 viewer._internal_camera->set_lens(new MatrixLens);
00368 viewer._internal_scene = NodePath("internal_screens");
00369 viewer._internal_camera->set_scene(viewer._internal_scene);
00370
00371 NodePath camera_np = viewer._internal_scene.attach_new_node(viewer._internal_camera);
00372 viewer._dr->set_camera(camera_np);
00373
00374
00375
00376
00377 viewer._internal_scene.set_two_sided(0);
00378
00379
00380 Screens::iterator si;
00381 for (si = _screens.begin(); si != _screens.end(); ++si) {
00382 Screen &screen = (*si);
00383 screen._meshes.push_back(Mesh());
00384 nassertr(screen._meshes.size() == _viewers.size(), -1);
00385 }
00386
00387 _stale = true;
00388
00389 if (_dark_room.is_empty()) {
00390 _dark_room = viewer._viewer.get_top();
00391 } else {
00392 nassertr(_dark_room.is_same_graph(viewer._viewer), vi);
00393 }
00394
00395 return vi;
00396 }
00397
00398
00399
00400
00401
00402
00403
00404
00405 int NonlinearImager::
00406 find_viewer(DisplayRegion *dr) const {
00407 for (size_t vi = 0; vi < _viewers.size(); vi++) {
00408 if (_viewers[vi]._dr == dr) {
00409 return vi;
00410 }
00411 }
00412
00413 return -1;
00414 }
00415
00416
00417
00418
00419
00420
00421
00422 void NonlinearImager::
00423 remove_viewer(int index) {
00424 nassertv_always(index >= 0 && index < (int)_viewers.size());
00425 Viewer &viewer = _viewers[index];
00426 viewer._internal_camera->set_scene(NodePath());
00427 viewer._dr->set_camera(viewer._viewer);
00428
00429
00430 Screens::iterator si;
00431 for (si = _screens.begin(); si != _screens.end(); ++si) {
00432 Screen &screen = (*si);
00433 nassertv(index < (int)screen._meshes.size());
00434 screen._meshes[index]._mesh.remove_node();
00435 screen._meshes.erase(screen._meshes.begin() + index);
00436 }
00437
00438 _viewers.erase(_viewers.begin() + index);
00439 }
00440
00441
00442
00443
00444
00445
00446 void NonlinearImager::
00447 remove_all_viewers() {
00448 while (!_viewers.empty()) {
00449 remove_viewer(_viewers.size() - 1);
00450 }
00451 }
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470 void NonlinearImager::
00471 set_viewer_camera(int index, const NodePath &viewer_camera) {
00472 nassertv(index >= 0 && index < (int)_viewers.size());
00473 nassertv(!viewer_camera.is_empty() &&
00474 viewer_camera.node()->is_of_type(LensNode::get_class_type()));
00475 Viewer &viewer = _viewers[index];
00476 viewer._viewer = viewer_camera;
00477 viewer._viewer_node = DCAST(LensNode, viewer_camera.node());
00478 _stale = true;
00479
00480 if (_dark_room.is_empty()) {
00481 _dark_room = viewer._viewer.get_top();
00482 } else {
00483 nassertv(_dark_room.is_same_graph(viewer._viewer));
00484 }
00485 }
00486
00487
00488
00489
00490
00491
00492
00493 NodePath NonlinearImager::
00494 get_viewer_camera(int index) const {
00495 nassertr(index >= 0 && index < (int)_viewers.size(), NodePath());
00496 return _viewers[index]._viewer;
00497 }
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513 NodePath NonlinearImager::
00514 get_viewer_scene(int index) const {
00515 nassertr(index >= 0 && index < (int)_viewers.size(), NodePath());
00516 return _viewers[index]._internal_scene;
00517 }
00518
00519
00520
00521
00522
00523
00524
00525 int NonlinearImager::
00526 get_num_viewers() const {
00527 return _viewers.size();
00528 }
00529
00530
00531
00532
00533
00534
00535
00536 DisplayRegion *NonlinearImager::
00537 get_viewer(int index) const {
00538 nassertr(index >= 0 && index < (int)_viewers.size(), (DisplayRegion *)NULL);
00539 return _viewers[index]._dr;
00540 }
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558 NodePath NonlinearImager::
00559 get_dark_room() const {
00560 return _dark_room;
00561 }
00562
00563
00564
00565
00566
00567
00568
00569 GraphicsEngine *NonlinearImager::
00570 get_graphics_engine() const {
00571 return _engine;
00572 }
00573
00574
00575
00576
00577
00578
00579 void NonlinearImager::
00580 recompute() {
00581 size_t vi;
00582 for (vi = 0; vi < _viewers.size(); ++vi) {
00583 Viewer &viewer = _viewers[vi];
00584
00585 Screens::iterator si;
00586 for (si = _screens.begin(); si != _screens.end(); ++si) {
00587 Screen &screen = (*si);
00588 if (screen._active) {
00589 recompute_screen(screen, vi);
00590 }
00591 }
00592
00593 if (viewer._viewer_node != (LensNode *)NULL &&
00594 viewer._viewer_node->get_lens() != (Lens *)NULL) {
00595 viewer._viewer_lens_change =
00596 viewer._viewer_node->get_lens()->get_last_change();
00597 }
00598 }
00599
00600 _stale = false;
00601 }
00602
00603
00604
00605
00606
00607
00608
00609 AsyncTask::DoneStatus NonlinearImager::
00610 recompute_callback(GenericAsyncTask *, void *data) {
00611 NonlinearImager *self = (NonlinearImager *)data;
00612 self->recompute_if_stale();
00613 return AsyncTask::DS_cont;
00614 }
00615
00616
00617
00618
00619
00620
00621 void NonlinearImager::
00622 recompute_if_stale() {
00623 if (_stale) {
00624 recompute();
00625 } else {
00626 size_t vi;
00627 for (vi = 0; vi < _viewers.size(); ++vi) {
00628 Viewer &viewer = _viewers[vi];
00629 if (viewer._viewer_node != (LensNode *)NULL) {
00630 UpdateSeq lens_change =
00631 viewer._viewer_node->get_lens()->get_last_change();
00632 if (lens_change != viewer._viewer_lens_change) {
00633
00634
00635 Screens::iterator si;
00636 for (si = _screens.begin(); si != _screens.end(); ++si) {
00637 Screen &screen = (*si);
00638 if (screen._active) {
00639 recompute_screen(screen, vi);
00640 }
00641 }
00642
00643 } else {
00644
00645
00646 Screens::iterator si;
00647 for (si = _screens.begin(); si != _screens.end(); ++si) {
00648 Screen &screen = (*si);
00649 if (screen._active &&
00650 screen._meshes[vi]._last_screen != screen._screen_node->get_last_screen()) {
00651 recompute_screen(screen, vi);
00652 } else {
00653 screen._screen_node->recompute_if_stale(screen._screen);
00654 }
00655 }
00656 }
00657 }
00658 }
00659 }
00660 }
00661
00662
00663
00664
00665
00666
00667
00668 void NonlinearImager::
00669 recompute_screen(NonlinearImager::Screen &screen, size_t vi) {
00670 nassertv(vi < screen._meshes.size());
00671 screen._meshes[vi]._mesh.remove_node();
00672 if (!screen._active) {
00673 return;
00674 }
00675
00676 screen._screen_node->recompute_if_stale(screen._screen);
00677
00678 Viewer &viewer = _viewers[vi];
00679 PT(PandaNode) mesh =
00680 screen._screen_node->make_flat_mesh(screen._screen, viewer._viewer);
00681 if (mesh != (PandaNode *)NULL) {
00682 screen._meshes[vi]._mesh = viewer._internal_scene.attach_new_node(mesh);
00683 }
00684
00685 if (screen._buffer == (GraphicsOutput *)NULL) {
00686 GraphicsOutput *win = viewer._dr->get_window();
00687 GraphicsOutput *buffer = win->make_texture_buffer
00688 (screen._name, screen._tex_width, screen._tex_height, NULL, false);
00689
00690 if (buffer != (GraphicsOutput *)NULL) {
00691 screen._buffer = buffer;
00692 DisplayRegion *dr = buffer->make_display_region();
00693 dr->set_camera(screen._source_camera);
00694
00695 } else {
00696 screen._meshes[vi]._mesh.clear_texture();
00697 }
00698 }
00699
00700 if (screen._buffer != (GraphicsOutput *)NULL) {
00701 screen._meshes[vi]._mesh.set_texture(screen._buffer->get_texture());
00702
00703
00704
00705
00706
00707 screen._screen.set_texture(screen._buffer->get_texture());
00708 }
00709
00710 screen._meshes[vi]._last_screen = screen._screen_node->get_last_screen();
00711 }