|
|
@@ -28,31 +28,11 @@
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
// Function: NonlinearImager::Constructor
|
|
|
// Access: Published
|
|
|
-// Description: The NonlinearImager is associated with a particular
|
|
|
-// DisplayRegion when it is created. It will throw away
|
|
|
-// whatever camera is currently associated with the
|
|
|
-// DisplayRegion, and create a speciality camera for
|
|
|
-// itself.
|
|
|
+// Description:
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
NonlinearImager::
|
|
|
-NonlinearImager(DisplayRegion *dr) {
|
|
|
- _dr = dr;
|
|
|
-
|
|
|
- // The internal camera is an identity-matrix camera that simply
|
|
|
- // views the meshes that represent the user's specified camera.
|
|
|
- _internal_camera = new Camera("NonlinearImager");
|
|
|
- _internal_camera->set_lens(new MatrixLens);
|
|
|
- _internal_scene = NodePath("screens");
|
|
|
- _internal_camera->set_scene(_internal_scene);
|
|
|
-
|
|
|
- NodePath camera_np = _internal_scene.attach_new_node(_internal_camera);
|
|
|
- _dr->set_camera(camera_np);
|
|
|
-
|
|
|
- // Enable face culling on the wireframe mesh. This will help us to
|
|
|
- // cull out invalid polygons that result from vertices crossing a
|
|
|
- // singularity (for instance, at the back of a fisheye lens).
|
|
|
- _internal_scene.set_two_sided(0);
|
|
|
-
|
|
|
+NonlinearImager() {
|
|
|
+ _gsg = (GraphicsStateGuardian *)NULL;
|
|
|
_stale = true;
|
|
|
}
|
|
|
|
|
|
@@ -63,9 +43,8 @@ NonlinearImager(DisplayRegion *dr) {
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
NonlinearImager::
|
|
|
~NonlinearImager() {
|
|
|
- _internal_camera->set_scene(NodePath());
|
|
|
- _dr->set_camera(NodePath());
|
|
|
remove_all_screens();
|
|
|
+ remove_all_viewers();
|
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
@@ -79,7 +58,7 @@ NonlinearImager::
|
|
|
//
|
|
|
// width and height indicate the size of the texture
|
|
|
// that will be created to render the scene for the
|
|
|
-// screen. See set_size().
|
|
|
+// screen. See set_texture_size().
|
|
|
//
|
|
|
// Each ProjectionScreen object should already have some
|
|
|
// screen geometry created.
|
|
|
@@ -101,9 +80,15 @@ add_screen(ProjectionScreen *screen) {
|
|
|
new_screen._texture = (Texture *)NULL;
|
|
|
new_screen._tex_width = 256;
|
|
|
new_screen._tex_height = 256;
|
|
|
- new_screen._last_screen = screen->get_last_screen();
|
|
|
new_screen._active = true;
|
|
|
|
|
|
+ // Slot a mesh for each viewer.
|
|
|
+ size_t vi;
|
|
|
+ for (vi = 0; vi < _viewers.size(); ++vi) {
|
|
|
+ new_screen._meshes.push_back(Mesh());
|
|
|
+ new_screen._meshes[vi]._last_screen = screen->get_last_screen();
|
|
|
+ }
|
|
|
+
|
|
|
_stale = true;
|
|
|
return _screens.size() - 1;
|
|
|
}
|
|
|
@@ -136,7 +121,9 @@ void NonlinearImager::
|
|
|
remove_screen(int index) {
|
|
|
nassertv_always(index >= 0 && index < (int)_screens.size());
|
|
|
Screen &screen = _screens[index];
|
|
|
- screen._mesh.remove_node();
|
|
|
+ for (size_t vi = 0; vi < screen._meshes.size(); vi++) {
|
|
|
+ screen._meshes[vi]._mesh.remove_node();
|
|
|
+ }
|
|
|
_screens.erase(_screens.begin() + index);
|
|
|
}
|
|
|
|
|
|
@@ -147,13 +134,9 @@ remove_screen(int index) {
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
void NonlinearImager::
|
|
|
remove_all_screens() {
|
|
|
- Screens::iterator si;
|
|
|
- for (si = _screens.begin(); si != _screens.end(); ++si) {
|
|
|
- Screen &screen = (*si);
|
|
|
- screen._mesh.remove_node();
|
|
|
+ while (!_screens.empty()) {
|
|
|
+ remove_screen(_screens.size() - 1);
|
|
|
}
|
|
|
-
|
|
|
- _screens.clear();
|
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
@@ -180,7 +163,7 @@ get_screen(int index) const {
|
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
-// Function: NonlinearImager::set_size
|
|
|
+// Function: NonlinearImager::set_texture_size
|
|
|
// Access: Published
|
|
|
// Description: Sets the width and height of the texture used to
|
|
|
// render the scene for the indicated screen. This must
|
|
|
@@ -191,7 +174,7 @@ get_screen(int index) const {
|
|
|
// detail of the rendered scene.
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
void NonlinearImager::
|
|
|
-set_size(int index, int width, int height) {
|
|
|
+set_texture_size(int index, int width, int height) {
|
|
|
nassertv(index >= 0 && index < (int)_screens.size());
|
|
|
_screens[index]._tex_width = width;
|
|
|
_screens[index]._tex_height = height;
|
|
|
@@ -216,21 +199,23 @@ set_source_camera(int index, const NodePath &source_camera) {
|
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
-// Function: NonlinearImager::set_active
|
|
|
+// Function: NonlinearImager::set_screen_active
|
|
|
// Access: Published
|
|
|
// Description: Sets the active flag on the indicated screen. If the
|
|
|
// active flag is true, the screen will be used;
|
|
|
// otherwise, it will not appear.
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
void NonlinearImager::
|
|
|
-set_active(int index, bool active) {
|
|
|
+set_screen_active(int index, bool active) {
|
|
|
nassertv(index >= 0 && index < (int)_screens.size());
|
|
|
_screens[index]._active = active;
|
|
|
|
|
|
if (!active) {
|
|
|
Screen &screen = _screens[index];
|
|
|
- // If we've just made this screen inactive, remove its mesh.
|
|
|
- screen._mesh.remove_node();
|
|
|
+ // If we've just made this screen inactive, remove its meshes.
|
|
|
+ for (size_t vi = 0; vi < screen._meshes.size(); vi++) {
|
|
|
+ screen._meshes[vi]._mesh.remove_node();
|
|
|
+ }
|
|
|
screen._texture.clear();
|
|
|
} else {
|
|
|
// If we've just made it active, it needs to be recomputed.
|
|
|
@@ -239,18 +224,147 @@ set_active(int index, bool active) {
|
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
-// Function: NonlinearImager::get_active
|
|
|
+// Function: NonlinearImager::get_screen_active
|
|
|
// Access: Published
|
|
|
// Description: Returns the active flag on the indicated screen.
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
bool NonlinearImager::
|
|
|
-get_active(int index) const {
|
|
|
+get_screen_active(int index) const {
|
|
|
nassertr(index >= 0 && index < (int)_screens.size(), false);
|
|
|
return _screens[index]._active;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: NonlinearImager::add_viewer
|
|
|
+// Access: Published
|
|
|
+// Description: Adds the indicated DisplayRegion as a viewer into the
|
|
|
+// NonlinearImager room. The camera associated with the
|
|
|
+// DisplayRegion at the time add_viewer() is called is
|
|
|
+// used as the initial viewer camera; it may have a
|
|
|
+// nonlinear lens, like a fisheye or cylindrical lens.
|
|
|
+//
|
|
|
+// This sets up a special scene graph for this
|
|
|
+// DisplayRegion alone and sets up the DisplayRegion
|
|
|
+// with a specialty camera. If future changes to the
|
|
|
+// camera are desired, you should use the
|
|
|
+// set_viewer_camera() interface.
|
|
|
+//
|
|
|
+// All viewers must share the same
|
|
|
+// GraphicsStateGuardian.
|
|
|
+//
|
|
|
+// The return value is the index of the new viewer.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+int NonlinearImager::
|
|
|
+add_viewer(DisplayRegion *dr) {
|
|
|
+ GraphicsWindow *win = dr->get_window();
|
|
|
+ GraphicsStateGuardian *gsg = win->get_gsg();
|
|
|
+ nassertr(_viewers.empty() || gsg == _gsg, -1);
|
|
|
+ _gsg = gsg;
|
|
|
+
|
|
|
+ int previous_vi = find_viewer(dr);
|
|
|
+ if (previous_vi >= 0) {
|
|
|
+ return previous_vi;
|
|
|
+ }
|
|
|
+
|
|
|
+ size_t vi = _viewers.size();
|
|
|
+ _viewers.push_back(Viewer());
|
|
|
+ Viewer &viewer = _viewers[vi];
|
|
|
+
|
|
|
+ viewer._dr = dr;
|
|
|
+
|
|
|
+ // Get the current camera off of the DisplayRegion, if any.
|
|
|
+ viewer._viewer = dr->get_camera();
|
|
|
+ if (viewer._viewer.is_empty()) {
|
|
|
+ viewer._viewer_node = (LensNode *)NULL;
|
|
|
+ } else {
|
|
|
+ viewer._viewer_node = DCAST(LensNode, viewer._viewer.node());
|
|
|
+ }
|
|
|
+
|
|
|
+ // The internal camera is an identity-matrix camera that simply
|
|
|
+ // views the meshes that represent the user's specified camera.
|
|
|
+ viewer._internal_camera = new Camera("NonlinearImager");
|
|
|
+ viewer._internal_camera->set_lens(new MatrixLens);
|
|
|
+ viewer._internal_scene = NodePath("screens");
|
|
|
+ viewer._internal_camera->set_scene(viewer._internal_scene);
|
|
|
+
|
|
|
+ NodePath camera_np = viewer._internal_scene.attach_new_node(viewer._internal_camera);
|
|
|
+ viewer._dr->set_camera(camera_np);
|
|
|
+
|
|
|
+ // Enable face culling on the wireframe mesh. This will help us to
|
|
|
+ // cull out invalid polygons that result from vertices crossing a
|
|
|
+ // singularity (for instance, at the back of a fisheye lens).
|
|
|
+ viewer._internal_scene.set_two_sided(0);
|
|
|
+
|
|
|
+ // Finally, slot a new mesh for each screen.
|
|
|
+ Screens::iterator si;
|
|
|
+ for (si = _screens.begin(); si != _screens.end(); ++si) {
|
|
|
+ Screen &screen = (*si);
|
|
|
+ screen._meshes.push_back(Mesh());
|
|
|
+ nassertr(screen._meshes.size() == _viewers.size(), -1);
|
|
|
+ }
|
|
|
+
|
|
|
+ _stale = true;
|
|
|
+ return vi;
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: NonlinearImager::find_viewer
|
|
|
+// Access: Published
|
|
|
+// Description: Returns the index number of the indicated
|
|
|
+// DisplayRegion within the list of viewers, or -1 if it
|
|
|
+// is not found.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+int NonlinearImager::
|
|
|
+find_viewer(DisplayRegion *dr) const {
|
|
|
+ for (size_t vi = 0; vi < _viewers.size(); vi++) {
|
|
|
+ if (_viewers[vi]._dr == dr) {
|
|
|
+ return vi;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return -1;
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: NonlinearImager::remove_viewer
|
|
|
+// Access: Published
|
|
|
+// Description: Removes the viewer with the indicated index number
|
|
|
+// from the imager.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+void NonlinearImager::
|
|
|
+remove_viewer(int index) {
|
|
|
+ nassertv_always(index >= 0 && index < (int)_viewers.size());
|
|
|
+ Viewer &viewer = _viewers[index];
|
|
|
+ viewer._internal_camera->set_scene(NodePath());
|
|
|
+ viewer._dr->set_camera(viewer._viewer);
|
|
|
+
|
|
|
+ // Also remove the corresponding mesh from each screen.
|
|
|
+ Screens::iterator si;
|
|
|
+ for (si = _screens.begin(); si != _screens.end(); ++si) {
|
|
|
+ Screen &screen = (*si);
|
|
|
+ nassertv(index < (int)screen._meshes.size());
|
|
|
+ screen._meshes[index]._mesh.remove_node();
|
|
|
+ screen._meshes.erase(screen._meshes.begin() + index);
|
|
|
+ }
|
|
|
+
|
|
|
+ _viewers.erase(_viewers.begin() + index);
|
|
|
+}
|
|
|
+
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
-// Function: NonlinearImager::set_viewer
|
|
|
+// Function: NonlinearImager::remove_all_viewers
|
|
|
+// Access: Published
|
|
|
+// Description: Removes all viewers from the imager.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+void NonlinearImager::
|
|
|
+remove_all_viewers() {
|
|
|
+ while (!_viewers.empty()) {
|
|
|
+ remove_viewer(_viewers.size() - 1);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: NonlinearImager::set_viewer_camera
|
|
|
// Access: Published
|
|
|
// Description: Specifies the LensNode that is to serve as the
|
|
|
// viewer for this screen. The relative position of
|
|
|
@@ -259,16 +373,70 @@ get_active(int index) const {
|
|
|
// determines the UV's that will be assigned to the
|
|
|
// geometry within the NonlinearImager.
|
|
|
//
|
|
|
+// It is not necessary to call this except to change the
|
|
|
+// camera after a viewer has been added, since the
|
|
|
+// default is to use whatever camera is associated with
|
|
|
+// the DisplayRegion at the time the viewer is added.
|
|
|
+//
|
|
|
// The NodePath must refer to a LensNode (or a Camera).
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
void NonlinearImager::
|
|
|
-set_viewer(const NodePath &viewer) {
|
|
|
- _viewer_node = (LensNode *)NULL;
|
|
|
- _viewer = viewer;
|
|
|
+set_viewer_camera(int index, const NodePath &viewer_camera) {
|
|
|
+ nassertv(index >= 0 && index < (int)_viewers.size());
|
|
|
+ nassertv(!viewer_camera.is_empty() &&
|
|
|
+ viewer_camera.node()->is_of_type(LensNode::get_class_type()));
|
|
|
+ Viewer &viewer = _viewers[index];
|
|
|
+ viewer._viewer = viewer_camera;
|
|
|
+ viewer._viewer_node = DCAST(LensNode, viewer_camera.node());
|
|
|
_stale = true;
|
|
|
- nassertv(!viewer.is_empty() &&
|
|
|
- viewer.node()->is_of_type(LensNode::get_class_type()));
|
|
|
- _viewer_node = DCAST(LensNode, viewer.node());
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: NonlinearImager::get_viewer_camera
|
|
|
+// Access: Published
|
|
|
+// Description: Returns the NodePath to the LensNode that is to serve
|
|
|
+// as nth viewer for this screen.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+NodePath NonlinearImager::
|
|
|
+get_viewer_camera(int index) const {
|
|
|
+ nassertr(index >= 0 && index < (int)_viewers.size(), NodePath());
|
|
|
+ return _viewers[index]._viewer;
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: NonlinearImager::get_internal_scene
|
|
|
+// Access: Published
|
|
|
+// Description: Returns a pointer to the root node of the internal
|
|
|
+// scene graph for the nth viewer, which is used to
|
|
|
+// render all of the screen meshes for this viewer.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+NodePath NonlinearImager::
|
|
|
+get_internal_scene(int index) const {
|
|
|
+ nassertr(index >= 0 && index < (int)_viewers.size(), NodePath());
|
|
|
+ return _viewers[index]._internal_scene;
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: NonlinearImager::get_num_viewers
|
|
|
+// Access: Published
|
|
|
+// Description: Returns the number of viewers that have been added to
|
|
|
+// the imager.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+int NonlinearImager::
|
|
|
+get_num_viewers() const {
|
|
|
+ return _viewers.size();
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: NonlinearImager::get_viewer
|
|
|
+// Access: Published
|
|
|
+// Description: Returns the nth viewer's DisplayRegion that has been
|
|
|
+// added to the imager.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+DisplayRegion *NonlinearImager::
|
|
|
+get_viewer(int index) const {
|
|
|
+ nassertr(index >= 0 && index < (int)_viewers.size(), (DisplayRegion *)NULL);
|
|
|
+ return _viewers[index]._dr;
|
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
@@ -278,17 +446,31 @@ set_viewer(const NodePath &viewer) {
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
void NonlinearImager::
|
|
|
recompute() {
|
|
|
+ // First, force all the textures to clear.
|
|
|
Screens::iterator si;
|
|
|
for (si = _screens.begin(); si != _screens.end(); ++si) {
|
|
|
- if ((*si)._active) {
|
|
|
- recompute_screen(*si);
|
|
|
- }
|
|
|
+ Screen &screen = (*si);
|
|
|
+ screen._texture.clear();
|
|
|
}
|
|
|
|
|
|
- if (_viewer_node != (LensNode *)NULL &&
|
|
|
- _viewer_node->get_lens() != (Lens *)NULL) {
|
|
|
- _viewer_lens_change = _viewer_node->get_lens()->get_last_change();
|
|
|
+ size_t vi;
|
|
|
+ for (vi = 0; vi < _viewers.size(); ++vi) {
|
|
|
+ Viewer &viewer = _viewers[vi];
|
|
|
+
|
|
|
+ for (si = _screens.begin(); si != _screens.end(); ++si) {
|
|
|
+ Screen &screen = (*si);
|
|
|
+ if (screen._active) {
|
|
|
+ recompute_screen(screen, vi);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (viewer._viewer_node != (LensNode *)NULL &&
|
|
|
+ viewer._viewer_node->get_lens() != (Lens *)NULL) {
|
|
|
+ viewer._viewer_lens_change =
|
|
|
+ viewer._viewer_node->get_lens()->get_last_change();
|
|
|
+ }
|
|
|
}
|
|
|
+
|
|
|
_stale = false;
|
|
|
}
|
|
|
|
|
|
@@ -321,20 +503,37 @@ render(GraphicsEngine *engine) {
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
void NonlinearImager::
|
|
|
recompute_if_stale() {
|
|
|
- if (_viewer_node != (LensNode *)NULL &&
|
|
|
- _viewer_node->get_lens() != (Lens *)NULL) {
|
|
|
- UpdateSeq lens_change = _viewer_node->get_lens()->get_last_change();
|
|
|
- if (_stale || lens_change != _viewer_lens_change) {
|
|
|
- recompute();
|
|
|
- } else {
|
|
|
- // We're not overall stale, but maybe we need to recompute one
|
|
|
- // or more of our screens.
|
|
|
- Screens::iterator si;
|
|
|
- for (si = _screens.begin(); si != _screens.end(); ++si) {
|
|
|
- Screen &screen = (*si);
|
|
|
- if (screen._active &&
|
|
|
- screen._last_screen != screen._screen->get_last_screen()) {
|
|
|
- recompute_screen(screen);
|
|
|
+ if (_stale) {
|
|
|
+ recompute();
|
|
|
+ } else {
|
|
|
+ size_t vi;
|
|
|
+ for (vi = 0; vi < _viewers.size(); ++vi) {
|
|
|
+ Viewer &viewer = _viewers[vi];
|
|
|
+ if (viewer._viewer_node != (LensNode *)NULL) {
|
|
|
+ UpdateSeq lens_change =
|
|
|
+ viewer._viewer_node->get_lens()->get_last_change();
|
|
|
+ if (lens_change != viewer._viewer_lens_change) {
|
|
|
+ // The viewer has changed, so we need to recompute all screens
|
|
|
+ // on this viewer.
|
|
|
+ Screens::iterator si;
|
|
|
+ for (si = _screens.begin(); si != _screens.end(); ++si) {
|
|
|
+ Screen &screen = (*si);
|
|
|
+ if (screen._active) {
|
|
|
+ recompute_screen(screen, vi);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ } else {
|
|
|
+ // We may not need to recompute all screens, but maybe some of
|
|
|
+ // them.
|
|
|
+ Screens::iterator si;
|
|
|
+ for (si = _screens.begin(); si != _screens.end(); ++si) {
|
|
|
+ Screen &screen = (*si);
|
|
|
+ if (screen._active &&
|
|
|
+ screen._meshes[vi]._last_screen != screen._screen->get_last_screen()) {
|
|
|
+ recompute_screen(screen, vi);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -348,28 +547,36 @@ recompute_if_stale() {
|
|
|
// screen.
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
void NonlinearImager::
|
|
|
-recompute_screen(NonlinearImager::Screen &screen) {
|
|
|
- screen._mesh.remove_node();
|
|
|
- screen._texture.clear();
|
|
|
- if (_viewer_node == (LensNode *)NULL || !screen._active) {
|
|
|
- // Not much we can do without a viewer.
|
|
|
+recompute_screen(NonlinearImager::Screen &screen, size_t vi) {
|
|
|
+ nassertv(vi < screen._meshes.size());
|
|
|
+ screen._meshes[vi]._mesh.remove_node();
|
|
|
+ if (!screen._active) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- PT(PandaNode) mesh = screen._screen->make_flat_mesh(_viewer);
|
|
|
- screen._mesh = _internal_scene.attach_new_node(mesh);
|
|
|
+ Viewer &viewer = _viewers[vi];
|
|
|
+ PT(PandaNode) mesh = screen._screen->make_flat_mesh(viewer._viewer);
|
|
|
+ if (mesh != (PandaNode *)NULL) {
|
|
|
+ screen._meshes[vi]._mesh = viewer._internal_scene.attach_new_node(mesh);
|
|
|
+ }
|
|
|
|
|
|
- PT(Texture) texture = new Texture;
|
|
|
- texture->set_minfilter(Texture::FT_linear);
|
|
|
- texture->set_magfilter(Texture::FT_linear);
|
|
|
- texture->set_wrapu(Texture::WM_clamp);
|
|
|
- texture->set_wrapv(Texture::WM_clamp);
|
|
|
- texture->_pbuffer->set_xsize(screen._tex_width);
|
|
|
- texture->_pbuffer->set_ysize(screen._tex_height);
|
|
|
+ if (screen._texture == (Texture *)NULL ||
|
|
|
+ screen._texture->_pbuffer == (PixelBuffer *)NULL ||
|
|
|
+ screen._texture->_pbuffer->get_xsize() != screen._tex_width ||
|
|
|
+ screen._texture->_pbuffer->get_ysize() != screen._tex_height) {
|
|
|
+ PT(Texture) texture = new Texture;
|
|
|
+ texture->set_minfilter(Texture::FT_linear);
|
|
|
+ texture->set_magfilter(Texture::FT_linear);
|
|
|
+ texture->set_wrapu(Texture::WM_clamp);
|
|
|
+ texture->set_wrapv(Texture::WM_clamp);
|
|
|
+ texture->_pbuffer->set_xsize(screen._tex_width);
|
|
|
+ texture->_pbuffer->set_ysize(screen._tex_height);
|
|
|
+
|
|
|
+ screen._texture = texture;
|
|
|
+ }
|
|
|
|
|
|
- screen._texture = texture;
|
|
|
- screen._mesh.set_texture(texture);
|
|
|
- screen._last_screen = screen._screen->get_last_screen();
|
|
|
+ screen._meshes[vi]._mesh.set_texture(screen._texture);
|
|
|
+ screen._meshes[vi]._last_screen = screen._screen->get_last_screen();
|
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
@@ -387,24 +594,23 @@ render_screen(GraphicsEngine *engine, NonlinearImager::Screen &screen) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- // Got to update this to new scene graph.
|
|
|
- GraphicsStateGuardian *gsg = _dr->get_window()->get_gsg();
|
|
|
+ nassertv(_gsg != (GraphicsStateGuardian *)NULL);
|
|
|
|
|
|
// Make a display region of the proper size and clear it to prepare for
|
|
|
// rendering the scene.
|
|
|
PT(DisplayRegion) scratch_region =
|
|
|
- gsg->get_window()->make_scratch_display_region(screen._tex_width, screen._tex_height);
|
|
|
+ _gsg->get_window()->make_scratch_display_region(screen._tex_width, screen._tex_height);
|
|
|
scratch_region->set_camera(screen._source_camera);
|
|
|
|
|
|
- gsg->clear(gsg->get_render_buffer(RenderBuffer::T_back |
|
|
|
- RenderBuffer::T_depth),
|
|
|
- scratch_region);
|
|
|
- engine->render_subframe(gsg, scratch_region);
|
|
|
+ _gsg->clear(_gsg->get_render_buffer(RenderBuffer::T_back |
|
|
|
+ RenderBuffer::T_depth),
|
|
|
+ scratch_region);
|
|
|
+ engine->render_subframe(_gsg, scratch_region);
|
|
|
|
|
|
// Copy the results of the render from the frame buffer into the
|
|
|
// screen's texture.
|
|
|
- screen._texture->copy(gsg, scratch_region,
|
|
|
- gsg->get_render_buffer(RenderBuffer::T_back));
|
|
|
+ screen._texture->copy(_gsg, scratch_region,
|
|
|
+ _gsg->get_render_buffer(RenderBuffer::T_back));
|
|
|
|
|
|
// It might be nice if we didn't throw away the scratch region every
|
|
|
// time, which prevents us from preserving cull state from one frame
|