mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-17 12:12:10 -04:00
use NodePaths for ProjectionScreen interface
This commit is contained in:
parent
4df761d285
commit
a1ba7a54e7
@ -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
|
||||
// Access: Published
|
||||
@ -61,27 +73,28 @@ NonlinearImager::
|
||||
// It must be based on a linear camera (or whatever kind
|
||||
// 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
|
||||
// screen geometry created.
|
||||
//
|
||||
// When render() is called, the graphics state guardian
|
||||
// will be used to render a scene for each
|
||||
// ProjectionScreen object, and then each resulting
|
||||
// image will be applied to a mesh to be rendered to the
|
||||
// screen.
|
||||
// As each frame is rendered, an offscreen image will be
|
||||
// rendered from the source camera associated with each
|
||||
// ProjectionScreen, and the resulting image will be
|
||||
// applied to the screen geometry.
|
||||
//
|
||||
// The return value is the index number of the new
|
||||
// screen.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
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());
|
||||
Screen &new_screen = _screens.back();
|
||||
new_screen._screen = screen;
|
||||
new_screen._screen_node = screen_node;
|
||||
new_screen._name = name;
|
||||
new_screen._buffer = (GraphicsOutput *)NULL;
|
||||
new_screen._tex_width = 256;
|
||||
@ -92,10 +105,17 @@ add_screen(ProjectionScreen *screen, const string &name) {
|
||||
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();
|
||||
new_screen._meshes[vi]._last_screen = screen_node->get_last_screen();
|
||||
}
|
||||
|
||||
_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;
|
||||
}
|
||||
|
||||
@ -107,7 +127,7 @@ add_screen(ProjectionScreen *screen, const string &name) {
|
||||
// if it does not appear.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int NonlinearImager::
|
||||
find_screen(ProjectionScreen *screen) const {
|
||||
find_screen(const NodePath &screen) const {
|
||||
for (size_t i = 0; i < _screens.size(); i++) {
|
||||
if (_screens[i]._screen == screen) {
|
||||
return i;
|
||||
@ -162,7 +182,7 @@ get_num_screens() const {
|
||||
// Description: Returns the nth screen that has been added to the
|
||||
// imager.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
ProjectionScreen *NonlinearImager::
|
||||
NodePath NonlinearImager::
|
||||
get_screen(int index) const {
|
||||
nassertr(index >= 0 && index < (int)_screens.size(), (ProjectionScreen *)NULL);
|
||||
return _screens[index]._screen;
|
||||
@ -294,7 +314,15 @@ get_screen_active(int index) const {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int NonlinearImager::
|
||||
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);
|
||||
if (_engine == (GraphicsEngine *)NULL) {
|
||||
_engine = engine;
|
||||
@ -323,9 +351,9 @@ add_viewer(DisplayRegion *dr) {
|
||||
|
||||
// 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 = new Camera("internal_camera");
|
||||
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);
|
||||
|
||||
NodePath camera_np = viewer._internal_scene.attach_new_node(viewer._internal_camera);
|
||||
@ -345,6 +373,13 @@ add_viewer(DisplayRegion *dr) {
|
||||
}
|
||||
|
||||
_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;
|
||||
}
|
||||
|
||||
@ -429,6 +464,12 @@ set_viewer_camera(int index, const NodePath &viewer_camera) {
|
||||
viewer._viewer = viewer_camera;
|
||||
viewer._viewer_node = DCAST(LensNode, viewer_camera.node());
|
||||
_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
|
||||
// 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.
|
||||
//
|
||||
// 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::
|
||||
get_internal_scene(int index) const {
|
||||
get_viewer_scene(int index) const {
|
||||
nassertr(index >= 0 && index < (int)_viewers.size(), NodePath());
|
||||
return _viewers[index]._internal_scene;
|
||||
}
|
||||
@ -479,6 +527,38 @@ get_viewer(int index) const {
|
||||
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
|
||||
// Access: Published
|
||||
@ -555,10 +635,10 @@ recompute_if_stale() {
|
||||
for (si = _screens.begin(); si != _screens.end(); ++si) {
|
||||
Screen &screen = (*si);
|
||||
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);
|
||||
} 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;
|
||||
}
|
||||
|
||||
screen._screen->recompute_if_stale();
|
||||
screen._screen_node->recompute_if_stale(screen._screen);
|
||||
|
||||
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) {
|
||||
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) {
|
||||
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();
|
||||
}
|
||||
|
@ -96,13 +96,14 @@ PUBLISHED:
|
||||
NonlinearImager();
|
||||
~NonlinearImager();
|
||||
|
||||
int add_screen(ProjectionScreen *screen, const string &name = string());
|
||||
int find_screen(ProjectionScreen *screen) const;
|
||||
int add_screen(ProjectionScreen *screen);
|
||||
int add_screen(const NodePath &screen, const string &name);
|
||||
int find_screen(const NodePath &screen) const;
|
||||
void remove_screen(int index);
|
||||
void remove_all_screens();
|
||||
|
||||
int get_num_screens() const;
|
||||
ProjectionScreen *get_screen(int index) const;
|
||||
NodePath get_screen(int index) const;
|
||||
GraphicsOutput *get_buffer(int index) const;
|
||||
void set_texture_size(int index, int width, int height);
|
||||
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);
|
||||
NodePath get_viewer_camera(int index) const;
|
||||
|
||||
NodePath get_internal_scene(int index) const;
|
||||
NodePath get_viewer_scene(int index) const;
|
||||
|
||||
int get_num_viewers() const;
|
||||
DisplayRegion *get_viewer(int index) const;
|
||||
|
||||
NodePath get_dark_room() const;
|
||||
GraphicsEngine *get_graphics_engine() const;
|
||||
|
||||
void recompute();
|
||||
|
||||
public:
|
||||
@ -150,7 +153,8 @@ private:
|
||||
|
||||
class Screen {
|
||||
public:
|
||||
PT(ProjectionScreen) _screen;
|
||||
NodePath _screen;
|
||||
PT(ProjectionScreen) _screen_node;
|
||||
string _name;
|
||||
PT(GraphicsOutput) _buffer;
|
||||
NodePath _source_camera;
|
||||
@ -169,6 +173,7 @@ private:
|
||||
Screens _screens;
|
||||
|
||||
GraphicsEngine *_engine;
|
||||
NodePath _dark_room;
|
||||
|
||||
bool _stale;
|
||||
};
|
||||
|
@ -116,8 +116,8 @@ has_cull_callback() const {
|
||||
// visible, or false if it should be culled.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool ProjectionScreen::
|
||||
cull_callback(CullTraverser *, CullTraverserData &) {
|
||||
recompute_if_stale();
|
||||
cull_callback(CullTraverser *, CullTraverserData &data) {
|
||||
recompute_if_stale(data._node_path.get_node_path());
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -313,7 +313,8 @@ regenerate_screen(const NodePath &projector, const string &screen_name,
|
||||
// does not get dereferenced and deleted.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
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() &&
|
||||
camera.node()->is_of_type(LensNode::get_class_type()),
|
||||
NULL);
|
||||
@ -321,10 +322,9 @@ make_flat_mesh(const NodePath &camera) {
|
||||
nassertr(camera_node->get_lens() != (Lens *)NULL, NULL);
|
||||
|
||||
// First, ensure the UV's are up-to-date.
|
||||
recompute_if_stale();
|
||||
recompute_if_stale(this_np);
|
||||
|
||||
PT(PandaNode) top = new PandaNode(get_name());
|
||||
NodePath this_np(this);
|
||||
|
||||
LMatrix4f rel_mat;
|
||||
bool computed_rel_mat = false;
|
||||
@ -348,7 +348,7 @@ make_flat_mesh(const NodePath &camera) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ProjectionScreen::
|
||||
recompute() {
|
||||
NodePath this_np(this);
|
||||
NodePath this_np(NodePath::any_path(this));
|
||||
do_recompute(this_np);
|
||||
}
|
||||
|
||||
@ -361,7 +361,9 @@ recompute() {
|
||||
// changed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
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 &&
|
||||
_projector_node->get_lens() != (Lens *)NULL) {
|
||||
UpdateSeq lens_change = _projector_node->get_lens()->get_last_change();
|
||||
@ -370,7 +372,6 @@ recompute_if_stale() {
|
||||
|
||||
} else {
|
||||
// Get the relative transform to ensure it hasn't changed.
|
||||
NodePath this_np(this);
|
||||
const LMatrix4f &top_mat = this_np.get_mat(_projector);
|
||||
if (!_rel_top_mat.almost_equal(top_mat)) {
|
||||
_rel_top_mat = top_mat;
|
||||
|
@ -71,7 +71,7 @@ PUBLISHED:
|
||||
void regenerate_screen(const NodePath &projector, const string &screen_name,
|
||||
int num_x_verts, int num_y_verts, float distance,
|
||||
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 bool get_invert_uvs() const;
|
||||
@ -88,7 +88,7 @@ PUBLISHED:
|
||||
|
||||
public:
|
||||
INLINE const UpdateSeq &get_last_screen() const;
|
||||
void recompute_if_stale();
|
||||
void recompute_if_stale(const NodePath &this_np);
|
||||
|
||||
private:
|
||||
void do_recompute(const NodePath &this_np);
|
||||
|
Loading…
x
Reference in New Issue
Block a user