diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index c81cd51eb2..7bef6cdd39 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -2785,16 +2785,16 @@ update_standard_vertex_arrays(bool force) { void CLP(GraphicsStateGuardian):: unbind_buffers() { if (_current_vbuffer_index != 0) { - if (GLCAT.is_debug() && CLP(debug_buffers)) { - GLCAT.debug() + if (GLCAT.is_spam() && CLP(debug_buffers)) { + GLCAT.spam() << "unbinding vertex buffer\n"; } _glBindBuffer(GL_ARRAY_BUFFER, 0); _current_vbuffer_index = 0; } if (_current_ibuffer_index != 0) { - if (GLCAT.is_debug() && CLP(debug_buffers)) { - GLCAT.debug() + if (GLCAT.is_spam() && CLP(debug_buffers)) { + GLCAT.spam() << "unbinding index buffer\n"; } _glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); @@ -3579,6 +3579,7 @@ prepare_vertex_buffer(GeomVertexArrayData *data) { } report_my_gl_errors(); + apply_vertex_buffer(gvbc, data->get_handle(), false); return gvbc; } @@ -3600,8 +3601,8 @@ apply_vertex_buffer(VertexBufferContext *vbc, CLP(VertexBufferContext) *gvbc = DCAST(CLP(VertexBufferContext), vbc); if (_current_vbuffer_index != gvbc->_index) { - if (GLCAT.is_debug() && CLP(debug_buffers)) { - GLCAT.debug() + if (GLCAT.is_spam() && CLP(debug_buffers)) { + GLCAT.spam() << "binding vertex buffer " << gvbc->_index << "\n"; } _glBindBuffer(GL_ARRAY_BUFFER, gvbc->_index); @@ -3666,8 +3667,8 @@ release_vertex_buffer(VertexBufferContext *vbc) { // help out a flaky driver, and we need to keep our internal state // consistent anyway. if (_current_vbuffer_index == gvbc->_index) { - if (GLCAT.is_debug() && CLP(debug_buffers)) { - GLCAT.debug() + if (GLCAT.is_spam() && CLP(debug_buffers)) { + GLCAT.spam() << "unbinding vertex buffer\n"; } _glBindBuffer(GL_ARRAY_BUFFER, 0); @@ -3714,8 +3715,8 @@ setup_array_data(const unsigned char *&client_pointer, // The array specifies client rendering only, or buffer objects // are configured off. if (_current_vbuffer_index != 0) { - if (GLCAT.is_debug() && CLP(debug_buffers)) { - GLCAT.debug() + if (GLCAT.is_spam() && CLP(debug_buffers)) { + GLCAT.spam() << "unbinding vertex buffer\n"; } _glBindBuffer(GL_ARRAY_BUFFER, 0); @@ -3765,6 +3766,8 @@ prepare_index_buffer(GeomPrimitive *data) { } report_my_gl_errors(); + GeomPrimitivePipelineReader reader(data, Thread::get_current_thread()); + apply_index_buffer(gibc, &reader, false); return gibc; } @@ -3787,8 +3790,8 @@ apply_index_buffer(IndexBufferContext *ibc, CLP(IndexBufferContext) *gibc = DCAST(CLP(IndexBufferContext), ibc); if (_current_ibuffer_index != gibc->_index) { - if (GLCAT.is_debug() && CLP(debug_buffers)) { - GLCAT.debug() + if (GLCAT.is_spam() && CLP(debug_buffers)) { + GLCAT.spam() << "binding index buffer " << gibc->_index << "\n"; } _glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gibc->_index); @@ -3798,8 +3801,8 @@ apply_index_buffer(IndexBufferContext *ibc, if (gibc->was_modified(reader)) { int num_bytes = reader->get_data_size_bytes(); - if (GLCAT.is_spam()) { - GLCAT.spam() + if (GLCAT.is_debug() && CLP(debug_buffers)) { + GLCAT.debug() << "copying " << num_bytes << " bytes into index buffer " << gibc->_index << "\n"; } @@ -3853,8 +3856,8 @@ release_index_buffer(IndexBufferContext *ibc) { // help out a flaky driver, and we need to keep our internal state // consistent anyway. if (_current_ibuffer_index == gibc->_index) { - if (GLCAT.is_debug() && CLP(debug_buffers)) { - GLCAT.debug() + if (GLCAT.is_spam() && CLP(debug_buffers)) { + GLCAT.spam() << "unbinding index buffer\n"; } _glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); @@ -3901,8 +3904,8 @@ setup_primitive(const unsigned char *&client_pointer, // The array specifies client rendering only, or buffer objects // are configured off. if (_current_ibuffer_index != 0) { - if (GLCAT.is_debug() && CLP(debug_buffers)) { - GLCAT.debug() + if (GLCAT.is_spam() && CLP(debug_buffers)) { + GLCAT.spam() << "unbinding index buffer\n"; } _glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); diff --git a/panda/src/gobj/geomPrimitive.I b/panda/src/gobj/geomPrimitive.I index 2dfcefb141..a593e01734 100644 --- a/panda/src/gobj/geomPrimitive.I +++ b/panda/src/gobj/geomPrimitive.I @@ -237,6 +237,7 @@ get_max_vertex() const { INLINE int GeomPrimitive:: get_data_size_bytes() const { CDReader cdata(_cycler); + nassertr(!cdata->_vertices.is_null(), 0); return cdata->_vertices.get_read_pointer()->get_data_size_bytes(); } diff --git a/panda/src/gobj/geomPrimitive.cxx b/panda/src/gobj/geomPrimitive.cxx index 94bb463707..babdfb36d6 100644 --- a/panda/src/gobj/geomPrimitive.cxx +++ b/panda/src/gobj/geomPrimitive.cxx @@ -1309,7 +1309,9 @@ get_num_unused_vertices_per_primitive() const { //////////////////////////////////////////////////////////////////// void GeomPrimitive:: prepare(PreparedGraphicsObjects *prepared_objects) { - prepared_objects->enqueue_index_buffer(this); + if (is_indexed()) { + prepared_objects->enqueue_index_buffer(this); + } } //////////////////////////////////////////////////////////////////// @@ -1348,6 +1350,8 @@ is_prepared(PreparedGraphicsObjects *prepared_objects) const { IndexBufferContext *GeomPrimitive:: prepare_now(PreparedGraphicsObjects *prepared_objects, GraphicsStateGuardianBase *gsg) { + nassertr(is_indexed(), NULL); + Contexts::const_iterator ci; ci = _contexts.find(prepared_objects); if (ci != _contexts.end()) { diff --git a/panda/src/pgraph/geomNode.cxx b/panda/src/pgraph/geomNode.cxx index 9b5cc91821..b0b319efbe 100644 --- a/panda/src/pgraph/geomNode.cxx +++ b/panda/src/pgraph/geomNode.cxx @@ -384,14 +384,40 @@ safe_to_combine() const { // NodePath::prepare_scene() instead. //////////////////////////////////////////////////////////////////// void GeomNode:: -r_prepare_scene(const RenderState *state, - PreparedGraphicsObjects *prepared_objects, - Thread *current_thread) { +r_prepare_scene(GraphicsStateGuardianBase *gsg, const RenderState *node_state, + GeomTransformer &transformer, Thread *current_thread) { + PreparedGraphicsObjects *prepared_objects = gsg->get_prepared_objects(); + CDReader cdata(_cycler, current_thread); GeomList::const_iterator gi; CPT(GeomList) geoms = cdata->get_geoms(); for (gi = geoms->begin(); gi != geoms->end(); ++gi) { - CPT(RenderState) geom_state = state->compose((*gi)._state); + const GeomEntry &entry = (*gi); + CPT(RenderState) geom_state = node_state->compose(entry._state); + CPT(Geom) geom = entry._geom.get_read_pointer(); + + // Munge the geom as required by the GSG. + PT(GeomMunger) munger = gsg->get_geom_munger(geom_state, current_thread); + geom = transformer.premunge_geom(geom, munger); + + // Prepare each of the vertex arrays in the munged Geom. + CPT(GeomVertexData) vdata = geom->get_vertex_data(current_thread); + vdata = vdata->animate_vertices(false, current_thread); + GeomVertexDataPipelineReader vdata_reader(vdata, current_thread); + int num_arrays = vdata_reader.get_num_arrays(); + for (int i = 0; i < num_arrays; ++i) { + CPT(GeomVertexArrayData) array = vdata_reader.get_array(i); + ((GeomVertexArrayData *)array.p())->prepare(prepared_objects); + } + + // And also each of the index arrays. + int num_primitives = geom->get_num_primitives(); + for (int i = 0; i < num_primitives; ++i) { + CPT(GeomPrimitive) prim = geom->get_primitive(i); + ((GeomPrimitive *)prim.p())->prepare(prepared_objects); + } + + // And now prepare each of the textures. const RenderAttrib *attrib = geom_state->get_attrib(TextureAttrib::get_class_slot()); if (attrib != (const RenderAttrib *)NULL) { @@ -407,7 +433,7 @@ r_prepare_scene(const RenderState *state, } } - PandaNode::r_prepare_scene(state, prepared_objects, current_thread); + PandaNode::r_prepare_scene(gsg, node_state, transformer, current_thread); } diff --git a/panda/src/pgraph/geomNode.h b/panda/src/pgraph/geomNode.h index 3f8b64ce60..ffedec99c2 100644 --- a/panda/src/pgraph/geomNode.h +++ b/panda/src/pgraph/geomNode.h @@ -60,8 +60,9 @@ public: virtual bool safe_to_flatten() const; virtual bool safe_to_combine() const; - virtual void r_prepare_scene(const RenderState *state, - PreparedGraphicsObjects *prepared_objects, + virtual void r_prepare_scene(GraphicsStateGuardianBase *gsg, + const RenderState *node_state, + GeomTransformer &transformer, Thread *current_thread); PUBLISHED: diff --git a/panda/src/pgraph/nodePath.cxx b/panda/src/pgraph/nodePath.cxx index 93a5731dd5..9a35a7876d 100644 --- a/panda/src/pgraph/nodePath.cxx +++ b/panda/src/pgraph/nodePath.cxx @@ -6588,16 +6588,15 @@ premunge_scene(GraphicsStateGuardianBase *gsg) { // but this may take some of the overhead away from that // process. // -// In particular, this will ensure that textures within -// the scene are loaded in texture memory, and display -// lists are built up from static geometry. +// In particular, this will ensure that textures and +// vertex buffers within the scene are loaded into +// graphics memory. //////////////////////////////////////////////////////////////////// void NodePath:: prepare_scene(GraphicsStateGuardianBase *gsg) { nassertv_always(!is_empty()); - CPT(RenderState) net_state = get_net_state(); - node()->prepare_scene(gsg, net_state); + node()->prepare_scene(gsg, get_net_state()); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/pgraph/pandaNode.cxx b/panda/src/pgraph/pandaNode.cxx index df05345f83..53e46482fe 100644 --- a/panda/src/pgraph/pandaNode.cxx +++ b/panda/src/pgraph/pandaNode.cxx @@ -2261,15 +2261,15 @@ get_off_clip_planes(Thread *current_thread) const { // but this may take some of the overhead away from that // process. // -// In particular, this will ensure that textures within -// the scene are loaded in texture memory, and display -// lists are built up from static geometry. +// In particular, this will ensure that textures and +// vertex buffers within the scene are loaded into +// graphics memory. //////////////////////////////////////////////////////////////////// void PandaNode:: -prepare_scene(GraphicsStateGuardianBase *gsg, const RenderState *net_state) { +prepare_scene(GraphicsStateGuardianBase *gsg, const RenderState *node_state) { + GeomTransformer transformer; Thread *current_thread = Thread::get_current_thread(); - PreparedGraphicsObjects *prepared_objects = gsg->get_prepared_objects(); - r_prepare_scene(net_state, prepared_objects, current_thread); + r_prepare_scene(gsg, node_state, transformer, current_thread); } //////////////////////////////////////////////////////////////////// @@ -3046,24 +3046,23 @@ r_copy_children(const PandaNode *from, PandaNode::InstanceMap &inst_map, // NodePath::prepare_scene() instead. //////////////////////////////////////////////////////////////////// void PandaNode:: -r_prepare_scene(const RenderState *state, - PreparedGraphicsObjects *prepared_objects, - Thread *current_thread) { +r_prepare_scene(GraphicsStateGuardianBase *gsg, const RenderState *node_state, + GeomTransformer &transformer, Thread *current_thread) { Children children = get_children(current_thread); // We must call get_num_children() each time through the loop, in // case we're running SIMPLE_THREADS and we get interrupted. int i; for (i = 0; i < children.get_num_children(); i++) { PandaNode *child = children.get_child(i); - CPT(RenderState) child_state = state->compose(child->get_state()); - child->r_prepare_scene(child_state, prepared_objects, current_thread); + CPT(RenderState) child_state = node_state->compose(child->get_state()); + child->r_prepare_scene(gsg, child_state, transformer, current_thread); } Stashed stashed = get_stashed(current_thread); for (i = 0; i < stashed.get_num_stashed(); i++) { PandaNode *child = stashed.get_stashed(i); - CPT(RenderState) child_state = state->compose(child->get_state()); - child->r_prepare_scene(child_state, prepared_objects, current_thread); + CPT(RenderState) child_state = node_state->compose(child->get_state()); + child->r_prepare_scene(gsg, child_state, transformer, current_thread); } } diff --git a/panda/src/pgraph/pandaNode.h b/panda/src/pgraph/pandaNode.h index f80f1a4e68..186d99aba3 100644 --- a/panda/src/pgraph/pandaNode.h +++ b/panda/src/pgraph/pandaNode.h @@ -250,7 +250,7 @@ PUBLISHED: CollideMask get_net_collide_mask(Thread *current_thread = Thread::get_current_thread()) const; CPT(RenderAttrib) get_off_clip_planes(Thread *current_thread = Thread::get_current_thread()) const; - void prepare_scene(GraphicsStateGuardianBase *gsg, const RenderState *net_state); + void prepare_scene(GraphicsStateGuardianBase *gsg, const RenderState *node_state); bool is_scene_root() const; bool is_under_scene_root() const; @@ -343,8 +343,9 @@ protected: void set_cull_callback(); void disable_cull_callback(); public: - virtual void r_prepare_scene(const RenderState *state, - PreparedGraphicsObjects *prepared_objects, + virtual void r_prepare_scene(GraphicsStateGuardianBase *gsg, + const RenderState *node_state, + GeomTransformer &transformer, Thread *current_thread); protected: diff --git a/panda/src/pgui/pgItem.cxx b/panda/src/pgui/pgItem.cxx index 967a5bb8fa..018f630ad7 100644 --- a/panda/src/pgui/pgItem.cxx +++ b/panda/src/pgui/pgItem.cxx @@ -359,21 +359,20 @@ compute_internal_bounds(CPT(BoundingVolume) &internal_bounds, // NodePath::prepare_scene() instead. //////////////////////////////////////////////////////////////////// void PGItem:: -r_prepare_scene(const RenderState *state, - PreparedGraphicsObjects *prepared_objects, - Thread *current_thread) { +r_prepare_scene(GraphicsStateGuardianBase *gsg, const RenderState *node_state, + GeomTransformer &transformer, Thread *current_thread) { LightReMutexHolder holder(_lock); StateDefs::iterator di; for (di = _state_defs.begin(); di != _state_defs.end(); ++di) { NodePath &root = (*di)._root; if (!root.is_empty()) { PandaNode *child = root.node(); - CPT(RenderState) child_state = state->compose(child->get_state()); - child->r_prepare_scene(child_state, prepared_objects, current_thread); + CPT(RenderState) child_state = node_state->compose(child->get_state()); + child->r_prepare_scene(gsg, child_state, transformer, current_thread); } } - PandaNode::r_prepare_scene(state, prepared_objects, current_thread); + PandaNode::r_prepare_scene(gsg, node_state, transformer, current_thread); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/pgui/pgItem.h b/panda/src/pgui/pgItem.h index fcc2e30283..635f9abfca 100644 --- a/panda/src/pgui/pgItem.h +++ b/panda/src/pgui/pgItem.h @@ -77,8 +77,9 @@ protected: int pipeline_stage, Thread *current_thread) const; - virtual void r_prepare_scene(const RenderState *state, - PreparedGraphicsObjects *prepared_objects, + virtual void r_prepare_scene(GraphicsStateGuardianBase *gsg, + const RenderState *node_state, + GeomTransformer &transformer, Thread *current_thread); public: diff --git a/panda/src/text/textNode.cxx b/panda/src/text/textNode.cxx index c42e2a8b03..673755a58b 100644 --- a/panda/src/text/textNode.cxx +++ b/panda/src/text/textNode.cxx @@ -757,18 +757,17 @@ compute_internal_bounds(CPT(BoundingVolume) &internal_bounds, // NodePath::prepare_scene() instead. //////////////////////////////////////////////////////////////////// void TextNode:: -r_prepare_scene(const RenderState *state, - PreparedGraphicsObjects *prepared_objects, - Thread *current_thread) { +r_prepare_scene(GraphicsStateGuardianBase *gsg, const RenderState *node_state, + GeomTransformer &transformer, Thread *current_thread) { check_rebuild(); PandaNode *child = _internal_geom; if (child != (PandaNode *)NULL) { - CPT(RenderState) child_state = state->compose(child->get_state()); - child->r_prepare_scene(child_state, prepared_objects, current_thread); + CPT(RenderState) child_state = node_state->compose(child->get_state()); + child->r_prepare_scene(gsg, child_state, transformer, current_thread); } - PandaNode::r_prepare_scene(state, prepared_objects, current_thread); + PandaNode::r_prepare_scene(gsg, node_state, transformer, current_thread); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/text/textNode.h b/panda/src/text/textNode.h index 38e21b3ef9..3cc4737a86 100644 --- a/panda/src/text/textNode.h +++ b/panda/src/text/textNode.h @@ -259,8 +259,9 @@ public: int pipeline_stage, Thread *current_thread) const; - virtual void r_prepare_scene(const RenderState *state, - PreparedGraphicsObjects *prepared_objects, + virtual void r_prepare_scene(GraphicsStateGuardianBase *gsg, + const RenderState *node_state, + GeomTransformer &transformer, Thread *current_thread); private: