use NodePaths for ProjectionScreen interface

This commit is contained in:
David Rose 2004-03-31 23:33:13 +00:00
parent 4df761d285
commit a1ba7a54e7
4 changed files with 132 additions and 39 deletions

View File

@ -52,6 +52,18 @@ NonlinearImager::
} }
} }
////////////////////////////////////////////////////////////////////
// Function: NonlinearImager::add_screen
// Access: Published
// This version of this method is deprecated and will
// soon be removed. Use the version that takes two
// parameters instead.
////////////////////////////////////////////////////////////////////
int NonlinearImager::
add_screen(ProjectionScreen *screen) {
return add_screen(NodePath(screen), screen->get_name());
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: NonlinearImager::add_screen // Function: NonlinearImager::add_screen
// Access: Published // Access: Published
@ -61,27 +73,28 @@ NonlinearImager::
// It must be based on a linear camera (or whatever kind // It must be based on a linear camera (or whatever kind
// of camera is respected by the graphics engine). // of camera is respected by the graphics engine).
// //
// width and height indicate the size of the texture
// that will be created to render the scene for the
// 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.
// //
// When render() is called, the graphics state guardian // As each frame is rendered, an offscreen image will be
// will be used to render a scene for each // rendered from the source camera associated with each
// ProjectionScreen object, and then each resulting // ProjectionScreen, and the resulting image will be
// image will be applied to a mesh to be rendered to the // applied to the screen geometry.
// screen.
// //
// The return value is the index number of the new // The return value is the index number of the new
// screen. // screen.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
int NonlinearImager:: int NonlinearImager::
add_screen(ProjectionScreen *screen, const string &name) { add_screen(const NodePath &screen, const string &name) {
nassertr(!screen.is_empty() &&
screen.node()->is_of_type(ProjectionScreen::get_class_type()), -1);
ProjectionScreen *screen_node = DCAST(ProjectionScreen, screen.node());
_screens.push_back(Screen()); _screens.push_back(Screen());
Screen &new_screen = _screens.back(); Screen &new_screen = _screens.back();
new_screen._screen = screen; new_screen._screen = screen;
new_screen._screen_node = screen_node;
new_screen._name = name; new_screen._name = name;
new_screen._buffer = (GraphicsOutput *)NULL; new_screen._buffer = (GraphicsOutput *)NULL;
new_screen._tex_width = 256; new_screen._tex_width = 256;
@ -92,10 +105,17 @@ add_screen(ProjectionScreen *screen, const string &name) {
size_t vi; size_t vi;
for (vi = 0; vi < _viewers.size(); ++vi) { for (vi = 0; vi < _viewers.size(); ++vi) {
new_screen._meshes.push_back(Mesh()); new_screen._meshes.push_back(Mesh());
new_screen._meshes[vi]._last_screen = screen->get_last_screen(); new_screen._meshes[vi]._last_screen = screen_node->get_last_screen();
} }
_stale = true; _stale = true;
if (_dark_room.is_empty()) {
_dark_room = screen.get_top();
} else {
nassertr(_dark_room.is_same_graph(screen), _screens.size() - 1);
}
return _screens.size() - 1; return _screens.size() - 1;
} }
@ -107,7 +127,7 @@ add_screen(ProjectionScreen *screen, const string &name) {
// if it does not appear. // if it does not appear.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
int NonlinearImager:: int NonlinearImager::
find_screen(ProjectionScreen *screen) const { find_screen(const NodePath &screen) const {
for (size_t i = 0; i < _screens.size(); i++) { for (size_t i = 0; i < _screens.size(); i++) {
if (_screens[i]._screen == screen) { if (_screens[i]._screen == screen) {
return i; return i;
@ -162,7 +182,7 @@ get_num_screens() const {
// Description: Returns the nth screen that has been added to the // Description: Returns the nth screen that has been added to the
// imager. // imager.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
ProjectionScreen *NonlinearImager:: NodePath NonlinearImager::
get_screen(int index) const { get_screen(int index) const {
nassertr(index >= 0 && index < (int)_screens.size(), (ProjectionScreen *)NULL); nassertr(index >= 0 && index < (int)_screens.size(), (ProjectionScreen *)NULL);
return _screens[index]._screen; return _screens[index]._screen;
@ -294,7 +314,15 @@ get_screen_active(int index) const {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
int NonlinearImager:: int NonlinearImager::
add_viewer(DisplayRegion *dr) { add_viewer(DisplayRegion *dr) {
GraphicsEngine *engine = dr->get_window()->get_gsg()->get_engine(); GraphicsOutput *window = dr->get_window();
nassertr(window != (GraphicsOutput *)NULL, -1);
GraphicsStateGuardian *gsg = window->get_gsg();
nassertr(gsg != (GraphicsStateGuardian *)NULL, -1);
GraphicsEngine *engine = gsg->get_engine();
nassertr(engine != (GraphicsEngine *)NULL, -1);
nassertr(_viewers.empty() || (engine == _engine), -1); nassertr(_viewers.empty() || (engine == _engine), -1);
if (_engine == (GraphicsEngine *)NULL) { if (_engine == (GraphicsEngine *)NULL) {
_engine = engine; _engine = engine;
@ -323,9 +351,9 @@ add_viewer(DisplayRegion *dr) {
// The internal camera is an identity-matrix camera that simply // The internal camera is an identity-matrix camera that simply
// views the meshes that represent the user's specified camera. // views the meshes that represent the user's specified camera.
viewer._internal_camera = new Camera("NonlinearImager"); viewer._internal_camera = new Camera("internal_camera");
viewer._internal_camera->set_lens(new MatrixLens); viewer._internal_camera->set_lens(new MatrixLens);
viewer._internal_scene = NodePath("screens"); viewer._internal_scene = NodePath("internal_screens");
viewer._internal_camera->set_scene(viewer._internal_scene); viewer._internal_camera->set_scene(viewer._internal_scene);
NodePath camera_np = viewer._internal_scene.attach_new_node(viewer._internal_camera); NodePath camera_np = viewer._internal_scene.attach_new_node(viewer._internal_camera);
@ -345,6 +373,13 @@ add_viewer(DisplayRegion *dr) {
} }
_stale = true; _stale = true;
if (_dark_room.is_empty()) {
_dark_room = viewer._viewer.get_top();
} else {
nassertr(_dark_room.is_same_graph(viewer._viewer), vi);
}
return vi; return vi;
} }
@ -429,6 +464,12 @@ set_viewer_camera(int index, const NodePath &viewer_camera) {
viewer._viewer = viewer_camera; viewer._viewer = viewer_camera;
viewer._viewer_node = DCAST(LensNode, viewer_camera.node()); viewer._viewer_node = DCAST(LensNode, viewer_camera.node());
_stale = true; _stale = true;
if (_dark_room.is_empty()) {
_dark_room = viewer._viewer.get_top();
} else {
nassertv(_dark_room.is_same_graph(viewer._viewer));
}
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -444,14 +485,21 @@ get_viewer_camera(int index) const {
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: NonlinearImager::get_internal_scene // Function: NonlinearImager::get_viewer_scene
// Access: Published // Access: Published
// Description: Returns a pointer to the root node of the internal // Description: Returns a pointer to the root node of the internal
// scene graph for the nth viewer, which is used to // scene graph for the nth viewer, which is used to
// render all of the screen meshes for this viewer. // render all of the screen meshes for this viewer.
//
// This is the scene graph in which the screen meshes
// within the dark room have been flattened into the
// appropriate transformation according to the viewer's
// lens properties (and position relative to the
// screens). It is this scene graph that is finally
// rendered to the window.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
NodePath NonlinearImager:: NodePath NonlinearImager::
get_internal_scene(int index) const { get_viewer_scene(int index) const {
nassertr(index >= 0 && index < (int)_viewers.size(), NodePath()); nassertr(index >= 0 && index < (int)_viewers.size(), NodePath());
return _viewers[index]._internal_scene; return _viewers[index]._internal_scene;
} }
@ -479,6 +527,38 @@ get_viewer(int index) const {
return _viewers[index]._dr; return _viewers[index]._dr;
} }
////////////////////////////////////////////////////////////////////
// Function: NonlinearImager::get_dark_room
// Access: Published
// Description: Returns the NodePath to the root of the dark room
// scene. This is the scene in which all of the
// ProjectionScreens and the viewer cameras reside.
// It's a standalone scene with a few projection screens
// arranged artfully around one or more viewers; it's so
// named because it's a little virtual theater.
//
// Normally this scene is not rendered directly; it only
// exists as an abstract concept, and to define the
// relation between the ProjectionScreens and the
// viewers. But it may be rendered to help visualize
// the NonlinearImager's behavior.
////////////////////////////////////////////////////////////////////
NodePath NonlinearImager::
get_dark_room() const {
return _dark_room;
}
////////////////////////////////////////////////////////////////////
// Function: NonlinearImager::get_graphics_engine
// Access: Published
// Description: Returns the GraphicsEngine that all of the viewers
// added to the NonlinearImager have in common.
////////////////////////////////////////////////////////////////////
GraphicsEngine *NonlinearImager::
get_graphics_engine() const {
return _engine;
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: NonlinearImager::recompute // Function: NonlinearImager::recompute
// Access: Published // Access: Published
@ -555,10 +635,10 @@ recompute_if_stale() {
for (si = _screens.begin(); si != _screens.end(); ++si) { for (si = _screens.begin(); si != _screens.end(); ++si) {
Screen &screen = (*si); Screen &screen = (*si);
if (screen._active && if (screen._active &&
screen._meshes[vi]._last_screen != screen._screen->get_last_screen()) { screen._meshes[vi]._last_screen != screen._screen_node->get_last_screen()) {
recompute_screen(screen, vi); recompute_screen(screen, vi);
} else { } else {
screen._screen->recompute_if_stale(); screen._screen_node->recompute_if_stale(screen._screen);
} }
} }
} }
@ -581,10 +661,11 @@ recompute_screen(NonlinearImager::Screen &screen, size_t vi) {
return; return;
} }
screen._screen->recompute_if_stale(); screen._screen_node->recompute_if_stale(screen._screen);
Viewer &viewer = _viewers[vi]; Viewer &viewer = _viewers[vi];
PT(PandaNode) mesh = screen._screen->make_flat_mesh(viewer._viewer); PT(PandaNode) mesh =
screen._screen_node->make_flat_mesh(screen._screen, viewer._viewer);
if (mesh != (PandaNode *)NULL) { if (mesh != (PandaNode *)NULL) {
screen._meshes[vi]._mesh = viewer._internal_scene.attach_new_node(mesh); screen._meshes[vi]._mesh = viewer._internal_scene.attach_new_node(mesh);
} }
@ -606,7 +687,13 @@ recompute_screen(NonlinearImager::Screen &screen, size_t vi) {
if (screen._buffer != (GraphicsOutput *)NULL) { if (screen._buffer != (GraphicsOutput *)NULL) {
screen._meshes[vi]._mesh.set_texture(screen._buffer->get_texture()); screen._meshes[vi]._mesh.set_texture(screen._buffer->get_texture());
// We don't really need to set the texture on the external screen,
// since that's normally not rendered, but we do anyway just for
// debugging purposes (in case the user does try to render it, to
// see what's going on).
screen._screen.set_texture(screen._buffer->get_texture());
} }
screen._meshes[vi]._last_screen = screen._screen->get_last_screen(); screen._meshes[vi]._last_screen = screen._screen_node->get_last_screen();
} }

View File

@ -96,13 +96,14 @@ PUBLISHED:
NonlinearImager(); NonlinearImager();
~NonlinearImager(); ~NonlinearImager();
int add_screen(ProjectionScreen *screen, const string &name = string()); int add_screen(ProjectionScreen *screen);
int find_screen(ProjectionScreen *screen) const; int add_screen(const NodePath &screen, const string &name);
int find_screen(const NodePath &screen) const;
void remove_screen(int index); void remove_screen(int index);
void remove_all_screens(); void remove_all_screens();
int get_num_screens() const; int get_num_screens() const;
ProjectionScreen *get_screen(int index) const; NodePath get_screen(int index) const;
GraphicsOutput *get_buffer(int index) const; GraphicsOutput *get_buffer(int index) const;
void set_texture_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);
@ -117,12 +118,14 @@ PUBLISHED:
void set_viewer_camera(int index, const NodePath &viewer_camera); void set_viewer_camera(int index, const NodePath &viewer_camera);
NodePath get_viewer_camera(int index) const; NodePath get_viewer_camera(int index) const;
NodePath get_viewer_scene(int index) const;
NodePath get_internal_scene(int index) const;
int get_num_viewers() const; int get_num_viewers() const;
DisplayRegion *get_viewer(int index) const; DisplayRegion *get_viewer(int index) const;
NodePath get_dark_room() const;
GraphicsEngine *get_graphics_engine() const;
void recompute(); void recompute();
public: public:
@ -150,7 +153,8 @@ private:
class Screen { class Screen {
public: public:
PT(ProjectionScreen) _screen; NodePath _screen;
PT(ProjectionScreen) _screen_node;
string _name; string _name;
PT(GraphicsOutput) _buffer; PT(GraphicsOutput) _buffer;
NodePath _source_camera; NodePath _source_camera;
@ -169,6 +173,7 @@ private:
Screens _screens; Screens _screens;
GraphicsEngine *_engine; GraphicsEngine *_engine;
NodePath _dark_room;
bool _stale; bool _stale;
}; };

View File

@ -116,8 +116,8 @@ has_cull_callback() const {
// visible, or false if it should be culled. // visible, or false if it should be culled.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
bool ProjectionScreen:: bool ProjectionScreen::
cull_callback(CullTraverser *, CullTraverserData &) { cull_callback(CullTraverser *, CullTraverserData &data) {
recompute_if_stale(); recompute_if_stale(data._node_path.get_node_path());
return true; return true;
} }
@ -313,7 +313,8 @@ regenerate_screen(const NodePath &projector, const string &screen_name,
// does not get dereferenced and deleted. // does not get dereferenced and deleted.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
PT(PandaNode) ProjectionScreen:: PT(PandaNode) ProjectionScreen::
make_flat_mesh(const NodePath &camera) { make_flat_mesh(const NodePath &this_np, const NodePath &camera) {
nassertr(!this_np.is_empty() && this_np.node() == this, NULL);
nassertr(!camera.is_empty() && nassertr(!camera.is_empty() &&
camera.node()->is_of_type(LensNode::get_class_type()), camera.node()->is_of_type(LensNode::get_class_type()),
NULL); NULL);
@ -321,10 +322,9 @@ make_flat_mesh(const NodePath &camera) {
nassertr(camera_node->get_lens() != (Lens *)NULL, NULL); nassertr(camera_node->get_lens() != (Lens *)NULL, NULL);
// First, ensure the UV's are up-to-date. // First, ensure the UV's are up-to-date.
recompute_if_stale(); recompute_if_stale(this_np);
PT(PandaNode) top = new PandaNode(get_name()); PT(PandaNode) top = new PandaNode(get_name());
NodePath this_np(this);
LMatrix4f rel_mat; LMatrix4f rel_mat;
bool computed_rel_mat = false; bool computed_rel_mat = false;
@ -348,7 +348,7 @@ make_flat_mesh(const NodePath &camera) {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void ProjectionScreen:: void ProjectionScreen::
recompute() { recompute() {
NodePath this_np(this); NodePath this_np(NodePath::any_path(this));
do_recompute(this_np); do_recompute(this_np);
} }
@ -361,7 +361,9 @@ recompute() {
// changed. // changed.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void ProjectionScreen:: void ProjectionScreen::
recompute_if_stale() { recompute_if_stale(const NodePath &this_np) {
nassertv(!this_np.is_empty() && this_np.node() == this);
if (_projector_node != (LensNode *)NULL && if (_projector_node != (LensNode *)NULL &&
_projector_node->get_lens() != (Lens *)NULL) { _projector_node->get_lens() != (Lens *)NULL) {
UpdateSeq lens_change = _projector_node->get_lens()->get_last_change(); UpdateSeq lens_change = _projector_node->get_lens()->get_last_change();
@ -370,7 +372,6 @@ recompute_if_stale() {
} else { } else {
// Get the relative transform to ensure it hasn't changed. // Get the relative transform to ensure it hasn't changed.
NodePath this_np(this);
const LMatrix4f &top_mat = this_np.get_mat(_projector); const LMatrix4f &top_mat = this_np.get_mat(_projector);
if (!_rel_top_mat.almost_equal(top_mat)) { if (!_rel_top_mat.almost_equal(top_mat)) {
_rel_top_mat = top_mat; _rel_top_mat = top_mat;

View File

@ -71,7 +71,7 @@ PUBLISHED:
void regenerate_screen(const NodePath &projector, const string &screen_name, void regenerate_screen(const NodePath &projector, const string &screen_name,
int num_x_verts, int num_y_verts, float distance, int num_x_verts, int num_y_verts, float distance,
float fill_ratio); float fill_ratio);
PT(PandaNode) make_flat_mesh(const NodePath &camera); PT(PandaNode) make_flat_mesh(const NodePath &this_np, const NodePath &camera);
INLINE void set_invert_uvs(bool invert_uvs); INLINE void set_invert_uvs(bool invert_uvs);
INLINE bool get_invert_uvs() const; INLINE bool get_invert_uvs() const;
@ -88,7 +88,7 @@ PUBLISHED:
public: public:
INLINE const UpdateSeq &get_last_screen() const; INLINE const UpdateSeq &get_last_screen() const;
void recompute_if_stale(); void recompute_if_stale(const NodePath &this_np);
private: private:
void do_recompute(const NodePath &this_np); void do_recompute(const NodePath &this_np);