mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 10:54:24 -04:00
support multiple viewers
This commit is contained in:
parent
99413ba1b3
commit
df65deb57f
@ -16,27 +16,3 @@
|
|||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: NonlinearImager::get_viewer
|
|
||||||
// Access: Published
|
|
||||||
// Description: Returns the NodePath to the LensNode that is to serve
|
|
||||||
// as the viewer for this screen, or empty if no
|
|
||||||
// viewer is associated.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
INLINE const NodePath &NonlinearImager::
|
|
||||||
get_viewer() const {
|
|
||||||
return _viewer;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: NonlinearImager::get_internal_scene
|
|
||||||
// Access: Published
|
|
||||||
// Description: Returns a pointer to the root node of the internal
|
|
||||||
// scene graph, which is used to render all of the
|
|
||||||
// screen meshes.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
INLINE NodePath NonlinearImager::
|
|
||||||
get_internal_scene() const {
|
|
||||||
return _internal_scene;
|
|
||||||
}
|
|
||||||
|
@ -28,31 +28,11 @@
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: NonlinearImager::Constructor
|
// Function: NonlinearImager::Constructor
|
||||||
// Access: Published
|
// Access: Published
|
||||||
// Description: The NonlinearImager is associated with a particular
|
// Description:
|
||||||
// DisplayRegion when it is created. It will throw away
|
|
||||||
// whatever camera is currently associated with the
|
|
||||||
// DisplayRegion, and create a speciality camera for
|
|
||||||
// itself.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
NonlinearImager::
|
NonlinearImager::
|
||||||
NonlinearImager(DisplayRegion *dr) {
|
NonlinearImager() {
|
||||||
_dr = dr;
|
_gsg = (GraphicsStateGuardian *)NULL;
|
||||||
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
_stale = true;
|
_stale = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,9 +43,8 @@ NonlinearImager(DisplayRegion *dr) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
NonlinearImager::
|
NonlinearImager::
|
||||||
~NonlinearImager() {
|
~NonlinearImager() {
|
||||||
_internal_camera->set_scene(NodePath());
|
|
||||||
_dr->set_camera(NodePath());
|
|
||||||
remove_all_screens();
|
remove_all_screens();
|
||||||
|
remove_all_viewers();
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -79,7 +58,7 @@ NonlinearImager::
|
|||||||
//
|
//
|
||||||
// width and height indicate the size of the texture
|
// width and height indicate the size of the texture
|
||||||
// that will be created to render the scene for the
|
// 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
|
// Each ProjectionScreen object should already have some
|
||||||
// screen geometry created.
|
// screen geometry created.
|
||||||
@ -101,9 +80,15 @@ add_screen(ProjectionScreen *screen) {
|
|||||||
new_screen._texture = (Texture *)NULL;
|
new_screen._texture = (Texture *)NULL;
|
||||||
new_screen._tex_width = 256;
|
new_screen._tex_width = 256;
|
||||||
new_screen._tex_height = 256;
|
new_screen._tex_height = 256;
|
||||||
new_screen._last_screen = screen->get_last_screen();
|
|
||||||
new_screen._active = true;
|
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;
|
_stale = true;
|
||||||
return _screens.size() - 1;
|
return _screens.size() - 1;
|
||||||
}
|
}
|
||||||
@ -136,7 +121,9 @@ void NonlinearImager::
|
|||||||
remove_screen(int index) {
|
remove_screen(int index) {
|
||||||
nassertv_always(index >= 0 && index < (int)_screens.size());
|
nassertv_always(index >= 0 && index < (int)_screens.size());
|
||||||
Screen &screen = _screens[index];
|
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);
|
_screens.erase(_screens.begin() + index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,13 +134,9 @@ remove_screen(int index) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void NonlinearImager::
|
void NonlinearImager::
|
||||||
remove_all_screens() {
|
remove_all_screens() {
|
||||||
Screens::iterator si;
|
while (!_screens.empty()) {
|
||||||
for (si = _screens.begin(); si != _screens.end(); ++si) {
|
remove_screen(_screens.size() - 1);
|
||||||
Screen &screen = (*si);
|
|
||||||
screen._mesh.remove_node();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_screens.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -180,7 +163,7 @@ get_screen(int index) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: NonlinearImager::set_size
|
// Function: NonlinearImager::set_texture_size
|
||||||
// Access: Published
|
// Access: Published
|
||||||
// Description: Sets the width and height of the texture used to
|
// Description: Sets the width and height of the texture used to
|
||||||
// render the scene for the indicated screen. This must
|
// render the scene for the indicated screen. This must
|
||||||
@ -191,7 +174,7 @@ get_screen(int index) const {
|
|||||||
// detail of the rendered scene.
|
// detail of the rendered scene.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void NonlinearImager::
|
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());
|
nassertv(index >= 0 && index < (int)_screens.size());
|
||||||
_screens[index]._tex_width = width;
|
_screens[index]._tex_width = width;
|
||||||
_screens[index]._tex_height = height;
|
_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
|
// Access: Published
|
||||||
// Description: Sets the active flag on the indicated screen. If the
|
// Description: Sets the active flag on the indicated screen. If the
|
||||||
// active flag is true, the screen will be used;
|
// active flag is true, the screen will be used;
|
||||||
// otherwise, it will not appear.
|
// otherwise, it will not appear.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void NonlinearImager::
|
void NonlinearImager::
|
||||||
set_active(int index, bool active) {
|
set_screen_active(int index, bool active) {
|
||||||
nassertv(index >= 0 && index < (int)_screens.size());
|
nassertv(index >= 0 && index < (int)_screens.size());
|
||||||
_screens[index]._active = active;
|
_screens[index]._active = active;
|
||||||
|
|
||||||
if (!active) {
|
if (!active) {
|
||||||
Screen &screen = _screens[index];
|
Screen &screen = _screens[index];
|
||||||
// If we've just made this screen inactive, remove its mesh.
|
// If we've just made this screen inactive, remove its meshes.
|
||||||
screen._mesh.remove_node();
|
for (size_t vi = 0; vi < screen._meshes.size(); vi++) {
|
||||||
|
screen._meshes[vi]._mesh.remove_node();
|
||||||
|
}
|
||||||
screen._texture.clear();
|
screen._texture.clear();
|
||||||
} else {
|
} else {
|
||||||
// If we've just made it active, it needs to be recomputed.
|
// 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
|
// Access: Published
|
||||||
// Description: Returns the active flag on the indicated screen.
|
// Description: Returns the active flag on the indicated screen.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
bool NonlinearImager::
|
bool NonlinearImager::
|
||||||
get_active(int index) const {
|
get_screen_active(int index) const {
|
||||||
nassertr(index >= 0 && index < (int)_screens.size(), false);
|
nassertr(index >= 0 && index < (int)_screens.size(), false);
|
||||||
return _screens[index]._active;
|
return _screens[index]._active;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: NonlinearImager::set_viewer
|
// 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::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
|
// Access: Published
|
||||||
// Description: Specifies the LensNode that is to serve as the
|
// Description: Specifies the LensNode that is to serve as the
|
||||||
// viewer for this screen. The relative position of
|
// 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
|
// determines the UV's that will be assigned to the
|
||||||
// geometry within the NonlinearImager.
|
// 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).
|
// The NodePath must refer to a LensNode (or a Camera).
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void NonlinearImager::
|
void NonlinearImager::
|
||||||
set_viewer(const NodePath &viewer) {
|
set_viewer_camera(int index, const NodePath &viewer_camera) {
|
||||||
_viewer_node = (LensNode *)NULL;
|
nassertv(index >= 0 && index < (int)_viewers.size());
|
||||||
_viewer = viewer;
|
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;
|
_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::
|
void NonlinearImager::
|
||||||
recompute() {
|
recompute() {
|
||||||
|
// First, force all the textures to clear.
|
||||||
Screens::iterator si;
|
Screens::iterator si;
|
||||||
for (si = _screens.begin(); si != _screens.end(); ++si) {
|
for (si = _screens.begin(); si != _screens.end(); ++si) {
|
||||||
if ((*si)._active) {
|
Screen &screen = (*si);
|
||||||
recompute_screen(*si);
|
screen._texture.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_viewer_node != (LensNode *)NULL &&
|
|
||||||
_viewer_node->get_lens() != (Lens *)NULL) {
|
|
||||||
_viewer_lens_change = _viewer_node->get_lens()->get_last_change();
|
|
||||||
}
|
|
||||||
_stale = false;
|
_stale = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -321,20 +503,37 @@ render(GraphicsEngine *engine) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void NonlinearImager::
|
void NonlinearImager::
|
||||||
recompute_if_stale() {
|
recompute_if_stale() {
|
||||||
if (_viewer_node != (LensNode *)NULL &&
|
if (_stale) {
|
||||||
_viewer_node->get_lens() != (Lens *)NULL) {
|
recompute();
|
||||||
UpdateSeq lens_change = _viewer_node->get_lens()->get_last_change();
|
} else {
|
||||||
if (_stale || lens_change != _viewer_lens_change) {
|
size_t vi;
|
||||||
recompute();
|
for (vi = 0; vi < _viewers.size(); ++vi) {
|
||||||
} else {
|
Viewer &viewer = _viewers[vi];
|
||||||
// We're not overall stale, but maybe we need to recompute one
|
if (viewer._viewer_node != (LensNode *)NULL) {
|
||||||
// or more of our screens.
|
UpdateSeq lens_change =
|
||||||
Screens::iterator si;
|
viewer._viewer_node->get_lens()->get_last_change();
|
||||||
for (si = _screens.begin(); si != _screens.end(); ++si) {
|
if (lens_change != viewer._viewer_lens_change) {
|
||||||
Screen &screen = (*si);
|
// The viewer has changed, so we need to recompute all screens
|
||||||
if (screen._active &&
|
// on this viewer.
|
||||||
screen._last_screen != screen._screen->get_last_screen()) {
|
Screens::iterator si;
|
||||||
recompute_screen(screen);
|
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.
|
// screen.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void NonlinearImager::
|
void NonlinearImager::
|
||||||
recompute_screen(NonlinearImager::Screen &screen) {
|
recompute_screen(NonlinearImager::Screen &screen, size_t vi) {
|
||||||
screen._mesh.remove_node();
|
nassertv(vi < screen._meshes.size());
|
||||||
screen._texture.clear();
|
screen._meshes[vi]._mesh.remove_node();
|
||||||
if (_viewer_node == (LensNode *)NULL || !screen._active) {
|
if (!screen._active) {
|
||||||
// Not much we can do without a viewer.
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PT(PandaNode) mesh = screen._screen->make_flat_mesh(_viewer);
|
Viewer &viewer = _viewers[vi];
|
||||||
screen._mesh = _internal_scene.attach_new_node(mesh);
|
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;
|
if (screen._texture == (Texture *)NULL ||
|
||||||
texture->set_minfilter(Texture::FT_linear);
|
screen._texture->_pbuffer == (PixelBuffer *)NULL ||
|
||||||
texture->set_magfilter(Texture::FT_linear);
|
screen._texture->_pbuffer->get_xsize() != screen._tex_width ||
|
||||||
texture->set_wrapu(Texture::WM_clamp);
|
screen._texture->_pbuffer->get_ysize() != screen._tex_height) {
|
||||||
texture->set_wrapv(Texture::WM_clamp);
|
PT(Texture) texture = new Texture;
|
||||||
texture->_pbuffer->set_xsize(screen._tex_width);
|
texture->set_minfilter(Texture::FT_linear);
|
||||||
texture->_pbuffer->set_ysize(screen._tex_height);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Got to update this to new scene graph.
|
nassertv(_gsg != (GraphicsStateGuardian *)NULL);
|
||||||
GraphicsStateGuardian *gsg = _dr->get_window()->get_gsg();
|
|
||||||
|
|
||||||
// Make a display region of the proper size and clear it to prepare for
|
// Make a display region of the proper size and clear it to prepare for
|
||||||
// rendering the scene.
|
// rendering the scene.
|
||||||
PT(DisplayRegion) scratch_region =
|
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);
|
scratch_region->set_camera(screen._source_camera);
|
||||||
|
|
||||||
gsg->clear(gsg->get_render_buffer(RenderBuffer::T_back |
|
_gsg->clear(_gsg->get_render_buffer(RenderBuffer::T_back |
|
||||||
RenderBuffer::T_depth),
|
RenderBuffer::T_depth),
|
||||||
scratch_region);
|
scratch_region);
|
||||||
engine->render_subframe(gsg, scratch_region);
|
engine->render_subframe(_gsg, scratch_region);
|
||||||
|
|
||||||
// Copy the results of the render from the frame buffer into the
|
// Copy the results of the render from the frame buffer into the
|
||||||
// screen's texture.
|
// screen's texture.
|
||||||
screen._texture->copy(gsg, scratch_region,
|
screen._texture->copy(_gsg, scratch_region,
|
||||||
gsg->get_render_buffer(RenderBuffer::T_back));
|
_gsg->get_render_buffer(RenderBuffer::T_back));
|
||||||
|
|
||||||
// It might be nice if we didn't throw away the scratch region every
|
// 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
|
// time, which prevents us from preserving cull state from one frame
|
||||||
|
@ -31,12 +31,14 @@
|
|||||||
#include "pvector.h"
|
#include "pvector.h"
|
||||||
|
|
||||||
class GraphicsEngine;
|
class GraphicsEngine;
|
||||||
|
class GraphicsStateGuardian;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Class : NonlinearImager
|
// Class : NonlinearImager
|
||||||
// Description : This class object combines the rendered output of a
|
// Description : This class object combines the rendered output of a
|
||||||
// 3-d from one or more linear cameras, as seen through
|
// 3-d from one or more linear (e.g. perspective)
|
||||||
// a single, possibly non-linear camera.
|
// cameras, as seen through a single, possibly nonlinear
|
||||||
|
// camera.
|
||||||
//
|
//
|
||||||
// This can be used to generate real-time imagery of a
|
// This can be used to generate real-time imagery of a
|
||||||
// 3-d scene using a nonlinear camera, for instance a
|
// 3-d scene using a nonlinear camera, for instance a
|
||||||
@ -44,7 +46,7 @@ class GraphicsEngine;
|
|||||||
// only supports linear cameras.
|
// only supports linear cameras.
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// A NonlinearImager may be visualized as a theater room
|
// A NonlinearImager may be visualized as a dark room
|
||||||
// into which a number of projection screens have been
|
// into which a number of projection screens have been
|
||||||
// placed, of arbitrary size and shape and at any
|
// placed, of arbitrary size and shape and at any
|
||||||
// arbitrary position and orientation to each other.
|
// arbitrary position and orientation to each other.
|
||||||
@ -52,14 +54,33 @@ class GraphicsEngine;
|
|||||||
// seen by a normal perspective camera that exists in
|
// seen by a normal perspective camera that exists in
|
||||||
// the world (that is, under render).
|
// the world (that is, under render).
|
||||||
//
|
//
|
||||||
// There is also in the theater a single, possibly
|
// There also exists in the theater one or more
|
||||||
// nonlinear, camera that observes these screens. The
|
// (possibly nonlinear) cameras, called viewers, that
|
||||||
// user's window (or DisplayRegion) will display the
|
// observe these screens. Each of these viewers is
|
||||||
// output of this camera.
|
// associated with a single DisplayRegion, where the
|
||||||
|
// final results are presented.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// There are several different LensNode (Camera) objects
|
||||||
|
// involved at each stage in the process. To help keep
|
||||||
|
// them all straight, different words are used to refer
|
||||||
|
// to each different kind of Camera used within this
|
||||||
|
// object. The camera(s) under render, that capture the
|
||||||
|
// original view of the world to be projected onto the
|
||||||
|
// screens, are called source cameras, and are set per
|
||||||
|
// screen via set_source_camera(). The LensNode that is
|
||||||
|
// associated with each screen to project the image as
|
||||||
|
// seen from the screen's source camera is called a
|
||||||
|
// projector; these are set via the
|
||||||
|
// ProjectionScreen::set_projector() interface.
|
||||||
|
// Finally, the (possibly nonlinear) cameras that view
|
||||||
|
// the whole configuration of screens are called
|
||||||
|
// viewers; each of these is associated with a
|
||||||
|
// DisplayRegion, and they are set via set_viewer_camera().
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
class EXPCL_PANDAFX NonlinearImager {
|
class EXPCL_PANDAFX NonlinearImager {
|
||||||
PUBLISHED:
|
PUBLISHED:
|
||||||
NonlinearImager(DisplayRegion *dr);
|
NonlinearImager();
|
||||||
~NonlinearImager();
|
~NonlinearImager();
|
||||||
|
|
||||||
int add_screen(ProjectionScreen *screen);
|
int add_screen(ProjectionScreen *screen);
|
||||||
@ -69,49 +90,69 @@ PUBLISHED:
|
|||||||
|
|
||||||
int get_num_screens() const;
|
int get_num_screens() const;
|
||||||
ProjectionScreen *get_screen(int index) const;
|
ProjectionScreen *get_screen(int index) const;
|
||||||
void set_size(int index, int width, int height);
|
void set_texture_size(int index, int width, int height);
|
||||||
void set_source_camera(int index, const NodePath &source_camera);
|
void set_source_camera(int index, const NodePath &source_camera);
|
||||||
|
|
||||||
void set_active(int index, bool active);
|
void set_screen_active(int index, bool active);
|
||||||
bool get_active(int index) const;
|
bool get_screen_active(int index) const;
|
||||||
|
|
||||||
void set_viewer(const NodePath &viewer);
|
int add_viewer(DisplayRegion *dr);
|
||||||
INLINE const NodePath &get_viewer() const;
|
int find_viewer(DisplayRegion *dr) const;
|
||||||
|
void remove_viewer(int index);
|
||||||
|
void remove_all_viewers();
|
||||||
|
|
||||||
INLINE NodePath get_internal_scene() const;
|
void set_viewer_camera(int index, const NodePath &viewer_camera);
|
||||||
|
NodePath get_viewer_camera(int index) const;
|
||||||
|
|
||||||
|
NodePath get_internal_scene(int index) const;
|
||||||
|
|
||||||
|
int get_num_viewers() const;
|
||||||
|
DisplayRegion *get_viewer(int index) const;
|
||||||
|
|
||||||
void recompute();
|
void recompute();
|
||||||
void render(GraphicsEngine *engine);
|
void render(GraphicsEngine *engine);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
class Viewer {
|
||||||
|
public:
|
||||||
|
PT(DisplayRegion) _dr;
|
||||||
|
PT(Camera) _internal_camera;
|
||||||
|
NodePath _internal_scene;
|
||||||
|
NodePath _viewer;
|
||||||
|
PT(LensNode) _viewer_node;
|
||||||
|
UpdateSeq _viewer_lens_change;
|
||||||
|
};
|
||||||
|
typedef pvector<Viewer> Viewers;
|
||||||
|
|
||||||
|
class Mesh {
|
||||||
|
public:
|
||||||
|
NodePath _mesh;
|
||||||
|
UpdateSeq _last_screen;
|
||||||
|
};
|
||||||
|
typedef pvector<Mesh> Meshes;
|
||||||
|
|
||||||
class Screen {
|
class Screen {
|
||||||
public:
|
public:
|
||||||
PT(ProjectionScreen) _screen;
|
PT(ProjectionScreen) _screen;
|
||||||
NodePath _mesh;
|
|
||||||
PT(Texture) _texture;
|
PT(Texture) _texture;
|
||||||
NodePath _source_camera;
|
NodePath _source_camera;
|
||||||
int _tex_width, _tex_height;
|
int _tex_width, _tex_height;
|
||||||
UpdateSeq _last_screen;
|
|
||||||
bool _active;
|
bool _active;
|
||||||
|
|
||||||
|
// One mesh per viewer.
|
||||||
|
Meshes _meshes;
|
||||||
};
|
};
|
||||||
|
typedef pvector<Screen> Screens;
|
||||||
|
|
||||||
void recompute_if_stale();
|
void recompute_if_stale();
|
||||||
void recompute_screen(Screen &screen);
|
void recompute_screen(Screen &screen, size_t vi);
|
||||||
void render_screen(GraphicsEngine *engine, Screen &screen);
|
void render_screen(GraphicsEngine *engine, Screen &screen);
|
||||||
|
|
||||||
PT(DisplayRegion) _dr;
|
Viewers _viewers;
|
||||||
|
|
||||||
typedef pvector<Screen> Screens;
|
|
||||||
Screens _screens;
|
Screens _screens;
|
||||||
|
GraphicsStateGuardian *_gsg;
|
||||||
NodePath _viewer;
|
|
||||||
PT(LensNode) _viewer_node;
|
|
||||||
|
|
||||||
PT(Camera) _internal_camera;
|
|
||||||
NodePath _internal_scene;
|
|
||||||
|
|
||||||
bool _stale;
|
bool _stale;
|
||||||
UpdateSeq _viewer_lens_change;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#include "nonlinearImager.I"
|
#include "nonlinearImager.I"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user