diff --git a/panda/src/glgsg/Sources.pp b/panda/src/glgsg/Sources.pp index 70221d32fc..41ab6ad706 100644 --- a/panda/src/glgsg/Sources.pp +++ b/panda/src/glgsg/Sources.pp @@ -14,7 +14,8 @@ config_glgsg.cxx config_glgsg.h glGraphicsStateGuardian.I \ glGraphicsStateGuardian.cxx glGraphicsStateGuardian.h \ glSavedFrameBuffer.I glSavedFrameBuffer.cxx glSavedFrameBuffer.h \ - glTextureContext.I glTextureContext.cxx glTextureContext.h + glTextureContext.I glGeomNodeContext.I glGeomNodeContext.cxx \ + glGeomNodeContext.h glTextureContext.cxx glTextureContext.h #define INSTALL_HEADERS \ config_glgsg.h glGraphicsStateGuardian.I glGraphicsStateGuardian.h diff --git a/panda/src/glgsg/config_glgsg.cxx b/panda/src/glgsg/config_glgsg.cxx index db73164d5f..039063c14b 100644 --- a/panda/src/glgsg/config_glgsg.cxx +++ b/panda/src/glgsg/config_glgsg.cxx @@ -20,6 +20,7 @@ #include "glGraphicsStateGuardian.h" #include "glSavedFrameBuffer.h" #include "glTextureContext.h" +#include "glGeomNodeContext.h" #include @@ -103,6 +104,7 @@ init_libglgsg() { GLGraphicsStateGuardian::init_type(); GLSavedFrameBuffer::init_type(); GLTextureContext::init_type(); + GLGeomNodeContext::init_type(); GraphicsStateGuardian::get_factory().register_factory (GLGraphicsStateGuardian::get_class_type(), diff --git a/panda/src/glgsg/glGeomNodeContext.I b/panda/src/glgsg/glGeomNodeContext.I new file mode 100644 index 0000000000..1390a99cac --- /dev/null +++ b/panda/src/glgsg/glGeomNodeContext.I @@ -0,0 +1,30 @@ +// Filename: glGeomNodeContext.I +// Created by: drose (12Jun01) +// +//////////////////////////////////////////////////////////////////// +// +// 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: GLGeomNodeContext::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE GLGeomNodeContext:: +GLGeomNodeContext(GeomNode *node) : + GeomNodeContext(node) +{ + _index = 0; +} diff --git a/panda/src/glgsg/glGeomNodeContext.cxx b/panda/src/glgsg/glGeomNodeContext.cxx new file mode 100644 index 0000000000..9f1dfc189a --- /dev/null +++ b/panda/src/glgsg/glGeomNodeContext.cxx @@ -0,0 +1,21 @@ +// Filename: glGeomNodeContext.cxx +// Created by: drose (12Jun01) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "glGeomNodeContext.h" + +TypeHandle GLGeomNodeContext::_type_handle; diff --git a/panda/src/glgsg/glGeomNodeContext.h b/panda/src/glgsg/glGeomNodeContext.h new file mode 100644 index 0000000000..fcbf2a6e38 --- /dev/null +++ b/panda/src/glgsg/glGeomNodeContext.h @@ -0,0 +1,74 @@ +// Filename: glGeomNodeContext.h +// Created by: drose (12Jun01) +// +//////////////////////////////////////////////////////////////////// +// +// 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 GLGEOMNODECONTEXT_H +#define GLGEOMNODECONTEXT_H + +#include + +#ifdef WIN32_VC +// Must include windows.h before gl.h on NT +#define WIN32_LEAN_AND_MEAN +#include +#undef WIN32_LEAN_AND_MEAN +#endif + +#include +#include +#include +#include "pvector.h" + +//////////////////////////////////////////////////////////////////// +// Class : GLGeomNodeContext +// Description : +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDAGL GLGeomNodeContext : public GeomNodeContext { +public: + INLINE GLGeomNodeContext(GeomNode *node); + + // The GL display list index that draws the contents of this + // GeomNode. + GLuint _index; + + // A list of the dynamic Geoms within the GeomNode; these aren't + // part of the above display list. + typedef pvector Geoms; + Geoms _dynamic_geoms; + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + GeomNodeContext::init_type(); + register_type(_type_handle, "GLGeomNodeContext", + GeomNodeContext::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 "glGeomNodeContext.I" + +#endif + diff --git a/panda/src/glgsg/glGraphicsStateGuardian.cxx b/panda/src/glgsg/glGraphicsStateGuardian.cxx index dae913fa57..64dfcd2925 100644 --- a/panda/src/glgsg/glGraphicsStateGuardian.cxx +++ b/panda/src/glgsg/glGraphicsStateGuardian.cxx @@ -19,6 +19,7 @@ #include "glGraphicsStateGuardian.h" #include "glSavedFrameBuffer.h" #include "glTextureContext.h" +#include "glGeomNodeContext.h" #include "config_glgsg.h" #include @@ -1771,6 +1772,130 @@ release_texture(TextureContext *tc) { report_errors(); } +//////////////////////////////////////////////////////////////////// +// Function: GLGraphicsStateGuardian::prepare_geom_node +// Access: Public, Virtual +// Description: Prepares the indicated GeomNode for retained-mode +// rendering. If this function returns non-NULL, the +// value returned will be passed back to a future call +// to draw_geom_node(), which is expected to draw the +// contents of the node. +//////////////////////////////////////////////////////////////////// +GeomNodeContext *GLGraphicsStateGuardian:: +prepare_geom_node(GeomNode *node) { + // Make sure we have at least some static Geoms in the GeomNode; + // otherwise there's no point in building a display list. + int num_geoms = node->get_num_geoms(); + bool all_dynamic = true; + for (int i = 0; i < num_geoms && all_dynamic; i++) { + dDrawable *geom = node->get_geom(i); + all_dynamic = geom->is_dynamic(); + } + if (all_dynamic) { + // Never mind. + return (GeomNodeContext *)NULL; + } + + // Ok, we've got something; use it. + GLGeomNodeContext *ggnc = new GLGeomNodeContext(node); + ggnc->_index = glGenLists(1); + if (ggnc->_index == 0) { + glgsg_cat.error() + << "Ran out of display list indices.\n"; + delete ggnc; + return (GeomNodeContext *)NULL; + } + + // We need to temporarily force normals and UV's on, so the display + // list will have them built in. + bool old_normals_enabled = _normals_enabled; + bool old_texturing_enabled = _texturing_enabled; + _normals_enabled = true; + _texturing_enabled = true; + + // Now define the display list. + glNewList(ggnc->_index, GL_COMPILE); + for (int i = 0; i < num_geoms; i++) { + dDrawable *geom = node->get_geom(i); + if (geom->is_dynamic()) { + // Wait, this is a dynamic Geom. We can't safely put it in the + // display list, because it may change from one frame to the + // next; instead, we'll keep it out. + ggnc->_dynamic_geoms.push_back(geom); + } else { + // A static Geom becomes part of the display list. + geom->draw(this); + } + } + glEndList(); + + _normals_enabled = old_normals_enabled; + _texturing_enabled = old_texturing_enabled; + + bool inserted = mark_prepared_geom_node(ggnc); + + // If this assertion fails, the same GeomNode was prepared twice, + // which shouldn't be possible, since the GeomNode itself should + // detect this. + nassertr(inserted, NULL); + + return ggnc; +} + +//////////////////////////////////////////////////////////////////// +// Function: GLGraphicsStateGuardian::draw_geom_node +// Access: Public, Virtual +// Description: Draws a GeomNode previously indicated by a call to +// prepare_geom_node(). +//////////////////////////////////////////////////////////////////// +void GLGraphicsStateGuardian:: +draw_geom_node(GeomNode *node, GeomNodeContext *gnc) { + if (gnc == (GeomNodeContext *)NULL) { + // We don't have a saved context; just draw the GeomNode in + // immediate mode. + int num_geoms = node->get_num_geoms(); + for (int i = 0; i < num_geoms; i++) { + node->get_geom(i)->draw(this); + } + + } else { + // We do have a saved context; use it. + add_to_geom_node_record(gnc); + GLGeomNodeContext *ggnc = DCAST(GLGeomNodeContext, gnc); + glCallList(ggnc->_index); + + // Also draw all the dynamic Geoms. + int num_geoms = ggnc->_dynamic_geoms.size(); + for (int i = 0; i < num_geoms; i++) { + ggnc->_dynamic_geoms[i]->draw(this); + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: GLGraphicsStateGuardian::release_geom_node +// Access: Public, Virtual +// Description: Frees the resources previously allocated via a call +// to prepare_geom_node(), including deleting the +// GeomNodeContext itself, if necessary. +//////////////////////////////////////////////////////////////////// +void GLGraphicsStateGuardian:: +release_geom_node(GeomNodeContext *gnc) { + if (gnc != (GeomNodeContext *)NULL) { + GLGeomNodeContext *ggnc = DCAST(GLGeomNodeContext, gnc); + glDeleteLists(ggnc->_index, 1); + + bool erased = unmark_prepared_geom_node(ggnc); + + // If this assertion fails, a GeomNode was released that hadn't + // been prepared (or a GeomNode was released twice). + nassertv(erased); + + ggnc->_node->clear_gsg(this); + delete ggnc; + } +} + static int logs[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 0 }; diff --git a/panda/src/glgsg/glGraphicsStateGuardian.h b/panda/src/glgsg/glGraphicsStateGuardian.h index fa48b0e398..e39e23f0f2 100644 --- a/panda/src/glgsg/glGraphicsStateGuardian.h +++ b/panda/src/glgsg/glGraphicsStateGuardian.h @@ -102,6 +102,10 @@ public: virtual void apply_texture(TextureContext *tc); virtual void release_texture(TextureContext *tc); + virtual GeomNodeContext *prepare_geom_node(GeomNode *node); + virtual void draw_geom_node(GeomNode *node, GeomNodeContext *gnc); + virtual void release_geom_node(GeomNodeContext *gnc); + virtual void copy_texture(TextureContext *tc, const DisplayRegion *dr); virtual void copy_texture(TextureContext *tc, const DisplayRegion *dr, const RenderBuffer &rb);