From 6a8b0b39136b062835a95281a281c130cc672a83 Mon Sep 17 00:00:00 2001 From: David Rose Date: Tue, 26 Feb 2002 00:07:26 +0000 Subject: [PATCH] integrate more new-scene-graph stuff --- panda/src/display/Sources.pp | 28 +- panda/src/display/displayRegion.I | 5 +- panda/src/display/displayRegion.cxx | 17 +- panda/src/display/displayRegion.h | 4 + panda/src/display/display_composite1.cxx | 2 + panda/src/display/drawCullHandler.I | 29 ++ panda/src/display/drawCullHandler.cxx | 36 +++ panda/src/display/drawCullHandler.h | 56 ++++ panda/src/display/graphicsChannel.I | 6 +- panda/src/display/graphicsChannel.cxx | 15 + panda/src/display/graphicsChannel.h | 3 + panda/src/display/graphicsEngine.I | 18 ++ panda/src/display/graphicsEngine.cxx | 156 ++++++++++ panda/src/display/graphicsEngine.h | 66 +++++ panda/src/display/graphicsLayer.I | 11 +- panda/src/display/graphicsLayer.cxx | 20 ++ panda/src/display/graphicsLayer.h | 4 + panda/src/display/graphicsStateGuardian.I | 104 ++++++- panda/src/display/graphicsStateGuardian.cxx | 104 ++++++- panda/src/display/graphicsStateGuardian.h | 38 ++- panda/src/display/graphicsWindow.I | 55 ++++ panda/src/display/graphicsWindow.cxx | 62 ++++ panda/src/display/graphicsWindow.h | 24 +- panda/src/display/lensStack.I | 61 ++++ panda/src/display/lensStack.h | 50 ++++ panda/src/glgsg/glGraphicsStateGuardian.cxx | 142 ++++----- panda/src/glgsg/glGraphicsStateGuardian.h | 15 +- panda/src/gsgbase/graphicsStateGuardianBase.h | 6 + panda/src/pgraph/Sources.pp | 2 +- panda/src/pgraph/colorAttrib.cxx | 15 + panda/src/pgraph/colorAttrib.h | 1 + panda/src/pgraph/cullHandler.cxx | 4 +- panda/src/pgraph/cullHandler.h | 7 +- panda/src/pgraph/pandaNode.I | 4 +- panda/src/pgraph/pandaNode.h | 10 +- panda/src/pgraph/pipeline.cxx | 14 +- panda/src/pgraph/pipeline.h | 5 +- panda/src/pgraph/qpcullTraverser.cxx | 2 +- panda/src/pgraph/renderAttrib.I | 21 ++ panda/src/pgraph/renderAttrib.cxx | 31 +- panda/src/pgraph/renderAttrib.h | 5 + panda/src/pgraph/renderState.cxx | 278 +++++++++++++++++- panda/src/pgraph/renderState.h | 13 +- panda/src/pgraph/textureAttrib.cxx | 15 + panda/src/pgraph/textureAttrib.h | 1 + panda/src/sgraph/camera.I | 24 ++ panda/src/sgraph/camera.h | 5 + panda/src/testbed/Sources.pp | 9 + 48 files changed, 1463 insertions(+), 140 deletions(-) create mode 100644 panda/src/display/drawCullHandler.I create mode 100644 panda/src/display/drawCullHandler.cxx create mode 100644 panda/src/display/drawCullHandler.h create mode 100644 panda/src/display/graphicsEngine.I create mode 100644 panda/src/display/graphicsEngine.cxx create mode 100644 panda/src/display/graphicsEngine.h create mode 100644 panda/src/display/lensStack.I create mode 100644 panda/src/display/lensStack.h diff --git a/panda/src/display/Sources.pp b/panda/src/display/Sources.pp index 91eae7e761..0322c46e6c 100644 --- a/panda/src/display/Sources.pp +++ b/panda/src/display/Sources.pp @@ -4,28 +4,38 @@ #begin lib_target #define TARGET display #define LOCAL_LIBS \ - putil gsgbase gobj linmath graph mathutil sgraph \ + pgraph putil gsgbase gobj linmath graph mathutil sgraph \ pstatclient #define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx #define SOURCES \ config_display.h displayRegion.I displayRegion.h \ + displayRegionStack.I \ + displayRegionStack.h \ + drawCullHandler.h drawCullHandler.I \ + frameBufferStack.I frameBufferStack.h \ geomContext.I geomContext.h geomNodeContext.I geomNodeContext.h \ - graphicsChannel.I graphicsChannel.h graphicsLayer.I \ + graphicsChannel.I graphicsChannel.h \ + graphicsEngine.I graphicsEngine.h \ + graphicsLayer.I \ graphicsLayer.h graphicsPipe.I graphicsPipe.N graphicsPipe.h \ graphicsStateGuardian.I graphicsStateGuardian.N \ graphicsStateGuardian.h graphicsWindow.I graphicsWindow.N \ graphicsWindow.h graphicsWindowInputDevice.I \ graphicsWindowInputDevice.h hardwareChannel.I \ hardwareChannel.h interactiveGraphicsPipe.I \ - interactiveGraphicsPipe.h noninteractiveGraphicsPipe.I \ + interactiveGraphicsPipe.h \ + lensStack.I lensStack.h \ + noninteractiveGraphicsPipe.I \ noninteractiveGraphicsPipe.h pipeSpec.I pipeSpec.h \ savedFrameBuffer.I savedFrameBuffer.h #define INCLUDED_SOURCES \ config_display.cxx displayRegion.cxx \ + drawCullHandler.cxx \ geomContext.cxx geomNodeContext.cxx graphicsChannel.cxx \ + graphicsEngine.cxx \ graphicsLayer.cxx graphicsPipe.cxx graphicsStateGuardian.cxx \ graphicsWindow.cxx graphicsWindowInputDevice.cxx \ hardwareChannel.cxx interactiveGraphicsPipe.cxx \ @@ -35,14 +45,20 @@ #define INSTALL_HEADERS \ config_display.h \ displayRegion.I displayRegion.h displayRegionStack.I \ - displayRegionStack.h frameBufferStack.I frameBufferStack.h \ + displayRegionStack.h \ + drawCullHandler.h drawCullHandler.I \ + frameBufferStack.I frameBufferStack.h \ geomContext.I geomContext.h geomNodeContext.I geomNodeContext.h \ - graphicsChannel.I graphicsChannel.h graphicsLayer.I graphicsLayer.h \ + graphicsChannel.I graphicsChannel.h \ + graphicsEngine.I graphicsEngine.h \ + graphicsLayer.I graphicsLayer.h \ graphicsPipe.I graphicsPipe.h graphicsStateGuardian.I \ graphicsStateGuardian.h graphicsWindow.I graphicsWindow.h \ graphicsWindowInputDevice.I graphicsWindowInputDevice.h \ hardwareChannel.I hardwareChannel.h interactiveGraphicsPipe.I \ - interactiveGraphicsPipe.h noninteractiveGraphicsPipe.I \ + interactiveGraphicsPipe.h \ + lensStack.I lensStack.h \ + noninteractiveGraphicsPipe.I \ noninteractiveGraphicsPipe.h pipeSpec.I pipeSpec.h renderBuffer.h \ savedFrameBuffer.I savedFrameBuffer.h diff --git a/panda/src/display/displayRegion.I b/panda/src/display/displayRegion.I index 4c793c7020..0f30621b01 100644 --- a/panda/src/display/displayRegion.I +++ b/panda/src/display/displayRegion.I @@ -140,7 +140,10 @@ get_cull_frustum() const { //////////////////////////////////////////////////////////////////// INLINE void DisplayRegion:: set_active(bool active) { - _active = active; + if (active != _active) { + _active = active; + win_display_regions_changed(); + } } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/display/displayRegion.cxx b/panda/src/display/displayRegion.cxx index c5c74e81dc..49cd5ceb45 100644 --- a/panda/src/display/displayRegion.cxx +++ b/panda/src/display/displayRegion.cxx @@ -21,9 +21,9 @@ #include "graphicsChannel.h" #include "graphicsWindow.h" #include "config_display.h" - #include "displayRegion.h" + //////////////////////////////////////////////////////////////////// // Function: DisplayRegion::Constructor // Access: Public @@ -193,3 +193,18 @@ output(ostream &out) const { << ")=pixels(" << _pl << " " << _pr << " " << _pb << " " << _pt << ")"; } + +//////////////////////////////////////////////////////////////////// +// Function: DisplayRegion::win_display_regions_changed +// Access: Public +// Description: Intended to be called when the active state on a +// nested channel or layer or display region changes, +// forcing the window to recompute its list of active +// display regions. +//////////////////////////////////////////////////////////////////// +void DisplayRegion:: +win_display_regions_changed() { + if (_layer != (GraphicsLayer *)NULL) { + _layer->win_display_regions_changed(); + } +} diff --git a/panda/src/display/displayRegion.h b/panda/src/display/displayRegion.h index fc09afabd9..d819bb4ab9 100644 --- a/panda/src/display/displayRegion.h +++ b/panda/src/display/displayRegion.h @@ -35,6 +35,7 @@ class GraphicsLayer; class GraphicsChannel; class GraphicsWindow; class GraphicsPipe; +class CullHandler; //////////////////////////////////////////////////////////////////// // Class : DisplayRegion @@ -80,6 +81,9 @@ PUBLISHED: void output(ostream &out) const; +public: + void win_display_regions_changed(); + protected: float _l; diff --git a/panda/src/display/display_composite1.cxx b/panda/src/display/display_composite1.cxx index 1549237758..9ac9f76253 100644 --- a/panda/src/display/display_composite1.cxx +++ b/panda/src/display/display_composite1.cxx @@ -1,8 +1,10 @@ #include "displayRegion.cxx" +#include "drawCullHandler.cxx" #include "geomContext.cxx" #include "geomNodeContext.cxx" #include "graphicsChannel.cxx" +#include "graphicsEngine.cxx" #include "graphicsLayer.cxx" #include "graphicsPipe.cxx" #include "graphicsStateGuardian.cxx" diff --git a/panda/src/display/drawCullHandler.I b/panda/src/display/drawCullHandler.I new file mode 100644 index 0000000000..3b968f9c50 --- /dev/null +++ b/panda/src/display/drawCullHandler.I @@ -0,0 +1,29 @@ +// Filename: drawCullHandler.I +// Created by: drose (25Feb02) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: DrawCullHandler::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE DrawCullHandler:: +DrawCullHandler(GraphicsStateGuardian *gsg) : + _gsg(gsg) +{ +} diff --git a/panda/src/display/drawCullHandler.cxx b/panda/src/display/drawCullHandler.cxx new file mode 100644 index 0000000000..56e82b3c4e --- /dev/null +++ b/panda/src/display/drawCullHandler.cxx @@ -0,0 +1,36 @@ +// Filename: drawCullHandler.cxx +// Created by: drose (25Feb02) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#include "drawCullHandler.h" +#include "geom.h" +#include "renderState.h" +#include "graphicsStateGuardian.h" + + +//////////////////////////////////////////////////////////////////// +// Function: DrawCullHandler::record_geom +// Access: Public, Virtual +// Description: This callback function is intended to be overridden +// by a derived class. This is called as each Geom is +// discovered by the CullTraverser. +//////////////////////////////////////////////////////////////////// +void DrawCullHandler:: +record_geom(Geom *geom, const RenderState *state) { + _gsg->set_state(state); + geom->draw(_gsg); +} diff --git a/panda/src/display/drawCullHandler.h b/panda/src/display/drawCullHandler.h new file mode 100644 index 0000000000..430f49eddf --- /dev/null +++ b/panda/src/display/drawCullHandler.h @@ -0,0 +1,56 @@ +// Filename: drawCullHandler.h +// Created by: drose (25Feb02) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#ifndef DRAWCULLHANDLER_H +#define DRAWCULLHANDLER_H + +#include "pandabase.h" +#include "cullHandler.h" + +class GraphicsStateGuardian; + +//////////////////////////////////////////////////////////////////// +// Class : DrawCullHandler +// Description : This special kind of CullHandler immediately draws +// its contents as soon as it receives them. This draws +// geometry immediately as it is encountered in the +// scene graph by cull, mixing the draw and cull +// traversals into one traversal, and prohibiting state +// sorting. However, it has somewhat lower overhead +// than separating out draw and cull, if state sorting +// and multiprocessing are not required. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA DrawCullHandler : public CullHandler { +public: + INLINE DrawCullHandler(GraphicsStateGuardian *gsg); + + // virtual void begin_decal(); + virtual void record_geom(Geom *geom, const RenderState *state); + // virtual void push_decal(); + // virtual void pop_decal(); + +private: + GraphicsStateGuardian *_gsg; +}; + +#include "drawCullHandler.I" + +#endif + + + diff --git a/panda/src/display/graphicsChannel.I b/panda/src/display/graphicsChannel.I index 3f5952b0d4..80388afc36 100644 --- a/panda/src/display/graphicsChannel.I +++ b/panda/src/display/graphicsChannel.I @@ -16,6 +16,7 @@ // //////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////// // Function: GraphicsChannel::set_active // Access: Public @@ -24,7 +25,10 @@ //////////////////////////////////////////////////////////////////// INLINE void GraphicsChannel:: set_active(bool active) { - _is_active = active; + if (active != _is_active) { + _is_active = active; + win_display_regions_changed(); + } } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/display/graphicsChannel.cxx b/panda/src/display/graphicsChannel.cxx index a2716e6472..c866f2856a 100644 --- a/panda/src/display/graphicsChannel.cxx +++ b/panda/src/display/graphicsChannel.cxx @@ -226,3 +226,18 @@ window_resized(int x, int y) { (*li)->channel_resized(x, y); } } + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsChannel::win_display_regions_changed +// Access: Public +// Description: Intended to be called when the active state on a +// nested channel or layer or display region changes, +// forcing the window to recompute its list of active +// display regions. +//////////////////////////////////////////////////////////////////// +void GraphicsChannel:: +win_display_regions_changed() { + if (_window != (GraphicsWindow *)NULL) { + _window->win_display_regions_changed(); + } +} diff --git a/panda/src/display/graphicsChannel.h b/panda/src/display/graphicsChannel.h index 5c3f006933..a14a61229c 100644 --- a/panda/src/display/graphicsChannel.h +++ b/panda/src/display/graphicsChannel.h @@ -36,6 +36,7 @@ class GraphicsChannel; class GraphicsPipe; class GraphicsWindow; +class CullHandler; //////////////////////////////////////////////////////////////////// // Class : GraphicsChannel @@ -67,6 +68,8 @@ PUBLISHED: public: virtual void window_resized(int x, int y); + void win_display_regions_changed(); + PUBLISHED: INLINE void set_active(bool active); INLINE bool is_active() const; diff --git a/panda/src/display/graphicsEngine.I b/panda/src/display/graphicsEngine.I new file mode 100644 index 0000000000..4f0a1010e6 --- /dev/null +++ b/panda/src/display/graphicsEngine.I @@ -0,0 +1,18 @@ +// Filename: graphicsEngine.I +// Created by: drose (24Feb02) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + diff --git a/panda/src/display/graphicsEngine.cxx b/panda/src/display/graphicsEngine.cxx new file mode 100644 index 0000000000..e04b848984 --- /dev/null +++ b/panda/src/display/graphicsEngine.cxx @@ -0,0 +1,156 @@ +// Filename: graphicsEngine.cxx +// Created by: drose (24Feb02) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#include "graphicsEngine.h" +#include "pipeline.h" +#include "drawCullHandler.h" +#include "qpcullTraverser.h" + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsEngine::Constructor +// Access: Published +// Description: Creates a new GraphicsEngine object. The Pipeline is +// normally left to default to NULL, which indicates the +// global render pipeline, but it may be any Pipeline +// you choose. +//////////////////////////////////////////////////////////////////// +GraphicsEngine:: +GraphicsEngine(Pipeline *pipeline) : + _pipeline(pipeline) +{ + if (_pipeline == (Pipeline *)NULL) { + _pipeline = Pipeline::get_render_pipeline(); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsEngine::add_window +// Access: Published +// Description: Adds a new window to the set of windows that will be +// processed when render_frame() is called. This also +// increments the reference count to the window. +//////////////////////////////////////////////////////////////////// +void GraphicsEngine:: +add_window(GraphicsWindow *window) { + _windows.insert(window); +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsEngine::remove_window +// Access: Published +// Description: Removes the indicated window from the set of windows +// that will be processed when render_frame() is called. +// This also decrements the reference count to the +// window, allowing the window to be destructed if there +// are no other references to it. +// +// The return value is true if the window was removed, +// false if it was not found. +//////////////////////////////////////////////////////////////////// +bool GraphicsEngine:: +remove_window(GraphicsWindow *window) { + size_t count = _windows.erase(window); + return (count != 0); +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsEngine::render_frame +// Access: Published +// Description: Renders the next frame in all the registered windows, +// and flips all of the frame buffers. +//////////////////////////////////////////////////////////////////// +void GraphicsEngine:: +render_frame() { + cull_and_draw_together(); +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsEngine::cull_and_draw_together +// Access: Private +// Description: An implementation of render_frame() that renders the +// frame with a DrawCullHandler, to cull and draw all +// windows in the same pass. +//////////////////////////////////////////////////////////////////// +void GraphicsEngine:: +cull_and_draw_together() { + Windows::iterator wi; + for (wi = _windows.begin(); wi != _windows.end(); ++wi) { + GraphicsWindow *win = (*wi); + win->clear(); + + int num_display_regions = win->get_num_display_regions(); + for (int i = 0; i < num_display_regions; i++) { + DisplayRegion *dr = win->get_display_region(i); + cull_and_draw_together(win, dr); + } + win->flip(); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsEngine::cull_and_draw_together +// Access: Private +// Description: An implementation of render_frame() that renders the +// frame with a DrawCullHandler, to cull and draw all +// windows in the same pass. +//////////////////////////////////////////////////////////////////// +void GraphicsEngine:: +cull_and_draw_together(GraphicsWindow *win, DisplayRegion *dr) { + Camera *camera = dr->get_camera(); + if (camera == (Camera *)NULL || !camera->is_active()) { + // No camera, no draw. + return; + } + + Lens *lens = camera->get_lens(); + if (lens == (Lens *)NULL) { + // No lens, no draw. + return; + } + + PandaNode *scene = camera->get_qpscene(); + if (scene == (PandaNode *)NULL) { + // No scene, no draw. + return; + } + + GraphicsStateGuardian *gsg = win->get_gsg(); + nassertv(gsg != (GraphicsStateGuardian *)NULL); + + if (!gsg->set_lens(lens)) { + // The lens is inappropriate somehow. + display_cat.error() + << gsg->get_type() << " cannot render with " << lens->get_type() + << "\n"; + return; + } + + DrawCullHandler cull_handler(gsg); + qpCullTraverser trav; + trav.set_cull_handler(&cull_handler); + + // Here we should figure out the world transform: the camera's + // inverse transform. + + DisplayRegionStack old_dr = gsg->push_display_region(dr); + gsg->prepare_display_region(); + + trav.traverse(scene); + + gsg->pop_display_region(old_dr); +} diff --git a/panda/src/display/graphicsEngine.h b/panda/src/display/graphicsEngine.h new file mode 100644 index 0000000000..70bd087150 --- /dev/null +++ b/panda/src/display/graphicsEngine.h @@ -0,0 +1,66 @@ +// Filename: graphicsEngine.h +// Created by: drose (24Feb02) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#ifndef GRAPHICSENGINE_H +#define GRAPHICSENGINE_H + +#include "pandabase.h" +#include "graphicsWindow.h" +#include "pointerTo.h" +#include "pset.h" + +class Pipeline; +class DisplayRegion; + +//////////////////////////////////////////////////////////////////// +// Class : GraphicsEngine +// Description : This class is the main interface to controlling the +// render process. There is typically only one +// GraphicsEngine in an application, and it synchronizes +// rendering to all all of the active windows; although +// it is possible to have multiple GraphicsEngine +// objects if multiple synchronicity groups are +// required. +// +// The GraphicsEngine is responsible for managing the +// cull and draw processes. The application simply +// calls engine->render_frame() and considers it done. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA GraphicsEngine : public Namable { +PUBLISHED: + GraphicsEngine(Pipeline *pipeline = NULL); + + void add_window(GraphicsWindow *window); + bool remove_window(GraphicsWindow *window); + + void render_frame(); + +private: + void cull_and_draw_together(); + void cull_and_draw_together(GraphicsWindow *win, DisplayRegion *dr); + + Pipeline *_pipeline; + + typedef pset Windows; + Windows _windows; +}; + +#include "graphicsEngine.I" + +#endif + diff --git a/panda/src/display/graphicsLayer.I b/panda/src/display/graphicsLayer.I index 20122bd7f7..db655058ee 100644 --- a/panda/src/display/graphicsLayer.I +++ b/panda/src/display/graphicsLayer.I @@ -18,7 +18,7 @@ //////////////////////////////////////////////////////////////////// // Function: GraphicsLayer::get_channel -// Access: Public +// Access: Published // Description: Returns the GraphicsChannel that this layer is // associated with. It is possible that the // GraphicsChannel might have been deleted while an @@ -33,18 +33,21 @@ get_channel() const { //////////////////////////////////////////////////////////////////// // Function: GraphicsLayer::set_active -// Access: Public +// Access: Published // Description: Sets the active flag on the layer. If the layer // is marked as inactive, nothing will be rendered. //////////////////////////////////////////////////////////////////// INLINE void GraphicsLayer:: set_active(bool active) { - _is_active = active; + if (active != _is_active) { + _is_active = active; + win_display_regions_changed(); + } } //////////////////////////////////////////////////////////////////// // Function: GraphicsLayer::is_active -// Access: Public +// Access: Published // Description: Returns the active flag on the layer. //////////////////////////////////////////////////////////////////// INLINE bool GraphicsLayer:: diff --git a/panda/src/display/graphicsLayer.cxx b/panda/src/display/graphicsLayer.cxx index 50ba7ac2a3..abf9b94e97 100644 --- a/panda/src/display/graphicsLayer.cxx +++ b/panda/src/display/graphicsLayer.cxx @@ -93,6 +93,7 @@ GraphicsLayer:: ++dri) { (*dri)->_layer = NULL; } + win_display_regions_changed(); // We don't need to remove ourself from the channel's list of // layers. We must have already been removed, or we wouldn't be @@ -113,6 +114,7 @@ make_display_region() { dr->compute_pixels(win->get_width(), win->get_height()); } _display_regions.push_back(dr); + win_display_regions_changed(); return dr; } @@ -131,6 +133,7 @@ make_display_region(float l, float r, float b, float t) { dr->compute_pixels(win->get_width(), win->get_height()); } _display_regions.push_back(dr); + win_display_regions_changed(); return dr; } @@ -169,6 +172,7 @@ remove_dr(int index) { nassertv(index >= 0 && index < (int)_display_regions.size()); _display_regions[index]->_layer = NULL; _display_regions.erase(_display_regions.begin() + index); + win_display_regions_changed(); } //////////////////////////////////////////////////////////////////// @@ -190,6 +194,7 @@ remove_dr(DisplayRegion *display_region) { if (dri != _display_regions.end()) { display_region->_layer = NULL; _display_regions.erase(dri); + win_display_regions_changed(); return true; } return false; @@ -238,3 +243,18 @@ channel_resized(int x, int y) { (*dri)->compute_pixels(x, y); } } + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsLayer::win_display_regions_changed +// Access: Public +// Description: Intended to be called when the active state on a +// nested channel or layer or display region changes, +// forcing the window to recompute its list of active +// display regions. +//////////////////////////////////////////////////////////////////// +void GraphicsLayer:: +win_display_regions_changed() { + if (_channel != (GraphicsChannel *)NULL) { + _channel->win_display_regions_changed(); + } +} diff --git a/panda/src/display/graphicsLayer.h b/panda/src/display/graphicsLayer.h index ad38bc2ff7..fdd8916c3f 100644 --- a/panda/src/display/graphicsLayer.h +++ b/panda/src/display/graphicsLayer.h @@ -37,6 +37,7 @@ class GraphicsChannel; class GraphicsWindow; class GraphicsPipe; +class CullHandler; //////////////////////////////////////////////////////////////////// // Class : GraphicsLayer @@ -74,6 +75,8 @@ PUBLISHED: public: void channel_resized(int x, int y); + void win_display_regions_changed(); + PUBLISHED: INLINE void set_active(bool active); INLINE bool is_active() const; @@ -109,6 +112,7 @@ private: static TypeHandle _type_handle; friend class GraphicsChannel; + friend class GraphicsWindow; }; #include "graphicsLayer.I" diff --git a/panda/src/display/graphicsStateGuardian.I b/panda/src/display/graphicsStateGuardian.I index d61b3133ee..8564780609 100644 --- a/panda/src/display/graphicsStateGuardian.I +++ b/panda/src/display/graphicsStateGuardian.I @@ -16,7 +16,6 @@ // //////////////////////////////////////////////////////////////////// -#include //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::StateInfo::Constructor @@ -114,6 +113,37 @@ set_state(const AllTransitionsWrapper &new_state) { set_state(new_state.get_transitions()); } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::modify_state +// Access: Public +// Description: Applies the attributes indicated in the state set to +// the current state, and issues the changes to the +// graphics hardware. +// +// Any transitions not mentioned are left unchanged. +//////////////////////////////////////////////////////////////////// +INLINE void GraphicsStateGuardian:: +modify_state(const RenderState *state) { + _qpstate = _qpstate->issue_delta_modify(state, this); +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::set_state +// Access: Public +// Description: Applies the attributes indicated in the state set to +// the current state, and issues the changes to the +// graphics hardware. +// +// The state is taken to be a complete description of +// what the graphics state should be; any transitions +// not mentioned are implicitly reset to their initial +// values. +//////////////////////////////////////////////////////////////////// +INLINE void GraphicsStateGuardian:: +set_state(const RenderState *state) { + _qpstate = _qpstate->issue_delta_set(state, this); +} + /* //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::get_state @@ -168,6 +198,19 @@ get_current_display_region(void) const { return _current_display_region; } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::get_current_lens +// Access: Public +// Description: Returns the current lens being rendered with, as set +// by the last call to push_lens() (or restored by +// pop_lens()). This lens will be made active (if it is +// not already) by a call to prepare_lens(). +//////////////////////////////////////////////////////////////////// +INLINE const Lens *GraphicsStateGuardian:: +get_current_lens() const { + return _current_lens; +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::push_display_region // Access: Public @@ -245,6 +288,65 @@ pop_frame_buffer(FrameBufferStack &node) { node._stack_level = -1; } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::push_lens +// Access: Public +// Description: Saves the current lens information and sets up a new +// lens for rendering. The return value from this +// function must eventually be passed to a matching +// pop_lens() call. +// +// The new lens will not actually be made active for +// rendering until the next call to prepare_lens(). +// This is a state-changing optimization. +//////////////////////////////////////////////////////////////////// +INLINE LensStack GraphicsStateGuardian:: +push_lens(const Lens *lens) { + LensStack old; + old._lens = _current_lens; + old._stack_level = _lens_stack_level; + _lens_stack_level++; + _current_lens = lens; + return old; +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::pop_lens +// Access: Public +// Description: Restores the lens previously in effect, before the +// matching call to push_lens(). +// +// The newly-restored lens will not actually be made +// active for rendering until the next call to +// prepare_lens(). This is a state-changing +// optimization. +//////////////////////////////////////////////////////////////////// +INLINE void GraphicsStateGuardian:: +pop_lens(LensStack &node) { + nassertv(_lens_stack_level > 0); + _lens_stack_level--; + nassertv(node._stack_level == _lens_stack_level); + _current_lens = node._lens; + node._stack_level = -1; +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::set_lens +// Access: Public +// Description: Sets a new lens for rendering without bothering to +// push or pop. This replaces the lens most recently +// pushed, if any. There is no need to call +// prepare_lens() following this call. +// +// The return value is true if the lens is acceptable, +// false if it is not. +//////////////////////////////////////////////////////////////////// +INLINE bool GraphicsStateGuardian:: +set_lens(const Lens *lens) { + _current_lens = lens; + return prepare_lens(); +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::set_coordinate_system // Access: Public diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index 5c04adb92f..cad320d6ad 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -21,6 +21,7 @@ #include "config_display.h" #include "textureContext.h" #include "renderBuffer.h" +#include "colorAttrib.h" #include "clockObject.h" #include "geomNode.h" @@ -93,6 +94,7 @@ GraphicsStateGuardian(GraphicsWindow *win) { _win = win; _coordinate_system = default_coordinate_system; _current_display_region = (DisplayRegion*)0L; + _current_lens = (Lens *)NULL; reset(); } @@ -115,8 +117,10 @@ void GraphicsStateGuardian:: reset() { _display_region_stack_level = 0; _frame_buffer_stack_level = 0; + _lens_stack_level = 0; _state.clear(); + _qpstate = RenderState::make_empty(); _buffer_mask = 0; _color_clear_value.set(gsg_clear_r, gsg_clear_g, gsg_clear_b, 0.0); @@ -125,6 +129,17 @@ reset() { _accum_clear_value.set(0.0, 0.0, 0.0, 0.0); _clear_buffer_type = RenderBuffer::T_back | RenderBuffer::T_depth; _normals_enabled = false; + + //Color and alpha transform variables + _color_transform_enabled = false; + _alpha_transform_enabled = false; + _current_color_mat = LMatrix4f::ident_mat(); + _current_alpha_offset = 0; + _current_alpha_scale = 1; + + _has_scene_graph_color = false; + _issued_color_stale = false; + _vertex_colors_enabled = true; } //////////////////////////////////////////////////////////////////// @@ -761,6 +776,47 @@ void GraphicsStateGuardian:: release_geom(GeomContext *) { } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::clear_framebuffer +// Access: Public, Virtual +// Description: Erases the contents of the framebuffer, according to +// _clear_buffer_type, which is set by +// enable_frame_clear(). +// +// This is used to prepare the framebuffer for drawing +// a new frame. +//////////////////////////////////////////////////////////////////// +void GraphicsStateGuardian:: +clear_framebuffer() { + if (_clear_buffer_type != 0) { + PT(DisplayRegion) win_dr = + _win->make_scratch_display_region(_win->get_width(), _win->get_height()); + nassertv(win_dr != (DisplayRegion*)NULL); + DisplayRegionStack old_dr = push_display_region(win_dr); + prepare_display_region(); + clear(get_render_buffer(_clear_buffer_type)); + pop_display_region(old_dr); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::prepare_lens +// Access: Public, Virtual +// Description: Makes the current lens (whichever lens was most +// recently specified with push_lens()) active, so that +// it will transform future rendered geometry. Normally +// this is only called from the draw process, and +// usually it is called immediately after a call to +// push_lens(). +// +// The return value is true if the lens is acceptable, +// false if it is not. +//////////////////////////////////////////////////////////////////// +bool GraphicsStateGuardian:: +prepare_lens() { + return false; +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::wants_normals // Access: Public, Virtual @@ -784,11 +840,12 @@ wants_texcoords() const { //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::wants_colors // Access: Public, Virtual -// Description: +// Description: Returns true if the GSG should issue geometry color +// commands, false otherwise. //////////////////////////////////////////////////////////////////// bool GraphicsStateGuardian:: wants_colors() const { - return false; + return _vertex_colors_enabled; } //////////////////////////////////////////////////////////////////// @@ -822,6 +879,49 @@ void GraphicsStateGuardian:: end_decal(GeomNode *) { } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::issue_color +// Access: Public, Virtual +// Description: This method is defined in the base class because it +// is likely that this functionality will be used for +// all (or at least most) kinds of +// GraphicsStateGuardians--it's not specific to any one +// rendering backend. +// +// The ColorAttribute just changes the interpretation of +// the color on the vertices, and fiddles with +// _vertex_colors_enabled, etc. +//////////////////////////////////////////////////////////////////// +void GraphicsStateGuardian:: +issue_color(const ColorAttrib *attrib) { + switch (attrib->get_color_type()) { + case ColorAttrib::T_flat: + // Color attribute flat: it specifies a scene graph color that + // overrides the vertex color. + _scene_graph_color = attrib->get_color(); + _has_scene_graph_color = true; + _vertex_colors_enabled = false; + _issued_color_stale = true; + break; + + case ColorAttrib::T_off: + // Color attribute off: it specifies that no scene graph color is + // in effect, and vertex color is not important either. + _has_scene_graph_color = false; + _issued_color_stale = false; + _vertex_colors_enabled = false; + break; + + case ColorAttrib::T_vertex: + // Color attribute vertex: it specifies that vertex color should + // be revealed. + _has_scene_graph_color = false; + _issued_color_stale = false; + _vertex_colors_enabled = true; + break; + } +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::mark_prepared_texture // Access: Protected diff --git a/panda/src/display/graphicsStateGuardian.h b/panda/src/display/graphicsStateGuardian.h index ce66750a08..3984c2e467 100644 --- a/panda/src/display/graphicsStateGuardian.h +++ b/panda/src/display/graphicsStateGuardian.h @@ -24,6 +24,7 @@ #include "savedFrameBuffer.h" #include "frameBufferStack.h" #include "displayRegionStack.h" +#include "lensStack.h" #include "graphicsStateGuardianBase.h" #include "nodeTransition.h" @@ -34,7 +35,9 @@ #include "renderTraverser.h" #include "pStatCollector.h" #include "allTransitionsWrapper.h" +#include "renderState.h" +#include "notify.h" #include "pvector.h" class AllTransitionsWrapper; @@ -101,8 +104,10 @@ public: virtual void clear(const RenderBuffer &buffer)=0; virtual void clear(const RenderBuffer &buffer, const DisplayRegion* region)=0; + virtual void clear_framebuffer(); virtual void prepare_display_region()=0; + virtual bool prepare_lens(); virtual void render_frame()=0; virtual void render_scene(Node *root, LensNode *projnode)=0; @@ -119,27 +124,32 @@ public: // These functions will be queried by the GeomIssuer to determine if // it should issue normals, texcoords, and/or colors, based on the // GSG's current state. - virtual bool wants_normals(void) const; - virtual bool wants_texcoords(void) const; - virtual bool wants_colors(void) const; + virtual bool wants_normals() const; + virtual bool wants_texcoords() const; + virtual bool wants_colors() const; virtual void begin_decal(GeomNode *base_geom, AllTransitionsWrapper &attrib); virtual void end_decal(GeomNode *base_geom); virtual void reset(); + // *** QP void modify_state(const NodeTransitions &new_state); // void modify_state(const NodeTransitionCache &new_state); void set_state(const NodeTransitionCache &new_state); INLINE void set_state(const AllTransitionsWrapper &new_state); // INLINE const NodeTransitionCache *get_state() const; + INLINE void modify_state(const RenderState *state); + INLINE void set_state(const RenderState *state); + RenderBuffer get_render_buffer(int buffer_type); INLINE LensNode *get_current_camera(void) const ; INLINE const Node* get_current_root_node(void) const; INLINE const DisplayRegion *get_current_display_region(void) const; + INLINE const Lens *get_current_lens() const; INLINE DisplayRegionStack push_display_region(const DisplayRegion *dr); INLINE void pop_display_region(DisplayRegionStack &node); @@ -147,6 +157,10 @@ public: const DisplayRegion *dr); INLINE void pop_frame_buffer(FrameBufferStack &node); + INLINE LensStack push_lens(const Lens *lens); + INLINE void pop_lens(LensStack &stack); + INLINE bool set_lens(const Lens *lens); + INLINE void set_coordinate_system(CoordinateSystem cs); INLINE CoordinateSystem get_coordinate_system() const; @@ -159,6 +173,8 @@ public: INLINE void clear_cached_state(void) { _state.clear(); }; + virtual void issue_color(const ColorAttrib *attrib); + protected: virtual PT(SavedFrameBuffer) save_frame_buffer(const RenderBuffer &buffer, CPT(DisplayRegion) dr)=0; @@ -207,6 +223,8 @@ protected: typedef pvector State; State _state; + CPT(RenderState) _qpstate; + int _buffer_mask; Colorf _color_clear_value; float _depth_clear_value; @@ -216,6 +234,7 @@ protected: int _display_region_stack_level; int _frame_buffer_stack_level; + int _lens_stack_level; GraphicsWindow *_win; PT(RenderTraverser) _render_traverser; @@ -225,11 +244,24 @@ protected: LensNode *_current_camera; CPT(DisplayRegion) _current_display_region; + CPT(Lens) _current_lens; + // This is used by wants_normals() bool _normals_enabled; CoordinateSystem _coordinate_system; + Colorf _scene_graph_color; + bool _has_scene_graph_color; + bool _issued_color_stale; + bool _vertex_colors_enabled; + + bool _color_transform_enabled; + bool _alpha_transform_enabled; + LMatrix4f _current_color_mat; + float _current_alpha_offset; + float _current_alpha_scale; + public: // Statistics static PStatCollector _total_texusage_pcollector; diff --git a/panda/src/display/graphicsWindow.I b/panda/src/display/graphicsWindow.I index acbaf3032f..a538985b57 100644 --- a/panda/src/display/graphicsWindow.I +++ b/panda/src/display/graphicsWindow.I @@ -418,6 +418,19 @@ render_and_update() { update(); } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsWindow::win_display_regions_changed +// Access: Public +// Description: Intended to be called when the active state on a +// nested channel or layer or display region changes, +// forcing the window to recompute its list of active +// display regions. +//////////////////////////////////////////////////////////////////// +INLINE void GraphicsWindow:: +win_display_regions_changed() { + _display_regions_stale = true; +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsWindow::set_sync // Access: Public @@ -441,3 +454,45 @@ get_sync() const { return _is_synced; } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsWindow::get_num_display_regions +// Access: Published +// Description: Returns the number of active DisplayRegions that have +// been created within the various layers and channels +// of the window. +//////////////////////////////////////////////////////////////////// +INLINE int GraphicsWindow:: +get_num_display_regions() const { + determine_display_regions(); + return _display_regions.size(); +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsWindow::get_display_region +// Access: Published +// Description: Returns the nth active DisplayRegion of those that +// have been created within the various layers and +// channels of the window. +//////////////////////////////////////////////////////////////////// +INLINE DisplayRegion *GraphicsWindow:: +get_display_region(int n) const { + determine_display_regions(); + nassertr(n >= 0 && n < (int)_display_regions.size(), NULL); + return _display_regions[n]; +} + + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsWindow::determine_display_regions +// Access: Private +// Description: Recomputes the list of active DisplayRegions within +// the window, if they have changed recently. +//////////////////////////////////////////////////////////////////// +INLINE void GraphicsWindow:: +determine_display_regions() const { + // This function isn't strictly speaking const, but we pretend it is + // because it only updates a transparent cache value. + if (_display_regions_stale) { + ((GraphicsWindow *)this)->do_determine_display_regions(); + } +} diff --git a/panda/src/display/graphicsWindow.cxx b/panda/src/display/graphicsWindow.cxx index 7f6e7453c0..52e60ca33e 100644 --- a/panda/src/display/graphicsWindow.cxx +++ b/panda/src/display/graphicsWindow.cxx @@ -142,6 +142,7 @@ GraphicsWindow(GraphicsPipe *pipe) : Configurable() { _idle_callback = NULL; _frame_number = 0; _is_synced = false; + _display_regions_stale = false; } //////////////////////////////////////////////////////////////////// @@ -350,6 +351,40 @@ declare_channel(int index, GraphicsChannel *chan) { _channels[index] = chan; } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsWindow::do_determine_display_regions +// Access: Private +// Description: Recomputes the list of active DisplayRegions within +// the window. +//////////////////////////////////////////////////////////////////// +void GraphicsWindow:: +do_determine_display_regions() { + _display_regions.clear(); + Channels::const_iterator ci; + for (ci = _channels.begin(); ci != _channels.end(); ++ci) { + GraphicsChannel *chan = (*ci); + if (chan->is_active()) { + GraphicsChannel::GraphicsLayers::const_iterator li; + for (li = chan->_layers.begin(); li != chan->_layers.end(); ++li) { + GraphicsLayer *layer = (*li); + if (layer->is_active()) { + GraphicsLayer::DisplayRegions::const_iterator dri; + for (dri = layer->_display_regions.begin(); + dri != layer->_display_regions.end(); + ++dri) { + DisplayRegion *dr = (*dri); + if (dr->is_active()) { + _display_regions.push_back(dr); + } + } + } + } + } + } + + _display_regions_stale = false; +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsWindow::register_draw_function // Access: Public, Virtual @@ -413,6 +448,33 @@ void GraphicsWindow:: update() { } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsWindow::clear +// Access: Public +// Description: Invokes the GSG to clear the entire contents of the +// window prior to drawing into it. This is normally +// called only by the draw process at the beginning of +// the frame. +//////////////////////////////////////////////////////////////////// +void GraphicsWindow:: +clear() { + _gsg->clear_framebuffer(); +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsWindow::flip +// Access: Public, Virtual +// Description: Flips the back buffer and front buffer, or does +// whatever other processing is appropriate, after the +// frame has been completely drawn. Normally this is +// only called by the draw process between frames, in +// sync with all the other windows. +//////////////////////////////////////////////////////////////////// +void GraphicsWindow:: +flip() { + end_frame(); +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsWindow::begin_frame // Access: Public, Virtual diff --git a/panda/src/display/graphicsWindow.h b/panda/src/display/graphicsWindow.h index 1001cc5a5d..e5af6d657c 100644 --- a/panda/src/display/graphicsWindow.h +++ b/panda/src/display/graphicsWindow.h @@ -63,6 +63,7 @@ enum WindowModeType class GraphicsPipe; class GraphicsWindow; +class CullHandler; //////////////////////////////////////////////////////////////////// // Class : GraphicsWindow @@ -109,14 +110,10 @@ public: public: GraphicsWindow(GraphicsPipe*); -#ifdef WIN32_VC GraphicsWindow(GraphicsPipe*, const Properties&); -#else - GraphicsWindow(GraphicsPipe*, const GraphicsWindow::Properties&); -#endif virtual ~GraphicsWindow(); - INLINE const GraphicsWindow::Properties& get_properties() const; + INLINE const Properties& get_properties() const; PUBLISHED: INLINE int get_width() const; @@ -191,17 +188,24 @@ PUBLISHED: virtual void register_draw_function(GraphicsWindow::vfn); virtual void register_idle_function(GraphicsWindow::vfn); + // Old-style scene graph rendering (will be phased out eventually). virtual void main_loop(); virtual bool supports_update() const; virtual void update(); INLINE void render_and_update(); public: + // New-style scene graph rendering (not yet complete). + void clear(); + virtual void flip(); + virtual void begin_frame(); virtual void end_frame(); virtual void deactivate_window(void); virtual void reactivate_window(void); + INLINE void win_display_regions_changed(); + // Statistics static PStatCollector _app_pcollector; static PStatCollector _show_code_pcollector; @@ -241,13 +245,23 @@ PUBLISHED: int get_max_channel_index() const; bool is_channel_defined(int index) const; + INLINE int get_num_display_regions() const; + INLINE DisplayRegion *get_display_region(int n) const; + protected: void declare_channel(int index, GraphicsChannel *chan); private: + INLINE void determine_display_regions() const; + void do_determine_display_regions(); + typedef pvector< PT(GraphicsChannel) > Channels; Channels _channels; + typedef pvector DisplayRegions; + DisplayRegions _display_regions; + bool _display_regions_stale; + public: // factory stuff diff --git a/panda/src/display/lensStack.I b/panda/src/display/lensStack.I new file mode 100644 index 0000000000..38f75be452 --- /dev/null +++ b/panda/src/display/lensStack.I @@ -0,0 +1,61 @@ +// Filename: lensStack.I +// Created by: drose (25Feb02) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + + + +//////////////////////////////////////////////////////////////////// +// Function: LensStack::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE LensStack:: +LensStack() { + _stack_level = -1; +} + +//////////////////////////////////////////////////////////////////// +// Function: LensStack::Destructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE LensStack:: +~LensStack() { +} + +//////////////////////////////////////////////////////////////////// +// Function: LensStack::Copy Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE LensStack:: +LensStack(const LensStack ©) : + _lens(copy._lens), + _stack_level(copy._stack_level) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: LensStack::Copy Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE void LensStack:: +operator =(const LensStack ©) { + _lens = copy._lens; + _stack_level = copy._stack_level; +} diff --git a/panda/src/display/lensStack.h b/panda/src/display/lensStack.h new file mode 100644 index 0000000000..77e8657ba2 --- /dev/null +++ b/panda/src/display/lensStack.h @@ -0,0 +1,50 @@ +// Filename: lensStack.h +// Created by: drose (25Feb02) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://www.panda3d.org/license.txt . +// +// To contact the maintainers of this program write to +// panda3d@yahoogroups.com . +// +//////////////////////////////////////////////////////////////////// + +#ifndef LENSSTACK_H +#define LENSSTACK_H + +#include + +#include "lens.h" + +class GraphicsStateGuardian; + +//////////////////////////////////////////////////////////////////// +// Class : LensStack +// Description : An instance of this kind of object is returned by +// GraphicsStateGuardian::push_lens(). It holds the +// information needed to restore the previous display +// region in the subsequent matching call to pop_lens(). +//////////////////////////////////////////////////////////////////// +class LensStack { +public: + INLINE LensStack(); + INLINE ~LensStack(); + INLINE LensStack(const LensStack ©); + INLINE void operator =(const LensStack ©); + +private: + CPT(Lens) _lens; + int _stack_level; + friend class GraphicsStateGuardian; +}; + +#include "lensStack.I" + +#endif diff --git a/panda/src/glgsg/glGraphicsStateGuardian.cxx b/panda/src/glgsg/glGraphicsStateGuardian.cxx index 8565f2a4dd..59bcf40c86 100644 --- a/panda/src/glgsg/glGraphicsStateGuardian.cxx +++ b/panda/src/glgsg/glGraphicsStateGuardian.cxx @@ -65,6 +65,7 @@ #include "stencilTransition.h" #include "pointShapeTransition.h" #include "polygonOffsetTransition.h" +#include "textureAttrib.h" #include "clockObject.h" #include "string_utils.h" #include "dcast.h" @@ -300,17 +301,6 @@ reset() { _current_projection_mat = LMatrix4f::ident_mat(); _projection_mat_stack_count = 0; - //Color and alpha transform variables - _color_transform_enabled = false; - _alpha_transform_enabled = false; - _current_color_mat = LMatrix4f::ident_mat(); - _current_alpha_offset = 0; - _current_alpha_scale = 1; - - _has_scene_graph_color = false; - _issued_color_stale = false; - _vertex_colors_enabled = true; - // Make sure the GL state matches all of our initial attribute // states. PT(DepthTestTransition) dta = new DepthTestTransition; @@ -462,6 +452,51 @@ prepare_display_region() { } } +//////////////////////////////////////////////////////////////////// +// Function: GLGraphicsStateGuardian::prepare_lens +// Access: Public, Virtual +// Description: Makes the current lens (whichever lens was most +// recently specified with push_lens()) active, so that +// it will transform future rendered geometry. Normally +// this is only called from the draw process, and +// usually it is called immediately after a call to +// push_lens(). +// +// The return value is true if the lens is acceptable, +// false if it is not. +//////////////////////////////////////////////////////////////////// +bool GLGraphicsStateGuardian:: +prepare_lens() { + if (_current_lens == (Lens *)NULL) { + return false; + } + + if (!_current_lens->is_linear()) { + return false; + } + + const LMatrix4f &projection_mat = _current_lens->get_projection_mat(); + + // The projection matrix must always be right-handed Y-up, even if + // our coordinate system of choice is otherwise, because certain GL + // calls (specifically glTexGen(GL_SPHERE_MAP)) assume this kind of + // a coordinate system. Sigh. In order to implement a Z-up (or + // other arbitrary) coordinate system, we'll use a Y-up projection + // matrix, and store the conversion to our coordinate system of + // choice in the modelview matrix. + LMatrix4f new_projection_mat = + LMatrix4f::convert_mat(CS_yup_right, _current_lens->get_coordinate_system()) * + projection_mat; + +#ifdef GSG_VERBOSE + glgsg_cat.debug() + << "glMatrixMode(GL_PROJECTION): " << new_projection_mat << endl; +#endif + glMatrixMode(GL_PROJECTION); + glLoadMatrixf(new_projection_mat.get_data()); + + return true; +} //////////////////////////////////////////////////////////////////// @@ -498,16 +533,8 @@ render_frame() { clear_attribute(TextureTransition::get_class_type()); #endif - if (_clear_buffer_type != 0) { - // First, clear the entire window. - PT(DisplayRegion) win_dr = - _win->make_scratch_display_region(_win->get_width(), _win->get_height()); - nassertv(win_dr != (DisplayRegion*)NULL); - DisplayRegionStack old_dr = push_display_region(win_dr); - prepare_display_region(); - clear(get_render_buffer(_clear_buffer_type)); - pop_display_region(old_dr); - } + // First, clear the entire window. + clear_framebuffer(); // Now render each of our layers in order. int max_channel_index = _win->get_max_channel_index(); @@ -624,38 +651,16 @@ render_subgraph(RenderTraverser *traverser, // activate(); Lens *lens = projnode->get_lens(); - if (!lens->is_linear()) { + LensNode *old_camera = _current_camera; + _current_camera = projnode; + + LensStack lens_stack = push_lens(lens); + if (!prepare_lens()) { glgsg_cat.error() << "Cannot render with a nonlinear lens!\n"; return; } - LensNode *old_camera = _current_camera; - _current_camera = projnode; - LMatrix4f old_projection_mat = _current_projection_mat; - - const LMatrix4f &projection_mat = lens->get_projection_mat(); - - // The projection matrix must always be right-handed Y-up, even if - // our coordinate system of choice is otherwise, because certain GL - // calls (specifically glTexGen(GL_SPHERE_MAP)) assume this kind of - // a coordinate system. Sigh. In order to implement a Z-up (or - // other arbitrary) coordinate system, we'll use a Y-up projection - // matrix, and store the conversion to our coordinate system of - // choice in the modelview matrix. - _current_projection_mat = - LMatrix4f::convert_mat(CS_yup_right, lens->get_coordinate_system()) * - projection_mat; - _projection_mat_stack_count++; - - // We load the projection matrix directly. -#ifdef GSG_VERBOSE - glgsg_cat.debug() - << "glMatrixMode(GL_PROJECTION): " << _current_projection_mat << endl; -#endif - glMatrixMode(GL_PROJECTION); - glLoadMatrixf(_current_projection_mat.get_data()); - // We infer the modelview matrix by doing a wrt on the lens // node. LMatrix4f modelview_mat; @@ -677,18 +682,8 @@ render_subgraph(RenderTraverser *traverser, render_subgraph(traverser, subgraph, sub_trans); _current_camera = old_camera; - _current_projection_mat = old_projection_mat; - _projection_mat_stack_count--; - - // We must now restore the projection matrix from before. We could - // do a push/pop matrix, but OpenGL doesn't promise more than 2 - // levels in the projection matrix stack, so we'd better do it in - // the CPU. - if (_projection_mat_stack_count > 0) { - glMatrixMode(GL_PROJECTION); - glLoadMatrixf(_current_projection_mat.get_data()); - } + pop_lens(lens_stack); } //////////////////////////////////////////////////////////////////// @@ -3420,6 +3415,24 @@ issue_polygon_offset(const PolygonOffsetTransition *attrib) { report_errors(); } +//////////////////////////////////////////////////////////////////// +// Function: GLGraphicsStateGuardian::issue_texture +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void GLGraphicsStateGuardian:: +issue_texture(const TextureAttrib *attrib) { + if (attrib->is_off()) { + enable_texturing(false); + } else { + enable_texturing(true); + Texture *tex = attrib->get_texture(); + nassertv(tex != (Texture *)NULL); + tex->apply(this); + } + report_errors(); +} + //////////////////////////////////////////////////////////////////// // Function: GLGraphicsStateGuardian::wants_normals // Access: Public, Virtual @@ -3440,17 +3453,6 @@ wants_texcoords() const { return _texturing_enabled; } -//////////////////////////////////////////////////////////////////// -// Function: GLGraphicsStateGuardian::wants_colors -// Access: Public, Virtual -// Description: Returns true if the GSG should issue geometry color -// commands, false otherwise. -//////////////////////////////////////////////////////////////////// -bool GLGraphicsStateGuardian:: -wants_colors() const { - return _vertex_colors_enabled; -} - //////////////////////////////////////////////////////////////////// // Function: GLGraphicsStateGuardian::begin_decal // Access: Public, Virtual diff --git a/panda/src/glgsg/glGraphicsStateGuardian.h b/panda/src/glgsg/glGraphicsStateGuardian.h index de4ffe09f4..2d1110fc6c 100644 --- a/panda/src/glgsg/glGraphicsStateGuardian.h +++ b/panda/src/glgsg/glGraphicsStateGuardian.h @@ -74,6 +74,7 @@ public: virtual void clear(const RenderBuffer &buffer, const DisplayRegion* region); virtual void prepare_display_region(); + virtual bool prepare_lens(); virtual void render_frame(); virtual void render_scene(Node *root, LensNode *projnode); @@ -155,9 +156,10 @@ public: virtual void issue_point_shape(const PointShapeTransition *attrib); virtual void issue_polygon_offset(const PolygonOffsetTransition *attrib); + virtual void issue_texture(const TextureAttrib *attrib); + virtual bool wants_normals(void) const; virtual bool wants_texcoords(void) const; - virtual bool wants_colors(void) const; virtual void begin_decal(GeomNode *base_geom, AllTransitionsWrapper &attrib); virtual void end_decal(GeomNode *base_geom); @@ -326,8 +328,6 @@ protected: bool _dithering_enabled; bool _alpha_test_enabled; bool _polygon_offset_enabled; - bool _color_transform_enabled; - bool _alpha_transform_enabled; int _decal_level; class LightInfo { @@ -353,15 +353,6 @@ protected: CPT(DisplayRegion) _actual_display_region; - LMatrix4f _current_color_mat; - float _current_alpha_offset; - float _current_alpha_scale; - - Colorf _scene_graph_color; - bool _has_scene_graph_color; - bool _issued_color_stale; - bool _vertex_colors_enabled; - int _pass_number; public: diff --git a/panda/src/gsgbase/graphicsStateGuardianBase.h b/panda/src/gsgbase/graphicsStateGuardianBase.h index 8444cfa8ca..e560130540 100644 --- a/panda/src/gsgbase/graphicsStateGuardianBase.h +++ b/panda/src/gsgbase/graphicsStateGuardianBase.h @@ -75,6 +75,9 @@ class LinesmoothTransition; class PointShapeTransition; class PolygonOffsetTransition; +class TextureAttrib; +class ColorAttrib; + class Node; class GeomNode; class PointLight; @@ -188,6 +191,9 @@ public: virtual void issue_point_shape(const PointShapeTransition *) { } virtual void issue_polygon_offset(const PolygonOffsetTransition *) { } + virtual void issue_texture(const TextureAttrib *) { } + virtual void issue_color(const ColorAttrib *) { } + PUBLISHED: static TypeHandle get_class_type() { return _type_handle; diff --git a/panda/src/pgraph/Sources.pp b/panda/src/pgraph/Sources.pp index b5043c5d0f..b8dcc3494e 100644 --- a/panda/src/pgraph/Sources.pp +++ b/panda/src/pgraph/Sources.pp @@ -1,6 +1,6 @@ #define OTHER_LIBS interrogatedb:c dconfig:c dtoolconfig:m \ dtoolutil:c dtoolbase:c dtool:m -#define LOCAL_LIBS gobj putil graph linmath express pandabase +#define LOCAL_LIBS gsgbase gobj putil graph linmath express pandabase #begin lib_target #define TARGET pgraph diff --git a/panda/src/pgraph/colorAttrib.cxx b/panda/src/pgraph/colorAttrib.cxx index b8b7565532..d9e21fca4e 100644 --- a/panda/src/pgraph/colorAttrib.cxx +++ b/panda/src/pgraph/colorAttrib.cxx @@ -17,6 +17,7 @@ //////////////////////////////////////////////////////////////////// #include "colorAttrib.h" +#include "graphicsStateGuardianBase.h" #include "dcast.h" #include "bamReader.h" #include "bamWriter.h" @@ -63,6 +64,20 @@ make_off() { return return_new(attrib); } +//////////////////////////////////////////////////////////////////// +// Function: ColorAttrib::issue +// Access: Public, Virtual +// Description: Calls the appropriate method on the indicated GSG +// to issue the graphics commands appropriate to the +// given attribute. This is normally called +// (indirectly) only from +// GraphicsStateGuardian::set_state() or modify_state(). +//////////////////////////////////////////////////////////////////// +void ColorAttrib:: +issue(GraphicsStateGuardianBase *gsg) const { + gsg->issue_color(this); +} + //////////////////////////////////////////////////////////////////// // Function: ColorAttrib::output // Access: Public, Virtual diff --git a/panda/src/pgraph/colorAttrib.h b/panda/src/pgraph/colorAttrib.h index ea43e559ce..682a4b50dd 100644 --- a/panda/src/pgraph/colorAttrib.h +++ b/panda/src/pgraph/colorAttrib.h @@ -48,6 +48,7 @@ PUBLISHED: INLINE const Colorf &get_color() const; public: + virtual void issue(GraphicsStateGuardianBase *gsg) const; virtual void output(ostream &out) const; protected: diff --git a/panda/src/pgraph/cullHandler.cxx b/panda/src/pgraph/cullHandler.cxx index 93aae74b1b..41ff6061c6 100644 --- a/panda/src/pgraph/cullHandler.cxx +++ b/panda/src/pgraph/cullHandler.cxx @@ -21,7 +21,7 @@ #include "renderState.h" //////////////////////////////////////////////////////////////////// -// Function: CullHandler::found_geom +// Function: CullHandler::record_geom // Access: Public, Virtual // Description: This callback function is intended to be overridden // by a derived class. This is called as each Geom is @@ -31,6 +31,6 @@ // it's not intended to be used except for debugging. //////////////////////////////////////////////////////////////////// void CullHandler:: -found_geom(Geom *geom, const RenderState *state) { +record_geom(Geom *geom, const RenderState *state) { cerr << *geom << " " << *state << "\n"; } diff --git a/panda/src/pgraph/cullHandler.h b/panda/src/pgraph/cullHandler.h index 08848d0856..b7e16f6057 100644 --- a/panda/src/pgraph/cullHandler.h +++ b/panda/src/pgraph/cullHandler.h @@ -29,11 +29,14 @@ class RenderState; // Description : This defines the abstract interface for an object // that receives Geoms identified by the CullTraverser. // By itself, it's not a particularly useful class; to -// use it, derive from it and redefine found_geom(). +// use it, derive from it and redefine record_geom(). //////////////////////////////////////////////////////////////////// class EXPCL_PANDA CullHandler { public: - virtual void found_geom(Geom *geom, const RenderState *state); + // virtual void begin_decal(); + virtual void record_geom(Geom *geom, const RenderState *state); + // virtual void push_decal(); + // virtual void pop_decal(); }; #endif diff --git a/panda/src/pgraph/pandaNode.I b/panda/src/pgraph/pandaNode.I index 5f444166d1..c58b64c004 100644 --- a/panda/src/pgraph/pandaNode.I +++ b/panda/src/pgraph/pandaNode.I @@ -187,14 +187,14 @@ get_child(int n) const { } //////////////////////////////////////////////////////////////////// -// Function: PandaNode::get_sort +// Function: PandaNode::get_child_sort // Access: Published // Description: Returns the sort index of the nth child node of this // node (that is, the number that was passed to // add_child()). See get_num_children(). //////////////////////////////////////////////////////////////////// INLINE int PandaNode:: -get_sort(int n) const { +get_child_sort(int n) const { CDReader cdata(_cycler); nassertr(n >= 0 && n < (int)cdata->_down.size(), -1); return cdata->_down[n].get_sort(); diff --git a/panda/src/pgraph/pandaNode.h b/panda/src/pgraph/pandaNode.h index 45d951f67d..9d18a06397 100644 --- a/panda/src/pgraph/pandaNode.h +++ b/panda/src/pgraph/pandaNode.h @@ -55,13 +55,21 @@ PUBLISHED: INLINE int get_num_children() const; INLINE PandaNode *get_child(int n) const; - INLINE int get_sort(int n) const; + INLINE int get_child_sort(int n) const; int find_child(PandaNode *node) const; int add_child(PandaNode *child, int sort = 0); void remove_child(int n); bool remove_child(PandaNode *child); + /* + bool stash_child(PandaNode *child); + bool unstash_child(PandaNode *child); + INLINE int get_num_stashed() const; + INLINE PandaNode *get_stashed(int n) const; + INLINE PandaNode *get_stashed_sort(int n) const; + */ + void remove_all_children(); INLINE void set_attrib(const RenderAttrib *attrib, int override = 0); diff --git a/panda/src/pgraph/pipeline.cxx b/panda/src/pgraph/pipeline.cxx index 9032df9754..0ad94683e2 100644 --- a/panda/src/pgraph/pipeline.cxx +++ b/panda/src/pgraph/pipeline.cxx @@ -42,23 +42,11 @@ Pipeline:: //////////////////////////////////////////////////////////////////// // Function: Pipeline::cycle -// Access: Public +// Access: Public, Virtual // Description: Flows all the pipeline data down to the next stage. //////////////////////////////////////////////////////////////////// void Pipeline:: cycle() { - pre_cycle(); -} - -//////////////////////////////////////////////////////////////////// -// Function: Pipeline::pre_cycle -// Access: Protected, Virtual -// Description: A callback function intended to be overridden by a -// derived class to perform whatever operations should -// be done before cycling the pipeline. -//////////////////////////////////////////////////////////////////// -void Pipeline:: -pre_cycle() { } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/pgraph/pipeline.h b/panda/src/pgraph/pipeline.h index 019cde80bd..64aa2f89be 100644 --- a/panda/src/pgraph/pipeline.h +++ b/panda/src/pgraph/pipeline.h @@ -42,10 +42,7 @@ public: INLINE static Pipeline *get_render_pipeline(); - void cycle(); - -protected: - virtual void pre_cycle(); + virtual void cycle(); private: static void make_render_pipeline(); diff --git a/panda/src/pgraph/qpcullTraverser.cxx b/panda/src/pgraph/qpcullTraverser.cxx index 55e37db904..5ae79738b8 100644 --- a/panda/src/pgraph/qpcullTraverser.cxx +++ b/panda/src/pgraph/qpcullTraverser.cxx @@ -104,7 +104,7 @@ r_traverse(PandaNode *node, const RenderState *state, int flags) { Geom *geom = geom_node->get_geom(i); CPT(RenderState) geom_state = next_state->compose(geom_node->get_geom_state(i)); - _cull_handler->found_geom(geom, geom_state); + _cull_handler->record_geom(geom, geom_state); } } diff --git a/panda/src/pgraph/renderAttrib.I b/panda/src/pgraph/renderAttrib.I index ca1e7f5ff8..7327d4ef0a 100644 --- a/panda/src/pgraph/renderAttrib.I +++ b/panda/src/pgraph/renderAttrib.I @@ -32,6 +32,27 @@ compose(const RenderAttrib *other) const { return compose_impl(other); } +//////////////////////////////////////////////////////////////////// +// Function: RenderAttrib::invert_compose +// Access: Public +// Description: Returns a new RenderAttrib object that represents the +// composition of the inverse of this attrib with the +// other attrib. In most cases, this is the same as the +// other attrib; !a compose b produces b. Some kinds of +// attributes, like a TextureTransform, for instance, +// might produce a new result: !a compose b produces c. +// +// This is similar to compose() except that the source +// attrib is inverted first. This is used to compute +// the relative attribute for one node as viewed from +// some other node, which is especially useful for +// transform-type attributes. +//////////////////////////////////////////////////////////////////// +INLINE CPT(RenderAttrib) RenderAttrib:: +invert_compose(const RenderAttrib *other) const { + return invert_compose_impl(other); +} + //////////////////////////////////////////////////////////////////// // Function: RenderAttrib::make_default // Access: Public diff --git a/panda/src/pgraph/renderAttrib.cxx b/panda/src/pgraph/renderAttrib.cxx index e4b7bb9ba5..3993068044 100644 --- a/panda/src/pgraph/renderAttrib.cxx +++ b/panda/src/pgraph/renderAttrib.cxx @@ -68,8 +68,21 @@ RenderAttrib:: } //////////////////////////////////////////////////////////////////// -// Function: RenderAttrib::output +// Function: RenderAttrib::issue // Access: Public, Virtual +// Description: Calls the appropriate method on the indicated GSG +// to issue the graphics commands appropriate to the +// given attribute. This is normally called +// (indirectly) only from +// GraphicsStateGuardian::set_state() or modify_state(). +//////////////////////////////////////////////////////////////////// +void RenderAttrib:: +issue(GraphicsStateGuardianBase *) const { +} + +//////////////////////////////////////////////////////////////////// +// Function: RenderAttrib::output +// Access: Published, Virtual // Description: //////////////////////////////////////////////////////////////////// void RenderAttrib:: @@ -79,7 +92,7 @@ output(ostream &out) const { //////////////////////////////////////////////////////////////////// // Function: RenderAttrib::write -// Access: Public, Virtual +// Access: Published, Virtual // Description: //////////////////////////////////////////////////////////////////// void RenderAttrib:: @@ -167,6 +180,20 @@ compose_impl(const RenderAttrib *other) const { return other; } +//////////////////////////////////////////////////////////////////// +// Function: RenderAttrib::invert_compose_impl +// Access: Protected, Virtual +// Description: Intended to be overridden by derived RenderAttrib +// types to specify how two consecutive RenderAttrib +// objects of the same type interact. +// +// See invert_compose() and compose_impl(). +//////////////////////////////////////////////////////////////////// +CPT(RenderAttrib) RenderAttrib:: +invert_compose_impl(const RenderAttrib *other) const { + return other; +} + //////////////////////////////////////////////////////////////////// // Function: RenderAttrib::make_default_impl // Access: Protected, Virtual diff --git a/panda/src/pgraph/renderAttrib.h b/panda/src/pgraph/renderAttrib.h index 6686783938..afebd6c86e 100644 --- a/panda/src/pgraph/renderAttrib.h +++ b/panda/src/pgraph/renderAttrib.h @@ -26,6 +26,8 @@ #include "pointerTo.h" #include "pset.h" +class GraphicsStateGuardianBase; + //////////////////////////////////////////////////////////////////// // Class : RenderAttrib // Description : This is the base class for a number of render @@ -54,8 +56,10 @@ public: virtual ~RenderAttrib(); INLINE CPT(RenderAttrib) compose(const RenderAttrib *other) const; + INLINE CPT(RenderAttrib) invert_compose(const RenderAttrib *other) const; INLINE CPT(RenderAttrib) make_default() const; INLINE int compare_to(const RenderAttrib &other) const; + virtual void issue(GraphicsStateGuardianBase *gsg) const; PUBLISHED: virtual void output(ostream &out) const; @@ -66,6 +70,7 @@ protected: virtual int compare_to_impl(const RenderAttrib *other) const; virtual CPT(RenderAttrib) compose_impl(const RenderAttrib *other) const; + virtual CPT(RenderAttrib) invert_compose_impl(const RenderAttrib *other) const; virtual RenderAttrib *make_default_impl() const=0; private: diff --git a/panda/src/pgraph/renderState.cxx b/panda/src/pgraph/renderState.cxx index c88ade0e5e..4391e181de 100644 --- a/panda/src/pgraph/renderState.cxx +++ b/panda/src/pgraph/renderState.cxx @@ -121,6 +121,18 @@ RenderState:: ++ci; } + // A similar bit of code for the invert cache. + ci = _invert_composition_cache.begin(); + while (ci != _invert_composition_cache.end()) { + { + PT(RenderState) other = (RenderState *)(*ci).first; + Composition comp = (*ci).second; + nassertv(other != (const RenderState *)this); + other->_invert_composition_cache.erase(this); + } + ++ci; + } + // Also, if we called compose(this) at some point and the return // value was something other than this, we need to decrement the // associated reference count. @@ -270,8 +282,6 @@ compose(const RenderState *other) const { // but we pretend that it is because it's only a cache which is // transparent to the rest of the interface. - cerr << "composing " << *this << " with " << *other << "\n"; - // We handle empty state (identity) as a trivial special case. if (is_empty()) { return other; @@ -330,6 +340,68 @@ compose(const RenderState *other) const { ((RenderState *)other)->_composition_cache[this]._result = NULL; ((RenderState *)this)->_composition_cache[other]._result = result; + return result; +} + +//////////////////////////////////////////////////////////////////// +// Function: RenderState::invert_compose +// Access: Published +// Description: Returns a new RenderState object that represents the +// composition of this state's inverse with the other +// state. +// +// This is similar to compose(), but is particularly +// useful for computing the relative state of a node as +// viewed from some other node. +//////////////////////////////////////////////////////////////////// +CPT(RenderState) RenderState:: +invert_compose(const RenderState *other) const { + // This method isn't strictly const, because it updates the cache, + // but we pretend that it is because it's only a cache which is + // transparent to the rest of the interface. + + cerr << "invert composing " << *this << " with " << *other << "\n"; + + // We handle empty state (identity) as a trivial special case. + if (is_empty()) { + return other; + } + // Unlike compose(), the case of other->is_empty() is not quite as + // trivial for invert_compose(). + + if (other == this) { + // a->invert_compose(a) always produces identity. + return make_empty(); + } + + // Is this composition already cached? + CompositionCache::const_iterator ci = _invert_composition_cache.find(other); + if (ci != _invert_composition_cache.end()) { + const Composition &comp = (*ci).second; + if (comp._result == (const RenderState *)NULL) { + // Well, it wasn't cached already, but we already had an entry + // (probably created for the reverse direction), so use the same + // entry to store the new result. + ((Composition &)comp)._result = do_invert_compose(other); + } + // Here's the cache! + cerr << " returning cached result " << (void *)comp._result.p() << "\n"; + return comp._result; + } + + // We need to make a new cache entry, both in this object and in the + // other object. We make both records so the other RenderState + // object will know to delete the entry from this object when it + // destructs, and vice-versa. + + // The cache entry in this object is the only one that indicates the + // result; the other will be NULL for now. + CPT(RenderState) result = do_invert_compose(other); + // We store them in this order, on the off-chance that other is the + // same as this, a degenerate case which is still worth supporting. + ((RenderState *)other)->_invert_composition_cache[this]._result = NULL; + ((RenderState *)this)->_invert_composition_cache[other]._result = result; + cerr << " returning new result " << (void *)result.p() << "\n"; return result; } @@ -396,7 +468,7 @@ remove(TypeHandle type) const { //////////////////////////////////////////////////////////////////// // Function: RenderState::output -// Access: Public, Virtual +// Access: Published, Virtual // Description: //////////////////////////////////////////////////////////////////// void RenderState:: @@ -417,7 +489,7 @@ output(ostream &out) const { //////////////////////////////////////////////////////////////////// // Function: RenderState::write -// Access: Public, Virtual +// Access: Published, Virtual // Description: //////////////////////////////////////////////////////////////////// void RenderState:: @@ -430,6 +502,149 @@ write(ostream &out, int indent_level) const { } } +//////////////////////////////////////////////////////////////////// +// Function: RenderState::issue_delta_modify +// Access: Public +// Description: This is intended to be called only from +// GraphicsStateGuardian::modify_state(). It calls +// issue() for each attribute given in the other state +// that differs from the current state (which is assumed +// to represent the GSG's current state). Returns the +// RenderState representing the newly composed result. +//////////////////////////////////////////////////////////////////// +CPT(RenderState) RenderState:: +issue_delta_modify(const RenderState *other, + GraphicsStateGuardianBase *gsg) const { + if (other == this) { + // If the state doesn't change, that's a trivial special case. + return other; + } + + // First, build a new Attributes member that represents the union of + // this one and that one. + Attributes::const_iterator ai = _attributes.begin(); + Attributes::const_iterator bi = other->_attributes.begin(); + + // Create a new RenderState that will hold the result. + RenderState *new_state = new RenderState; + back_insert_iterator result = + back_inserter(new_state->_attributes); + + bool any_changed = false; + + while (ai != _attributes.end() && bi != other->_attributes.end()) { + if ((*ai) < (*bi)) { + // Here is an attribute that we have in the original, which is + // not present in the secondary. Leave it alone. + *result = *ai; + ++ai; + ++result; + } else if ((*bi) < (*ai)) { + // Here is a new attribute we have in the secondary, that was + // not present in the original. Issue the new one, and save it. + (*bi)._attrib->issue(gsg); + *result = *bi; + ++bi; + ++result; + any_changed = true; + } else { + // Here is an attribute we have in both. Issue the new one if + // it's different, and save it. + if ((*ai)._attrib != (*bi)._attrib) { + any_changed = true; + (*bi)._attrib->issue(gsg); + } + *result = *bi; + ++ai; + ++bi; + ++result; + } + } + + while (ai != _attributes.end()) { + *result = *ai; + ++ai; + ++result; + } + + while (bi != other->_attributes.end()) { + (*bi)._attrib->issue(gsg); + *result = *bi; + ++bi; + ++result; + any_changed = true; + } + + if (any_changed) { + return return_new(new_state); + } else { + delete new_state; + return other; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: RenderState::issue_delta_set +// Access: Public +// Description: This is intended to be called only from +// GraphicsStateGuardian::set_state(). It calls issue() +// for each attribute given in the other state that +// differs from the current state (which is assumed to +// represent the GSG's current state). Returns the +// RenderState representing the newly composed result +// (which will be the same as other). +//////////////////////////////////////////////////////////////////// +CPT(RenderState) RenderState:: +issue_delta_set(const RenderState *other, + GraphicsStateGuardianBase *gsg) const { + if (other->is_empty()) { + // If the other state is empty, that's a trivial special case. + return this; + } + + // We don't need to build a new RenderState, because the return + // value will be exactly other. + + Attributes::const_iterator ai = _attributes.begin(); + Attributes::const_iterator bi = other->_attributes.begin(); + + while (ai != _attributes.end() && bi != other->_attributes.end()) { + if ((*ai) < (*bi)) { + // Here is an attribute that we have in the original, which is + // not present in the secondary. Issue the default state instead. + (*ai)._attrib->make_default()->issue(gsg); + ++ai; + + } else if ((*bi) < (*ai)) { + // Here is a new attribute we have in the secondary, that was + // not present in the original. Issue the new one. + (*bi)._attrib->issue(gsg); + ++bi; + + } else { + // Here is an attribute we have in both. Issue the new one if + // it's different. + if ((*ai)._attrib != (*bi)._attrib) { + (*bi)._attrib->issue(gsg); + } + ++ai; + ++bi; + } + } + + while (ai != _attributes.end()) { + (*ai)._attrib->make_default()->issue(gsg); + ++ai; + } + + while (bi != other->_attributes.end()) { + (*bi)._attrib->issue(gsg); + ++bi; + } + + return other; +} + //////////////////////////////////////////////////////////////////// // Function: RenderState::return_new // Access: Private, Static @@ -513,7 +728,7 @@ do_compose(const RenderState *other) const { } else if (b._override < a._override) { // A overrides. - *result = *bi; + *result = *ai; } else { // No, they're equivalent, so compose them. @@ -540,6 +755,59 @@ do_compose(const RenderState *other) const { return return_new(new_state); } +//////////////////////////////////////////////////////////////////// +// Function: RenderState::do_invert_compose +// Access: Private +// Description: The private implemention of invert_compose(). +//////////////////////////////////////////////////////////////////// +CPT(RenderState) RenderState:: +do_invert_compose(const RenderState *other) const { + Attributes::const_iterator ai = _attributes.begin(); + Attributes::const_iterator bi = other->_attributes.begin(); + + // Create a new RenderState that will hold the result. + RenderState *new_state = new RenderState; + back_insert_iterator result = + back_inserter(new_state->_attributes); + + while (ai != _attributes.end() && bi != other->_attributes.end()) { + if ((*ai) < (*bi)) { + // Here is an attribute that we have in the original, which is + // not present in the secondary. + *result = Attribute((*ai)._attrib->invert_compose((*ai)._attrib->make_default()), 0); + ++ai; + ++result; + } else if ((*bi) < (*ai)) { + // Here is a new attribute we have in the secondary, that was + // not present in the original. + *result = *bi; + ++bi; + ++result; + } else { + // Here is an attribute we have in both. In this case, override + // is meaningless. + *result = Attribute((*ai)._attrib->invert_compose((*bi)._attrib), (*bi)._override); + ++ai; + ++bi; + ++result; + } + } + + while (ai != _attributes.end()) { + *result = Attribute((*ai)._attrib->invert_compose((*ai)._attrib->make_default()), 0); + ++ai; + ++result; + } + + while (bi != other->_attributes.end()) { + *result = *bi; + ++bi; + ++result; + } + + return return_new(new_state); +} + //////////////////////////////////////////////////////////////////// // Function: RenderState::register_with_read_factory // Access: Public, Static diff --git a/panda/src/pgraph/renderState.h b/panda/src/pgraph/renderState.h index 6aba2d290e..61b6634f50 100644 --- a/panda/src/pgraph/renderState.h +++ b/panda/src/pgraph/renderState.h @@ -27,6 +27,8 @@ #include "indirectLess.h" #include "ordered_vector.h" +class GraphicsStateGuardianBase; + //////////////////////////////////////////////////////////////////// // Class : RenderState // Description : This represents a unique collection of RenderAttrib @@ -73,6 +75,7 @@ PUBLISHED: const RenderAttrib *attrib4, int override = 0); CPT(RenderState) compose(const RenderState *other) const; + CPT(RenderState) invert_compose(const RenderState *other) const; CPT(RenderState) add(const RenderAttrib *attrib, int override = 0) const; CPT(RenderState) remove(TypeHandle type) const; @@ -80,9 +83,16 @@ PUBLISHED: void output(ostream &out) const; void write(ostream &out, int indent_level) const; +public: + CPT(RenderState) issue_delta_modify(const RenderState *other, + GraphicsStateGuardianBase *gsg) const; + CPT(RenderState) issue_delta_set(const RenderState *other, + GraphicsStateGuardianBase *gsg) const; + private: static CPT(RenderState) return_new(RenderState *state); CPT(RenderState) do_compose(const RenderState *other) const; + CPT(RenderState) do_invert_compose(const RenderState *other) const; private: typedef pset > States; @@ -106,8 +116,9 @@ private: typedef pmap CompositionCache; CompositionCache _composition_cache; + CompositionCache _invert_composition_cache; - // This pointer is used to cache the result of compose(this). This + // Thise pointer is used to cache the result of compose(this). This // has to be a special case, because we have to handle the reference // counts carefully so that we don't leak. Most of the time, the // result of compose(this) is this, which should not be reference diff --git a/panda/src/pgraph/textureAttrib.cxx b/panda/src/pgraph/textureAttrib.cxx index 667ad7b2e1..9c5381fd26 100644 --- a/panda/src/pgraph/textureAttrib.cxx +++ b/panda/src/pgraph/textureAttrib.cxx @@ -17,6 +17,7 @@ //////////////////////////////////////////////////////////////////// #include "textureAttrib.h" +#include "graphicsStateGuardianBase.h" #include "bamReader.h" #include "bamWriter.h" #include "datagram.h" @@ -49,6 +50,20 @@ make_off() { return return_new(attrib); } +//////////////////////////////////////////////////////////////////// +// Function: TextureAttrib::issue +// Access: Public, Virtual +// Description: Calls the appropriate method on the indicated GSG +// to issue the graphics commands appropriate to the +// given attribute. This is normally called +// (indirectly) only from +// GraphicsStateGuardian::set_state() or modify_state(). +//////////////////////////////////////////////////////////////////// +void TextureAttrib:: +issue(GraphicsStateGuardianBase *gsg) const { + gsg->issue_texture(this); +} + //////////////////////////////////////////////////////////////////// // Function: TextureAttrib::output // Access: Public, Virtual diff --git a/panda/src/pgraph/textureAttrib.h b/panda/src/pgraph/textureAttrib.h index f09214d097..302323c2ba 100644 --- a/panda/src/pgraph/textureAttrib.h +++ b/panda/src/pgraph/textureAttrib.h @@ -42,6 +42,7 @@ PUBLISHED: INLINE Texture *get_texture() const; public: + virtual void issue(GraphicsStateGuardianBase *gsg) const; virtual void output(ostream &out) const; protected: diff --git a/panda/src/sgraph/camera.I b/panda/src/sgraph/camera.I index 1f01231f26..9602cc92d5 100644 --- a/panda/src/sgraph/camera.I +++ b/panda/src/sgraph/camera.I @@ -62,3 +62,27 @@ INLINE Node *Camera:: get_scene() const { return _scene; } + +//////////////////////////////////////////////////////////////////// +// Function: Camera::set_qpscene +// Access: Public +// Description: Sets the scene that will be rendered by the camera. +// This is normally the root node of a scene graph, +// typically a node called 'render', although it could +// represent the root of any subgraph. +//////////////////////////////////////////////////////////////////// +INLINE void Camera:: +set_qpscene(PandaNode *scene) { + _qpscene = scene; +} + +//////////////////////////////////////////////////////////////////// +// Function: Camera::get_qpscene +// Access: Public +// Description: Returns the scene that will be rendered by the +// camera. See set_qpscene(). +//////////////////////////////////////////////////////////////////// +INLINE PandaNode *Camera:: +get_qpscene() const { + return _qpscene; +} diff --git a/panda/src/sgraph/camera.h b/panda/src/sgraph/camera.h index 5d75980517..e79d40db33 100644 --- a/panda/src/sgraph/camera.h +++ b/panda/src/sgraph/camera.h @@ -28,6 +28,7 @@ #include "pvector.h" class DisplayRegion; +class PandaNode; //////////////////////////////////////////////////////////////////// // Class : Camera @@ -56,6 +57,9 @@ PUBLISHED: INLINE void set_scene(Node *scene); INLINE Node *get_scene() const; + INLINE void set_qpscene(PandaNode *scene); + INLINE PandaNode *get_qpscene() const; + int get_num_drs() const; DisplayRegion *get_dr(int index) const; @@ -65,6 +69,7 @@ private: bool _active; PT_Node _scene; + PandaNode *_qpscene; typedef pvector DisplayRegions; DisplayRegions _display_regions; diff --git a/panda/src/testbed/Sources.pp b/panda/src/testbed/Sources.pp index 5b8433d996..a29d8be370 100644 --- a/panda/src/testbed/Sources.pp +++ b/panda/src/testbed/Sources.pp @@ -26,6 +26,15 @@ #end bin_target +#begin test_bin_target + #define TARGET pview + + #define SOURCES \ + pview.cxx + + #define LOCAL_LIBS pgraph $[LOCAL_LIBS] +#end test_bin_target + #begin test_bin_target #define TARGET open_window