From f79661eb9aeb3f3b258ae0c3dbc6f46678b20dd8 Mon Sep 17 00:00:00 2001 From: David Rose Date: Fri, 1 Mar 2002 01:07:07 +0000 Subject: [PATCH] pgraph cull binning --- panda/src/display/displayRegion.h | 8 + panda/src/display/graphicsEngine.cxx | 112 ++++++- panda/src/display/graphicsEngine.h | 3 + panda/src/display/graphicsStateGuardian.cxx | 13 + panda/src/display/graphicsStateGuardian.h | 3 + panda/src/gsgbase/graphicsStateGuardianBase.h | 25 +- panda/src/pgraph/Sources.pp | 15 + panda/src/pgraph/binCullHandler.I | 29 ++ panda/src/pgraph/binCullHandler.cxx | 33 ++ panda/src/pgraph/binCullHandler.h | 53 +++ panda/src/pgraph/config_pgraph.cxx | 6 +- panda/src/pgraph/config_pgraph.h | 2 + panda/src/pgraph/cullBin.I | 29 ++ panda/src/pgraph/cullBin.cxx | 75 +++++ panda/src/pgraph/cullBin.h | 81 +++++ panda/src/pgraph/cullBinManager.I | 125 +++++++ panda/src/pgraph/cullBinManager.cxx | 309 ++++++++++++++++++ panda/src/pgraph/cullBinManager.h | 105 ++++++ panda/src/pgraph/cullBinUnsorted.I | 44 +++ panda/src/pgraph/cullBinUnsorted.cxx | 52 +++ panda/src/pgraph/cullBinUnsorted.h | 81 +++++ panda/src/pgraph/cullHandler.cxx | 11 + panda/src/pgraph/cullHandler.h | 2 + panda/src/pgraph/cullResult.I | 69 ++++ panda/src/pgraph/cullResult.cxx | 121 +++++++ panda/src/pgraph/cullResult.h | 80 +++++ panda/src/pgraph/pgraph_composite1.cxx | 10 +- panda/src/pgraph/pgraph_composite2.cxx | 5 + panda/src/pgraph/renderState.I | 19 ++ panda/src/pgraph/renderState.cxx | 43 +++ panda/src/pgraph/renderState.h | 9 + panda/src/testbed/pview.cxx | 2 +- 32 files changed, 1557 insertions(+), 17 deletions(-) create mode 100644 panda/src/pgraph/binCullHandler.I create mode 100644 panda/src/pgraph/binCullHandler.cxx create mode 100644 panda/src/pgraph/binCullHandler.h create mode 100644 panda/src/pgraph/cullBin.I create mode 100644 panda/src/pgraph/cullBin.cxx create mode 100644 panda/src/pgraph/cullBin.h create mode 100644 panda/src/pgraph/cullBinManager.I create mode 100644 panda/src/pgraph/cullBinManager.cxx create mode 100644 panda/src/pgraph/cullBinManager.h create mode 100644 panda/src/pgraph/cullBinUnsorted.I create mode 100644 panda/src/pgraph/cullBinUnsorted.cxx create mode 100644 panda/src/pgraph/cullBinUnsorted.h create mode 100644 panda/src/pgraph/cullResult.I create mode 100644 panda/src/pgraph/cullResult.cxx create mode 100644 panda/src/pgraph/cullResult.h diff --git a/panda/src/display/displayRegion.h b/panda/src/display/displayRegion.h index a363ccf00a..bc80dc3364 100644 --- a/panda/src/display/displayRegion.h +++ b/panda/src/display/displayRegion.h @@ -23,6 +23,8 @@ #include "referenceCount.h" #include "camera.h" #include "nodeChain.h" +#include "cullResult.h" +#include "pointerTo.h" #include "plist.h" @@ -108,7 +110,13 @@ protected: bool _active; + // This is used to cache the culling result from last frame's + // drawing into this display region. It should only be accessed or + // modified by the GraphicsEngine, during the cull traversal. + PT(CullResult) _cull_result; + friend class GraphicsLayer; + friend class GraphicsEngine; }; INLINE ostream &operator << (ostream &out, const DisplayRegion &dr); diff --git a/panda/src/display/graphicsEngine.cxx b/panda/src/display/graphicsEngine.cxx index 67c7f6d1ca..7f3dbf9fb0 100644 --- a/panda/src/display/graphicsEngine.cxx +++ b/panda/src/display/graphicsEngine.cxx @@ -19,6 +19,8 @@ #include "graphicsEngine.h" #include "pipeline.h" #include "drawCullHandler.h" +#include "binCullHandler.h" +#include "cullResult.h" #include "qpcullTraverser.h" #include "clockObject.h" @@ -77,7 +79,8 @@ remove_window(GraphicsWindow *window) { //////////////////////////////////////////////////////////////////// void GraphicsEngine:: render_frame() { - cull_and_draw_together(); + // cull_and_draw_together(); + cull_bin_draw(); // **** This doesn't belong here; it really belongs in the Pipeline, // but here it is for now. @@ -180,3 +183,110 @@ cull_and_draw_together(GraphicsWindow *win, DisplayRegion *dr) { gsg->pop_display_region(old_dr); } + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsEngine::cull_bin_draw +// Access: Private +// Description: An implementation of render_frame() that renders the +// frame with a BinCullHandler, to cull into bins and +// then draw the bins. This is the normal method. +//////////////////////////////////////////////////////////////////// +void GraphicsEngine:: +cull_bin_draw() { + 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_bin_draw(win, dr); + } + win->flip(); + win->process_events(); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsEngine::cull_bin_draw +// Access: Private +// Description: An implementation of render_frame() that renders the +// frame with a BinCullHandler, to cull into bins and +// then draw the bins. This is the normal method. +//////////////////////////////////////////////////////////////////// +void GraphicsEngine:: +cull_bin_draw(GraphicsWindow *win, DisplayRegion *dr) { + const NodeChain &camera = dr->get_qpcamera(); + if (camera.is_empty()) { + // No camera, no draw. + return; + } + + qpCamera *camera_node; + DCAST_INTO_V(camera_node, camera.node()); + + if (!camera_node->is_active()) { + // Camera inactive, no draw. + return; + } + + Lens *lens = camera_node->get_lens(); + if (lens == (Lens *)NULL) { + // No lens, no draw. + return; + } + + NodeChain scene = camera_node->get_scene(); + if (scene.is_empty()) { + // 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; + } + + PT(CullResult) cull_result = dr->_cull_result; + if (cull_result == (CullResult *)NULL) { + cull_result = new CullResult(gsg); + } + + BinCullHandler cull_handler(cull_result); + qpCullTraverser trav; + trav.set_cull_handler(&cull_handler); + + // The world transform is computed from the camera's position; we + // then might need to adjust it into the GSG's internal coordinate + // system. + trav.set_camera_transform(scene.get_rel_transform(camera)); + + CPT(TransformState) render_transform = camera.get_rel_transform(scene); + CoordinateSystem external_cs = gsg->get_coordinate_system(); + CoordinateSystem internal_cs = gsg->get_internal_coordinate_system(); + if (internal_cs != CS_default && internal_cs != external_cs) { + CPT(TransformState) cs_transform = + TransformState::make_mat(LMatrix4f::convert_mat(external_cs, internal_cs)); + render_transform = cs_transform->compose(render_transform); + } + trav.set_render_transform(render_transform); + + trav.traverse(scene.node()); + cull_result->finish_cull(); + + // Save the results for next frame. + dr->_cull_result = cull_result->make_next(); + + // Now draw. + DisplayRegionStack old_dr = gsg->push_display_region(dr); + gsg->prepare_display_region(); + cull_result->draw(); + gsg->pop_display_region(old_dr); +} diff --git a/panda/src/display/graphicsEngine.h b/panda/src/display/graphicsEngine.h index 70bd087150..86e4e97617 100644 --- a/panda/src/display/graphicsEngine.h +++ b/panda/src/display/graphicsEngine.h @@ -54,6 +54,9 @@ private: void cull_and_draw_together(); void cull_and_draw_together(GraphicsWindow *win, DisplayRegion *dr); + void cull_bin_draw(); + void cull_bin_draw(GraphicsWindow *win, DisplayRegion *dr); + Pipeline *_pipeline; typedef pset Windows; diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index 83c4266a46..9760e08a07 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -776,6 +776,19 @@ void GraphicsStateGuardian:: release_geom(GeomContext *) { } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::set_state_and_transform +// Access: Public, Virtual +// Description: Simultaneously resets the render state and the +// transform state. +//////////////////////////////////////////////////////////////////// +void GraphicsStateGuardian:: +set_state_and_transform(const RenderState *state, + const TransformState *transform) { + set_state(state); + set_transform(transform); +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::clear_framebuffer // Access: Public, Virtual diff --git a/panda/src/display/graphicsStateGuardian.h b/panda/src/display/graphicsStateGuardian.h index b07b65181e..f9811b5c29 100644 --- a/panda/src/display/graphicsStateGuardian.h +++ b/panda/src/display/graphicsStateGuardian.h @@ -103,6 +103,9 @@ public: virtual GeomContext *prepare_geom(Geom *geom); virtual void release_geom(GeomContext *gc); + virtual void set_state_and_transform(const RenderState *state, + const TransformState *transform); + virtual void clear(const RenderBuffer &buffer)=0; virtual void clear(const RenderBuffer &buffer, const DisplayRegion* region)=0; virtual void clear_framebuffer(); diff --git a/panda/src/gsgbase/graphicsStateGuardianBase.h b/panda/src/gsgbase/graphicsStateGuardianBase.h index 1679b28540..e048758c71 100644 --- a/panda/src/gsgbase/graphicsStateGuardianBase.h +++ b/panda/src/gsgbase/graphicsStateGuardianBase.h @@ -47,6 +47,8 @@ class GeomSphere; class TextureContext; class Texture; class PixelBuffer; +class RenderState; +class TransformState; class Material; class Fog; @@ -129,15 +131,9 @@ public: virtual bool wants_texcoords(void) const=0; virtual bool wants_colors(void) const=0; - - // Defined here are some internal interface functions for the - // GraphicsStateGuardian. These are here to support - // double-dispatching from Geoms and NodeTransitions, and are - // intended to be invoked only directly by the appropriate Geom and - // NodeTransition types. They're public only because it would be too - // inconvenient to declare each of those types to be friends of this - // class. - + // These are some general interface functions; they're defined here + // mainly to make it easy to call these from code in some directory + // that display depends on. virtual TextureContext *prepare_texture(Texture *tex)=0; virtual void apply_texture(TextureContext *tc)=0; virtual void release_texture(TextureContext *tc)=0; @@ -149,6 +145,17 @@ public: virtual GeomContext *prepare_geom(Geom *geom)=0; virtual void release_geom(GeomContext *gc)=0; + virtual void set_state_and_transform(const RenderState *state, + const TransformState *transform)=0; + + // Defined here are some internal interface functions for the + // GraphicsStateGuardian. These are here to support + // double-dispatching from Geoms and NodeTransitions, and are + // intended to be invoked only directly by the appropriate Geom and + // NodeTransition types. They're public only because it would be too + // inconvenient to declare each of those types to be friends of this + // class. + virtual void draw_point(GeomPoint *geom, GeomContext *gc)=0; virtual void draw_line(GeomLine *geom, GeomContext *gc)=0; virtual void draw_linestrip(GeomLinestrip *geom, GeomContext *gc)=0; diff --git a/panda/src/pgraph/Sources.pp b/panda/src/pgraph/Sources.pp index 71096cdcb0..afcd8c631e 100644 --- a/panda/src/pgraph/Sources.pp +++ b/panda/src/pgraph/Sources.pp @@ -7,11 +7,16 @@ #define SOURCES \ billboardAttrib.h billboardAttrib.I \ + binCullHandler.h binCullHandler.I \ qpcamera.h qpcamera.I \ colorAttrib.h colorAttrib.I \ config_pgraph.h \ + cullBin.h cullBin.I \ + cullBinManager.h cullBinManager.I \ + cullBinUnsorted.h cullBinUnsorted.I \ cullFaceAttrib.h cullFaceAttrib.I \ cullHandler.h \ + cullResult.h \ qpcullTraverser.h qpcullTraverser.I \ cycleData.h cycleData.I \ cycleDataReader.h cycleDataReader.I \ @@ -32,11 +37,16 @@ #define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx #define INCLUDED_SOURCES \ billboardAttrib.cxx \ + binCullHandler.cxx \ qpcamera.cxx \ colorAttrib.cxx \ config_pgraph.cxx \ + cullBin.cxx \ + cullBinManager.cxx \ + cullBinUnsorted.cxx \ cullFaceAttrib.cxx \ cullHandler.cxx \ + cullResult.cxx \ qpcullTraverser.cxx \ cycleData.cxx \ cycleDataReader.cxx \ @@ -62,11 +72,16 @@ #define INSTALL_HEADERS \ billboardAttrib.h billboardAttrib.I \ + binCullHandler.h binCullHandler.I \ qpcamera.h qpcamera.I \ colorAttrib.h colorAttrib.I \ config_pgraph.h \ + cullBin.h cullBin.I \ + cullBinManager.h cullBinManager.I \ + cullBinUnsorted.h cullBinUnsorted.I \ cullFaceAttrib.h cullFaceAttrib.I \ cullHandler.h \ + cullResult.h \ qpcullTraverser.h qpcullTraverser.I \ cycleData.h cycleData.I \ cycleDataReader.h cycleDataReader.I \ diff --git a/panda/src/pgraph/binCullHandler.I b/panda/src/pgraph/binCullHandler.I new file mode 100644 index 0000000000..1a3518710b --- /dev/null +++ b/panda/src/pgraph/binCullHandler.I @@ -0,0 +1,29 @@ +// Filename: binCullHandler.I +// Created by: drose (28Feb02) +// +//////////////////////////////////////////////////////////////////// +// +// 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: BinCullHandler::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE BinCullHandler:: +BinCullHandler(CullResult *cull_result) : + _cull_result(cull_result) +{ +} diff --git a/panda/src/pgraph/binCullHandler.cxx b/panda/src/pgraph/binCullHandler.cxx new file mode 100644 index 0000000000..d9d51eb0cf --- /dev/null +++ b/panda/src/pgraph/binCullHandler.cxx @@ -0,0 +1,33 @@ +// Filename: binCullHandler.cxx +// Created by: drose (28Feb02) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "binCullHandler.h" + + +//////////////////////////////////////////////////////////////////// +// Function: BinCullHandler::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 BinCullHandler:: +record_geom(Geom *geom, const TransformState *transform, + const RenderState *state) { + _cull_result->add_geom(geom, transform, state); +} diff --git a/panda/src/pgraph/binCullHandler.h b/panda/src/pgraph/binCullHandler.h new file mode 100644 index 0000000000..f87916deec --- /dev/null +++ b/panda/src/pgraph/binCullHandler.h @@ -0,0 +1,53 @@ +// Filename: binCullHandler.h +// Created by: drose (28Feb02) +// +//////////////////////////////////////////////////////////////////// +// +// 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 BINCULLHANDLER_H +#define BINCULLHANDLER_H + +#include "pandabase.h" +#include "cullHandler.h" +#include "cullResult.h" +#include "pointerTo.h" + +//////////////////////////////////////////////////////////////////// +// Class : BinCullHandler +// Description : This CullHandler sends all of the geoms it receives +// into a CullResult object, for binning (and later +// drawing). This is the kind of CullHandler to use for +// most normal rendering needs. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA BinCullHandler : public CullHandler { +public: + INLINE BinCullHandler(CullResult *cull_result); + + // virtual void begin_decal(); + virtual void record_geom(Geom *geom, const TransformState *transform, + const RenderState *state); + // virtual void push_decal(); + // virtual void pop_decal(); + +private: + PT(CullResult) _cull_result; +}; + +#include "binCullHandler.I" + +#endif + + + diff --git a/panda/src/pgraph/config_pgraph.cxx b/panda/src/pgraph/config_pgraph.cxx index 1a874fbbbc..e252db190a 100644 --- a/panda/src/pgraph/config_pgraph.cxx +++ b/panda/src/pgraph/config_pgraph.cxx @@ -22,6 +22,8 @@ #include "qpcamera.h" #include "colorAttrib.h" #include "cullFaceAttrib.h" +#include "cullBin.h" +#include "cullBinUnsorted.h" #include "qpgeomNode.h" #include "qplensNode.h" #include "nodeChain.h" @@ -35,7 +37,7 @@ #include "dconfig.h" -Configure(config_pgraph); +ConfigureDef(config_pgraph); NotifyCategoryDef(pgraph, ""); ConfigureFn(config_pgraph) { @@ -63,6 +65,8 @@ init_libpgraph() { qpCamera::init_type(); ColorAttrib::init_type(); CullFaceAttrib::init_type(); + CullBin::init_type(); + CullBinUnsorted::init_type(); qpGeomNode::init_type(); qpLensNode::init_type(); NodeChain::init_type(); diff --git a/panda/src/pgraph/config_pgraph.h b/panda/src/pgraph/config_pgraph.h index aa0c551307..4226777c01 100644 --- a/panda/src/pgraph/config_pgraph.h +++ b/panda/src/pgraph/config_pgraph.h @@ -21,7 +21,9 @@ #include "pandabase.h" #include "notifyCategoryProxy.h" +#include "dconfig.h" +ConfigureDecl(config_pgraph, EXPCL_PANDA, EXPTP_PANDA); NotifyCategoryDecl(pgraph, EXPCL_PANDA, EXPTP_PANDA); extern EXPCL_PANDA void init_libpgraph(); diff --git a/panda/src/pgraph/cullBin.I b/panda/src/pgraph/cullBin.I new file mode 100644 index 0000000000..10cf494fd9 --- /dev/null +++ b/panda/src/pgraph/cullBin.I @@ -0,0 +1,29 @@ +// Filename: cullBin.I +// Created by: drose (28Feb02) +// +//////////////////////////////////////////////////////////////////// +// +// 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: CullBin::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE CullBin:: +CullBin(GraphicsStateGuardianBase *gsg) : + _gsg(gsg) +{ +} diff --git a/panda/src/pgraph/cullBin.cxx b/panda/src/pgraph/cullBin.cxx new file mode 100644 index 0000000000..dbe321ea03 --- /dev/null +++ b/panda/src/pgraph/cullBin.cxx @@ -0,0 +1,75 @@ +// Filename: cullBin.cxx +// Created by: drose (28Feb02) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "cullBin.h" + + +TypeHandle CullBin::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: CullBin::make_next +// Access: Public, Virtual +// Description: Returns a newly-allocated CullBin object that +// contains a copy of just the subset of the data from +// this CullBin object that is worth keeping around +// for next frame. +// +// If a particular CullBin object has no data worth +// preserving till next frame, it is acceptable to +// return NULL (which is the default behavior of this +// method). +//////////////////////////////////////////////////////////////////// +PT(CullBin) CullBin:: +make_next() const { + return (CullBin *)NULL; +} + +//////////////////////////////////////////////////////////////////// +// Function: CullBin::add_geom +// Access: Public, Virtual +// Description: Adds the geom, along with its associated state, to +// the bin for rendering. +//////////////////////////////////////////////////////////////////// +void CullBin:: +add_geom(Geom *geom, const TransformState *transform, + const RenderState *state) { +} + +//////////////////////////////////////////////////////////////////// +// Function: CullBin::finish_cull +// Access: Public +// Description: Called after all the geoms have been added, this +// indicates that the cull process is finished for this +// frame and gives the bins a chance to do any +// post-processing (like sorting) before moving on to +// draw. +//////////////////////////////////////////////////////////////////// +void CullBin:: +finish_cull() { +} + +//////////////////////////////////////////////////////////////////// +// Function: CullBin::draw +// Access: Public +// Description: Draws all the geoms in the bin, in the appropriate +// order. +//////////////////////////////////////////////////////////////////// +void CullBin:: +draw() { +} + diff --git a/panda/src/pgraph/cullBin.h b/panda/src/pgraph/cullBin.h new file mode 100644 index 0000000000..d7764b2adc --- /dev/null +++ b/panda/src/pgraph/cullBin.h @@ -0,0 +1,81 @@ +// Filename: cullBin.h +// Created by: drose (27Feb02) +// +//////////////////////////////////////////////////////////////////// +// +// 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 CULLBIN_H +#define CULLBIN_H + +#include "pandabase.h" + +#include "typedReferenceCount.h" +#include "pointerTo.h" + +class Geom; +class TransformState; +class RenderState; +class GraphicsStateGuardianBase; + +//////////////////////////////////////////////////////////////////// +// Class : CullBin +// Description : A collection of Geoms and their associated state, for +// a particular scene. The cull traversal (and the +// BinCullHandler) assigns Geoms to bins as it comes +// across them. +// +// This is an abstract base class; derived classes like +// CullBinStateSorted and CullBinBackToFront provide the +// actual implementation. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA CullBin : public TypedReferenceCount { +public: + INLINE CullBin(GraphicsStateGuardianBase *gsg); + + virtual PT(CullBin) make_next() const; + + virtual void add_geom(Geom *geom, const TransformState *transform, + const RenderState *state)=0; + virtual void finish_cull(); + + virtual void draw()=0; + +protected: + GraphicsStateGuardianBase *_gsg; + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + TypedReferenceCount::init_type(); + register_type(_type_handle, "CullBin", + TypedReferenceCount::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; +}; + +#include "cullBin.I" + +#endif + + + diff --git a/panda/src/pgraph/cullBinManager.I b/panda/src/pgraph/cullBinManager.I new file mode 100644 index 0000000000..cb3894ea33 --- /dev/null +++ b/panda/src/pgraph/cullBinManager.I @@ -0,0 +1,125 @@ +// Filename: cullBinManager.I +// Created by: drose (28Feb02) +// +//////////////////////////////////////////////////////////////////// +// +// 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: CullBinManager::SortBins::Constructor +// Access: Public +// Description: This is a function object whose sole purpose is to +// put the _sorted_bins vector in the proper order for +// rendering the bins. +//////////////////////////////////////////////////////////////////// +INLINE CullBinManager::SortBins:: +SortBins(CullBinManager *manager) : + _manager(manager) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: CullBinManager::SortBins::operator () +// Access: Public +// Description: The function call method of the function object. +// Returns true if the two bin indices are already in +// sorted order with a < b, or false otherwise. +//////////////////////////////////////////////////////////////////// +INLINE bool CullBinManager::SortBins:: +operator () (int a, int b) const { + return _manager->_bin_definitions[a]._sort < _manager->_bin_definitions[b]._sort; +} + + + +//////////////////////////////////////////////////////////////////// +// Function: CullBinManager::get_num_bins +// Access: Published +// Description: Returns the number of bins in the world. +//////////////////////////////////////////////////////////////////// +INLINE int CullBinManager:: +get_num_bins() const { + // We quietly sort the bins in order if they are not already sorted. + // This is a non-const operation, but we pretend it's const because + // it's intended to be a transparent update. + if (!_bins_are_sorted) { + ((CullBinManager *)this)->do_sort_bins(); + } + return _sorted_bins.size(); +} + +//////////////////////////////////////////////////////////////////// +// Function: CullBinManager::get_bin +// Access: Published +// Description: Returns the bin_index of the nth bin in the set, +// where n is a number between 0 and get_num_bins(). +// This returns the list of bin_index numbers, in sorted +// order (that is, in the order in which the bins should +// be rendered). +//////////////////////////////////////////////////////////////////// +INLINE int CullBinManager:: +get_bin(int n) const { + nassertr(n >= 0 && n < (int)_sorted_bins.size(), -1); + return _sorted_bins[n]; +} + +//////////////////////////////////////////////////////////////////// +// Function: CullBinManager::get_bin_name +// Access: Published +// Description: Returns the name of the bin with the indicated +// bin_index (where bin_index was retrieved by get_bin() + +// or find_bin()). The bin's name may not be changed +// during the life of the bin. +//////////////////////////////////////////////////////////////////// +INLINE string CullBinManager:: +get_bin_name(int bin_index) const { + nassertr(bin_index >= 0 && bin_index < (int)_bin_definitions.size(), string()); + nassertr(_bin_definitions[bin_index]._in_use, string()); + return _bin_definitions[bin_index]._name; +} + +//////////////////////////////////////////////////////////////////// +// Function: CullBinManager::get_bin_type +// Access: Published +// Description: Returns the type of the bin with the indicated +// bin_index (where bin_index was retrieved by get_bin() +// or find_bin()). The bin's type may not be changed +// during the life of the bin. +//////////////////////////////////////////////////////////////////// +INLINE CullBinManager::BinType CullBinManager:: +get_bin_type(int bin_index) const { + nassertr(bin_index >= 0 && bin_index < (int)_bin_definitions.size(), BT_invalid); + nassertr(_bin_definitions[bin_index]._in_use, BT_invalid); + return _bin_definitions[bin_index]._type; +} + +//////////////////////////////////////////////////////////////////// +// Function: CullBinManager::get_bin_sort +// Access: Published +// Description: Returns the sort order of the bin with the indicated +// bin_index (where bin_index was retrieved by get_bin() +// or find_bin()). +// +// The bins are rendered in increasing order by their +// sort order; this number may be changed from time to +// time to reorder the bins. +//////////////////////////////////////////////////////////////////// +INLINE int CullBinManager:: +get_bin_sort(int bin_index) const { + nassertr(bin_index >= 0 && bin_index < (int)_bin_definitions.size(), 0); + nassertr(_bin_definitions[bin_index]._in_use, 0); + return _bin_definitions[bin_index]._sort; +} diff --git a/panda/src/pgraph/cullBinManager.cxx b/panda/src/pgraph/cullBinManager.cxx new file mode 100644 index 0000000000..08f78e7017 --- /dev/null +++ b/panda/src/pgraph/cullBinManager.cxx @@ -0,0 +1,309 @@ +// Filename: cullBinManager.cxx +// Created by: drose (28Feb02) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "cullBinManager.h" +#include "cullBinUnsorted.h" +#include "renderState.h" +#include "cullResult.h" +#include "config_pgraph.h" +#include "string_utils.h" + + +CullBinManager *CullBinManager::_global_ptr = (CullBinManager *)NULL; + +//////////////////////////////////////////////////////////////////// +// Function: CullBinManager::Constructor +// Access: Protected +// Description: The constructor is not intended to be called +// directly; there is only one CullBinManager and it +// constructs itself. This could have been a private +// constructor, but gcc issues a spurious warning if the +// constructor is private and the class has no friends. +//////////////////////////////////////////////////////////////////// +CullBinManager:: +CullBinManager() { + _bins_are_sorted = true; + _unused_bin_index = false; + + setup_initial_bins(); +} + +//////////////////////////////////////////////////////////////////// +// Function: CullBinManager::Destructor +// Access: Protected +// Description: Don't call the destructor. +//////////////////////////////////////////////////////////////////// +CullBinManager:: +~CullBinManager() { +} + +//////////////////////////////////////////////////////////////////// +// Function: CullBinManager::add_bin +// Access: Published +// Description: Defines a new bin with the indicated name, and +// returns the new bin_index. If there is already a bin +// with the same name returns its bin_index if it had +// the same properties; otherwise, reports an error and +// returns -1. +//////////////////////////////////////////////////////////////////// +int CullBinManager:: +add_bin(const string &name, BinType type, int sort) { + BinsByName::const_iterator bni = _bins_by_name.find(name); + if (bni != _bins_by_name.end()) { + // We already have such a bin. This is not a problem if the bin + // has the same properties. + int bin_index = (*bni).second; + nassertr(bin_index >= 0 && bin_index < (int)_bin_definitions.size(), -1); + const BinDefinition &def = _bin_definitions[bin_index]; + nassertr(def._in_use, -1); + if (def._type == type && def._sort == sort) { + return bin_index; + } + + // Nope, the old bin had different properties. Too bad. + pgraph_cat.warning() + << "Cannot create a bin named " << name + << "; already have a bin by that name.\n"; + return -1; + } + + // No bin by that name already; choose a bin_index to assign to the + // newly created bin. + int new_bin_index = -1; + if (_unused_bin_index) { + // If there is some bin index that's not being used, we can claim + // it. + int i = 0; + for (i = 0; i < (int)_bin_definitions.size() && new_bin_index == -1; i++) { + if (!_bin_definitions[i]._in_use) { + new_bin_index = i; + } + } + + if (new_bin_index == -1) { + // Oops, maybe we've used up all the unused indices already. + _unused_bin_index = false; + } + } + + if (new_bin_index == -1) { + // Slot a new index on the end of the vector. + new_bin_index = _bin_definitions.size(); + _bin_definitions.push_back(BinDefinition()); + } + + BinDefinition &def = _bin_definitions[new_bin_index]; + def._in_use = true; + def._name = name; + def._type = type; + def._sort = sort; + + _bins_by_name.insert(BinsByName::value_type(name, new_bin_index)); + _sorted_bins.push_back(new_bin_index); + _bins_are_sorted = false; + + return new_bin_index; +} + +//////////////////////////////////////////////////////////////////// +// Function: CullBinManager::remove_bin +// Access: Published +// Description: Permanently removes the indicated bin. This +// operation is not protected from the pipeline and will +// disturb whatever is currently rendering in draw. You +// should not call this during the normal course of +// rendering a frame; it is intended only as an aid to +// development, to allow the developer to interactively +// fiddle with the set of bins. +//////////////////////////////////////////////////////////////////// +void CullBinManager:: +remove_bin(int bin_index) { + nassertv(bin_index >= 0 && bin_index < (int)_bin_definitions.size()); + nassertv(_bin_definitions[bin_index]._in_use); + + _bin_definitions[bin_index]._in_use = false; + SortedBins::iterator si = + find(_sorted_bins.begin(), _sorted_bins.end(), bin_index); + nassertv(si != _sorted_bins.end()); + _sorted_bins.erase(si); + _bins_by_name.erase(_bin_definitions[bin_index]._name); + + // Now we have to make sure all of the data objects in the world + // that had cached this bin index or have a bin object are correctly + // updated. + + // First, tell all the RenderStates in the world to reset their bin + // index cache. + RenderState::bin_removed(bin_index); + + // Now tell all the CullResults to clear themselves up too. + CullResult::bin_removed(bin_index); +} + +//////////////////////////////////////////////////////////////////// +// Function: CullBinManager::find_bin +// Access: Published +// Description: Returns the bin_index associated with the bin of the +// given name, or -1 if no bin has that name. +//////////////////////////////////////////////////////////////////// +int CullBinManager:: +find_bin(const string &name) const { + BinsByName::const_iterator bni; + bni = _bins_by_name.find(name); + if (bni != _bins_by_name.end()) { + return (*bni).second; + } + return -1; +} + +//////////////////////////////////////////////////////////////////// +// Function: CullBinManager::get_global_ptr +// Access: Published, Static +// Description: Returns the pointer to the global CullBinManager +// object. +//////////////////////////////////////////////////////////////////// +CullBinManager *CullBinManager:: +get_global_ptr() { + if (_global_ptr == (CullBinManager *)NULL) { + _global_ptr = new CullBinManager; + } + return _global_ptr; +} + +//////////////////////////////////////////////////////////////////// +// Function: CullBinManager::make_new_bin +// Access: Public +// Description: Intended to be called by CullResult when a new +// CullBin pointer corresponding to the indicated +// bin_index is required. It allocates and returns a +// brand new CullBin object of the appropriate type. +//////////////////////////////////////////////////////////////////// +PT(CullBin) CullBinManager:: +make_new_bin(int bin_index, GraphicsStateGuardianBase *gsg) { + nassertr(bin_index >= 0 && bin_index < (int)_bin_definitions.size(), NULL); + nassertr(_bin_definitions[bin_index]._in_use, NULL); + + return new CullBinUnsorted(gsg); +} + +//////////////////////////////////////////////////////////////////// +// Function: CullBinManager::do_sort_bins +// Access: Private +// Description: Puts the _sorted_bins vector in proper rendering +// order. +//////////////////////////////////////////////////////////////////// +void CullBinManager:: +do_sort_bins() { + sort(_sorted_bins.begin(), _sorted_bins.end(), SortBins(this)); + _bins_are_sorted = true; +} + +//////////////////////////////////////////////////////////////////// +// Function: CullBinManager::setup_initial_bins +// Access: Private +// Description: Called only at construction time to create the +// default bins and the bins specified in the Configrc +// file. +//////////////////////////////////////////////////////////////////// +void CullBinManager:: +setup_initial_bins() { + // First, add all of the bins specified in the Configrc file. + Config::ConfigTable::Symbol cull_bins; + config_pgraph.GetAll("cull-bin", cull_bins); + + Config::ConfigTable::Symbol::iterator bi; + for (bi = cull_bins.begin(); bi != cull_bins.end(); ++bi) { + ConfigString def = (*bi).Val(); + + // This is a string in three tokens, separated by whitespace: + // bin_name sort type + + vector_string words; + extract_words(def, words); + + if (words.size() != 3) { + pgraph_cat.error() + << "Invalid cull-bin definition: " << def << "\n" + << "Definition should be three words: bin_name sort type\n"; + } else { + int sort; + if (!string_to_int(words[1], sort)) { + pgraph_cat.error() + << "Invalid cull-bin definition: " << def << "\n" + << "Sort token " << words[1] << " is not an integer.\n"; + + } else { + BinType type = parse_bin_type(words[2]); + if (type == BT_invalid) { + pgraph_cat.error() + << "Invalid cull-bin definition: " << def << "\n" + << "Bin type " << words[2] << " is not known.\n"; + } else { + add_bin(words[0], type, sort); + } + } + } + } + + // Now add the default bins, unless the names have already been + // specified explicitly in the Config file, above. + if (find_bin("background") == -1) { + add_bin("background", BT_fixed, 10); + } + if (find_bin("opaque") == -1) { + add_bin("opaque", BT_state_sorted, 20); + } + if (find_bin("transparent") == -1) { + add_bin("transparent", BT_back_to_front, 30); + } + if (find_bin("fixed") == -1) { + add_bin("fixed", BT_fixed, 40); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: CullBinManager::parse_bin_type +// Access: Private, Static +// Description: Given the name of a bin type, returns the +// corresponding BinType value, or BT_invalid if it is +// an unknown type. +//////////////////////////////////////////////////////////////////// +CullBinManager::BinType CullBinManager:: +parse_bin_type(const string &bin_type) { + if (cmp_nocase_uh(bin_type, "unsorted") == 0) { + return BT_unsorted; + + } else if (cmp_nocase_uh(bin_type, "state_sorted") == 0) { + return BT_state_sorted; + + } else if (cmp_nocase_uh(bin_type, "statesorted") == 0) { + return BT_state_sorted; + + } else if (cmp_nocase_uh(bin_type, "fixed") == 0) { + return BT_fixed; + + } else if (cmp_nocase_uh(bin_type, "back_to_front") == 0) { + return BT_back_to_front; + + } else if (cmp_nocase_uh(bin_type, "backtofront") == 0) { + return BT_back_to_front; + + } else { + return BT_invalid; + } +} diff --git a/panda/src/pgraph/cullBinManager.h b/panda/src/pgraph/cullBinManager.h new file mode 100644 index 0000000000..29554a7c25 --- /dev/null +++ b/panda/src/pgraph/cullBinManager.h @@ -0,0 +1,105 @@ +// Filename: cullBinManager.h +// Created by: drose (27Feb02) +// +//////////////////////////////////////////////////////////////////// +// +// 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 CULLBINMANAGER_H +#define CULLBINMANAGER_H + +#include "pandabase.h" +#include "cullBin.h" +#include "pointerTo.h" +#include "pvector.h" +#include "pmap.h" + +class CullResult; +class GraphicsStateGuardianBase; + +//////////////////////////////////////////////////////////////////// +// Class : CullBinManager +// Description : This is a global object that maintains the collection +// of named CullBins in the world. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA CullBinManager { +protected: + CullBinManager(); + ~CullBinManager(); + +PUBLISHED: + enum BinType { + BT_invalid, + BT_unsorted, + BT_state_sorted, + BT_back_to_front, + BT_fixed, + }; + + int add_bin(const string &name, BinType type, int sort); + void remove_bin(int bin_index); + + INLINE int get_num_bins() const; + INLINE int get_bin(int n) const; + int find_bin(const string &name) const; + + INLINE string get_bin_name(int bin_index) const; + INLINE BinType get_bin_type(int bin_index) const; + + INLINE int get_bin_sort(int bin_index) const; + INLINE void set_bin_sort(int bin_index, int sort); + + static CullBinManager *get_global_ptr(); + +public: + // This interface is only intended to be used by CullResult. + PT(CullBin) make_new_bin(int bin_index, GraphicsStateGuardianBase *gsg); + +private: + void do_sort_bins(); + void setup_initial_bins(); + static BinType parse_bin_type(const string &bin_type); + + class EXPCL_PANDA BinDefinition { + public: + bool _in_use; + string _name; + BinType _type; + int _sort; + }; + typedef pvector BinDefinitions; + BinDefinitions _bin_definitions; + + class SortBins { + public: + INLINE SortBins(CullBinManager *manager); + INLINE bool operator () (int a, int b) const; + CullBinManager *_manager; + }; + + typedef pmap BinsByName; + BinsByName _bins_by_name; + + typedef pvector SortedBins; + SortedBins _sorted_bins; + bool _bins_are_sorted; + bool _unused_bin_index; + + static CullBinManager *_global_ptr; + friend class SortBins; +}; + +#include "cullBinManager.I" + +#endif diff --git a/panda/src/pgraph/cullBinUnsorted.I b/panda/src/pgraph/cullBinUnsorted.I new file mode 100644 index 0000000000..6f4f4c343c --- /dev/null +++ b/panda/src/pgraph/cullBinUnsorted.I @@ -0,0 +1,44 @@ +// Filename: cullBinUnsorted.I +// Created by: drose (28Feb02) +// +//////////////////////////////////////////////////////////////////// +// +// 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: CullBinUnsorted::GeomData::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE CullBinUnsorted::GeomData:: +GeomData(Geom *geom, const TransformState *transform, + const RenderState *state) : + _geom(geom), + _transform(transform), + _state(state) +{ +} + + +//////////////////////////////////////////////////////////////////// +// Function: CullBinUnsorted::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE CullBinUnsorted:: +CullBinUnsorted(GraphicsStateGuardianBase *gsg) : + CullBin(gsg) +{ +} diff --git a/panda/src/pgraph/cullBinUnsorted.cxx b/panda/src/pgraph/cullBinUnsorted.cxx new file mode 100644 index 0000000000..19a721a162 --- /dev/null +++ b/panda/src/pgraph/cullBinUnsorted.cxx @@ -0,0 +1,52 @@ +// Filename: cullBinUnsorted.cxx +// Created by: drose (28Feb02) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "cullBinUnsorted.h" +#include "graphicsStateGuardianBase.h" + + +TypeHandle CullBinUnsorted::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: CullBinUnsorted::add_geom +// Access: Public, Virtual +// Description: Adds the geom, along with its associated state, to +// the bin for rendering. +//////////////////////////////////////////////////////////////////// +void CullBinUnsorted:: +add_geom(Geom *geom, const TransformState *transform, + const RenderState *state) { + _geoms.push_back(GeomData(geom, transform, state)); +} + +//////////////////////////////////////////////////////////////////// +// Function: CullBinUnsorted::draw +// Access: Public +// Description: Draws all the geoms in the bin, in the appropriate +// order. +//////////////////////////////////////////////////////////////////// +void CullBinUnsorted:: +draw() { + Geoms::iterator gi; + for (gi = _geoms.begin(); gi != _geoms.end(); ++gi) { + GeomData &geom_data = (*gi); + _gsg->set_state_and_transform(geom_data._state, geom_data._transform); + geom_data._geom->draw(_gsg); + } +} + diff --git a/panda/src/pgraph/cullBinUnsorted.h b/panda/src/pgraph/cullBinUnsorted.h new file mode 100644 index 0000000000..eacaf0336e --- /dev/null +++ b/panda/src/pgraph/cullBinUnsorted.h @@ -0,0 +1,81 @@ +// Filename: cullBinUnsorted.h +// Created by: drose (28Feb02) +// +//////////////////////////////////////////////////////////////////// +// +// 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 CULLBINUNSORTED_H +#define CULLBINUNSORTED_H + +#include "pandabase.h" + +#include "cullBin.h" +#include "geom.h" +#include "transformState.h" +#include "renderState.h" +#include "pointerTo.h" + +//////////////////////////////////////////////////////////////////// +// Class : CullBinUnsorted +// Description : A specific kind of CullBin that does not reorder the +// geometry; it simply passes it through to the GSG in +// the same order it was encountered, which will be in +// scene-graph order. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA CullBinUnsorted : public CullBin { +public: + INLINE CullBinUnsorted(GraphicsStateGuardianBase *gsg); + + virtual void add_geom(Geom *geom, const TransformState *transform, + const RenderState *state); + virtual void draw(); + +private: + class GeomData { + public: + INLINE GeomData(Geom *geom, const TransformState *transform, + const RenderState *state); + PT(Geom) _geom; + CPT(TransformState) _transform; + CPT(RenderState) _state; + }; + + typedef pvector Geoms; + Geoms _geoms; + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + CullBin::init_type(); + register_type(_type_handle, "CullBinUnsorted", + CullBin::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; +}; + +#include "cullBinUnsorted.I" + +#endif + + + diff --git a/panda/src/pgraph/cullHandler.cxx b/panda/src/pgraph/cullHandler.cxx index d6b1b05c65..103ef7d0f8 100644 --- a/panda/src/pgraph/cullHandler.cxx +++ b/panda/src/pgraph/cullHandler.cxx @@ -21,6 +21,17 @@ #include "transformState.h" #include "renderState.h" +//////////////////////////////////////////////////////////////////// +// Function: CullHandler::Destructor +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +CullHandler:: +~CullHandler() +{ +} + + //////////////////////////////////////////////////////////////////// // Function: CullHandler::record_geom // Access: Public, Virtual diff --git a/panda/src/pgraph/cullHandler.h b/panda/src/pgraph/cullHandler.h index f4c62f9c7b..4f122647f6 100644 --- a/panda/src/pgraph/cullHandler.h +++ b/panda/src/pgraph/cullHandler.h @@ -34,6 +34,8 @@ class RenderState; //////////////////////////////////////////////////////////////////// class EXPCL_PANDA CullHandler { public: + virtual ~CullHandler(); + // virtual void begin_decal(); virtual void record_geom(Geom *geom, const TransformState *transform, const RenderState *state); diff --git a/panda/src/pgraph/cullResult.I b/panda/src/pgraph/cullResult.I new file mode 100644 index 0000000000..4d8692bea1 --- /dev/null +++ b/panda/src/pgraph/cullResult.I @@ -0,0 +1,69 @@ +// Filename: cullResult.I +// Created by: drose (28Feb02) +// +//////////////////////////////////////////////////////////////////// +// +// 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: CullResult::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE CullResult:: +CullResult(GraphicsStateGuardianBase *gsg) : + _gsg(gsg) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: CullResult::Destructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE CullResult:: +~CullResult() { +} + +//////////////////////////////////////////////////////////////////// +// Function: CullResult::get_bin +// Access: Public +// Description: Returns the CullBin associated with the indicated +// bin_index, or NULL if the bin_index is invalid. If +// there is the first time this bin_index has been +// requested for this CullResult, creates a new CullBin +// object on the fly. +//////////////////////////////////////////////////////////////////// +INLINE CullBin *CullResult:: +get_bin(int bin_index) { + if (bin_index >= 0 && bin_index < (int)_bins.size() && + _bins[bin_index] != (CullBin *)NULL) { + return _bins[bin_index]; + } + return make_new_bin(bin_index); +} + +//////////////////////////////////////////////////////////////////// +// Function: CullResult::add_geom +// Access: Public +// Description: Adds the indicated Geom to the appropriate bin. +//////////////////////////////////////////////////////////////////// +INLINE void CullResult:: +add_geom(Geom *geom, const TransformState *transform, + const RenderState *state) { + CullBin *bin = get_bin(state->get_bin_index()); + nassertv(bin != (CullBin *)NULL); + bin->add_geom(geom, transform, state); +} diff --git a/panda/src/pgraph/cullResult.cxx b/panda/src/pgraph/cullResult.cxx new file mode 100644 index 0000000000..1804f54333 --- /dev/null +++ b/panda/src/pgraph/cullResult.cxx @@ -0,0 +1,121 @@ +// Filename: cullResult.cxx +// Created by: drose (28Feb02) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "cullResult.h" +#include "cullBinManager.h" + +//////////////////////////////////////////////////////////////////// +// Function: CullResult::make_next +// Access: Public +// Description: Returns a newly-allocated CullResult object that +// contains a copy of just the subset of the data from +// this CullResult object that is worth keeping around +// for next frame. +//////////////////////////////////////////////////////////////////// +PT(CullResult) CullResult:: +make_next() const { + PT(CullResult) new_result = new CullResult(_gsg); + new_result->_bins.reserve(_bins.size()); + + for (Bins::const_iterator bi = _bins.begin(); bi != _bins.end(); ++bi) { + CullBin *old_bin = (*bi); + if (old_bin == (CullBin *)NULL) { + new_result->_bins.push_back((CullBin *)NULL); + } else { + new_result->_bins.push_back(old_bin->make_next()); + } + } + + return new_result; +} + +//////////////////////////////////////////////////////////////////// +// Function: CullResult::finish_cull +// Access: Public +// Description: Called after all the geoms have been added, this +// indicates that the cull process is finished for this +// frame and gives the bins a chance to do any +// post-processing (like sorting) before moving on to +// draw. +//////////////////////////////////////////////////////////////////// +void CullResult:: +finish_cull() { + for (Bins::iterator bi = _bins.begin(); bi != _bins.end(); ++bi) { + CullBin *bin = (*bi); + if (bin != (CullBin *)NULL) { + bin->finish_cull(); + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: CullResult::draw +// Access: Public +// Description: Asks all the bins to draw themselves in the correct +// order. +//////////////////////////////////////////////////////////////////// +void CullResult:: +draw() { + // Ask the bin manager for the correct order to draw all the bins. + CullBinManager *bin_manager = CullBinManager::get_global_ptr(); + int num_bins = bin_manager->get_num_bins(); + for (int i = 0; i < num_bins; i++) { + int bin_index = bin_manager->get_bin(i); + nassertv(bin_index >= 0); + + if (bin_index < (int)_bins.size() && _bins[bin_index] != (CullBin *)NULL) { + _bins[bin_index]->draw(); + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: CullResult::bin_removed +// Access: Public, Static +// Description: Intended to be called by +// CullBinManager::remove_bin(), this informs all the +// CullResults in the world to remove the indicated +// bin_index from their cache if it has been cached. +//////////////////////////////////////////////////////////////////// +void CullResult:: +bin_removed(int bin_index) { + // Do something here. + nassertv(false); +} + +//////////////////////////////////////////////////////////////////// +// Function: CullResult::make_new_bin +// Access: Private +// Description: Allocates a new CullBin for the given bin_index and +// stores it for next time. +//////////////////////////////////////////////////////////////////// +CullBin *CullResult:: +make_new_bin(int bin_index) { + CullBinManager *bin_manager = CullBinManager::get_global_ptr(); + PT(CullBin) bin = bin_manager->make_new_bin(bin_index, _gsg); + if (bin != (CullBin *)NULL) { + // Now store it in the vector. + while (bin_index >= (int)_bins.size()) { + _bins.push_back((CullBin *)NULL); + } + nassertr(bin_index >= 0 && bin_index < (int)_bins.size(), NULL); + _bins[bin_index] = bin; + } + + return bin; +} diff --git a/panda/src/pgraph/cullResult.h b/panda/src/pgraph/cullResult.h new file mode 100644 index 0000000000..3eddebb1b6 --- /dev/null +++ b/panda/src/pgraph/cullResult.h @@ -0,0 +1,80 @@ +// Filename: cullResult.h +// Created by: drose (27Feb02) +// +//////////////////////////////////////////////////////////////////// +// +// 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 CULLRESULT_H +#define CULLRESULT_H + +#include "pandabase.h" +#include "cullBin.h" +#include "renderState.h" + +#include "referenceCount.h" +#include "pointerTo.h" +#include "pvector.h" +#include "pset.h" + +class GraphicsStateGuardianBase; +class TransformState; +class RenderState; + +//////////////////////////////////////////////////////////////////// +// Class : CullResult +// Description : This stores the result of a BinCullHandler traversal: +// an ordered collection of CullBins, each of which +// holds a number of Geoms and RenderStates to be +// rendered in some defined order. +// +// This is also used to keep the results of last frame's +// cull traversal around to make next frame's traversal +// of the same scene a little easier. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA CullResult : public ReferenceCount { +public: + INLINE CullResult(GraphicsStateGuardianBase *gsg); + INLINE ~CullResult(); + + PT(CullResult) make_next() const; + + INLINE CullBin *get_bin(int bin_index); + + INLINE void add_geom(Geom *geom, const TransformState *transform, + const RenderState *state); + void finish_cull(); + void draw(); + +public: + static void bin_removed(int bin_index); + +private: + CullBin *make_new_bin(int bin_index); + + GraphicsStateGuardianBase *_gsg; + + typedef pvector< PT(CullBin) > Bins; + Bins _bins; + + typedef pset CullResults; + static CullResults _cull_results; +}; + +#include "cullResult.I" + +#endif + + + diff --git a/panda/src/pgraph/pgraph_composite1.cxx b/panda/src/pgraph/pgraph_composite1.cxx index d3dc08d6dd..3607e10def 100644 --- a/panda/src/pgraph/pgraph_composite1.cxx +++ b/panda/src/pgraph/pgraph_composite1.cxx @@ -1,12 +1,12 @@ #include "billboardAttrib.cxx" +#include "binCullHandler.cxx" #include "qpcamera.cxx" #include "colorAttrib.cxx" #include "config_pgraph.cxx" +#include "cullBin.cxx" +#include "cullBinManager.cxx" +#include "cullBinUnsorted.cxx" #include "cullFaceAttrib.cxx" #include "cullHandler.cxx" +#include "cullResult.cxx" #include "qpcullTraverser.cxx" -#include "cycleData.cxx" -#include "cycleDataReader.cxx" -#include "cycleDataWriter.cxx" -#include "qpgeomNode.cxx" -#include "qplensNode.cxx" diff --git a/panda/src/pgraph/pgraph_composite2.cxx b/panda/src/pgraph/pgraph_composite2.cxx index bffae7a01f..2b9d110bbe 100644 --- a/panda/src/pgraph/pgraph_composite2.cxx +++ b/panda/src/pgraph/pgraph_composite2.cxx @@ -1,3 +1,8 @@ +#include "cycleData.cxx" +#include "cycleDataReader.cxx" +#include "cycleDataWriter.cxx" +#include "qpgeomNode.cxx" +#include "qplensNode.cxx" #include "nodeChain.cxx" #include "nodeChainComponent.cxx" #include "pandaNode.cxx" diff --git a/panda/src/pgraph/renderState.I b/panda/src/pgraph/renderState.I index fd0fe2bbb3..d02edfee10 100644 --- a/panda/src/pgraph/renderState.I +++ b/panda/src/pgraph/renderState.I @@ -167,3 +167,22 @@ get_billboard() const { } return _billboard; } + +//////////////////////////////////////////////////////////////////// +// Function: RenderState::get_bin_index +// Access: Public +// Description: Returns the bin index indicated by the CullBinAttrib +// transition, if any, associated by this state (or the +// default bin index if there is no CullBinAttrib). As +// in get_billboard(), above, this function is provided +// as an optimization. +//////////////////////////////////////////////////////////////////// +INLINE int RenderState:: +get_bin_index() const { + if ((_flags & F_checked_bin_index) == 0) { + // We pretend this function is const, even though it transparently + // modifies the internal bin_index cache. + ((RenderState *)this)->determine_bin_index(); + } + return _bin_index; +} diff --git a/panda/src/pgraph/renderState.cxx b/panda/src/pgraph/renderState.cxx index 24bc305f06..d01c23667d 100644 --- a/panda/src/pgraph/renderState.cxx +++ b/panda/src/pgraph/renderState.cxx @@ -18,6 +18,8 @@ #include "renderState.h" #include "billboardAttrib.h" +#include "cullBinManager.h" +#include "config_pgraph.h" #include "bamReader.h" #include "bamWriter.h" #include "datagramIterator.h" @@ -666,6 +668,20 @@ issue_delta_set(const RenderState *other, return other; } +//////////////////////////////////////////////////////////////////// +// Function: RenderState::bin_removed +// Access: Public, Static +// Description: Intended to be called by +// CullBinManager::remove_bin(), this informs all the +// RenderStates in the world to remove the indicated +// bin_index from their cache if it has been cached. +//////////////////////////////////////////////////////////////////// +void RenderState:: +bin_removed(int bin_index) { + // Do something here. + nassertv(false); +} + //////////////////////////////////////////////////////////////////// // Function: RenderState::return_new // Access: Private, Static @@ -841,6 +857,33 @@ determine_billboard() { _flags |= F_checked_billboard; } +//////////////////////////////////////////////////////////////////// +// Function: RenderState::determine_bin_index +// Access: Private +// Description: This is the private implementation of +// get_bin_index(). +//////////////////////////////////////////////////////////////////// +void RenderState:: +determine_bin_index() { + string bin_name = "opaque"; + + /* + const RenderAttrib *attrib = get_attrib(CullBinAttrib::get_class_type()); + if (attrib != (const RenderAttrib *)NULL) { + const CullBinAttrib *bin_attrib = DCAST(CullBinAttrib, attrib); + } + */ + + CullBinManager *bin_manager = CullBinManager::get_global_ptr(); + _bin_index = bin_manager->find_bin(bin_name); + if (_bin_index == -1) { + pgraph_cat.warning() + << "No bin named " << bin_name << "; creating default bin.\n"; + _bin_index = bin_manager->add_bin(bin_name, CullBinManager::BT_unsorted, 0); + } + _flags |= F_checked_bin_index; +} + //////////////////////////////////////////////////////////////////// // Function: RenderState::register_with_read_factory // Access: Public, Static diff --git a/panda/src/pgraph/renderState.h b/panda/src/pgraph/renderState.h index 5ea7200362..8d3ec29f84 100644 --- a/panda/src/pgraph/renderState.h +++ b/panda/src/pgraph/renderState.h @@ -88,17 +88,21 @@ PUBLISHED: public: INLINE const BillboardAttrib *get_billboard() const; + INLINE int get_bin_index() const; CPT(RenderState) issue_delta_modify(const RenderState *other, GraphicsStateGuardianBase *gsg) const; CPT(RenderState) issue_delta_set(const RenderState *other, GraphicsStateGuardianBase *gsg) const; + static void bin_removed(int bin_index); + 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; void determine_billboard(); + void determine_bin_index(); private: typedef pset > States; @@ -154,8 +158,13 @@ private: // We cache the pointer to the BillboardAttrib stored in the state, // if there is one. const BillboardAttrib *_billboard; + + // We also cache the index to the associated GeomBin. + int _bin_index; + enum Flags { F_checked_billboard = 0x0001, + F_checked_bin_index = 0x0002, }; short _flags; diff --git a/panda/src/testbed/pview.cxx b/panda/src/testbed/pview.cxx index 358207d6cb..59192e54c3 100644 --- a/panda/src/testbed/pview.cxx +++ b/panda/src/testbed/pview.cxx @@ -183,7 +183,7 @@ make_default_geometry(PandaNode *parent) { if (tex != (Texture *)NULL) { tex->set_minfilter(Texture::FT_linear); tex->set_magfilter(Texture::FT_linear); - state->add_attrib(TextureAttrib::make(tex)); + state = state->add_attrib(TextureAttrib::make(tex)); } qpGeomNode *geomnode = new qpGeomNode("tri");