瀏覽代碼

fix prepare_scene() to prepare vertex buffers as well as textures

David Rose 14 年之前
父節點
當前提交
83b87652f8

+ 21 - 18
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -2785,16 +2785,16 @@ update_standard_vertex_arrays(bool force) {
 void CLP(GraphicsStateGuardian)::
 void CLP(GraphicsStateGuardian)::
 unbind_buffers() {
 unbind_buffers() {
   if (_current_vbuffer_index != 0) {
   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";
         << "unbinding vertex buffer\n";
     }
     }
     _glBindBuffer(GL_ARRAY_BUFFER, 0);
     _glBindBuffer(GL_ARRAY_BUFFER, 0);
     _current_vbuffer_index = 0;
     _current_vbuffer_index = 0;
   }
   }
   if (_current_ibuffer_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";
         << "unbinding index buffer\n";
     }
     }
     _glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
     _glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
@@ -3579,6 +3579,7 @@ prepare_vertex_buffer(GeomVertexArrayData *data) {
     }
     }
 
 
     report_my_gl_errors();
     report_my_gl_errors();
+    apply_vertex_buffer(gvbc, data->get_handle(), false);
     return gvbc;
     return gvbc;
   }
   }
 
 
@@ -3600,8 +3601,8 @@ apply_vertex_buffer(VertexBufferContext *vbc,
   CLP(VertexBufferContext) *gvbc = DCAST(CLP(VertexBufferContext), vbc);
   CLP(VertexBufferContext) *gvbc = DCAST(CLP(VertexBufferContext), vbc);
 
 
   if (_current_vbuffer_index != gvbc->_index) {
   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";
         << "binding vertex buffer " << gvbc->_index << "\n";
     }
     }
     _glBindBuffer(GL_ARRAY_BUFFER, gvbc->_index);
     _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
   // help out a flaky driver, and we need to keep our internal state
   // consistent anyway.
   // consistent anyway.
   if (_current_vbuffer_index == gvbc->_index) {
   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";
         << "unbinding vertex buffer\n";
     }
     }
     _glBindBuffer(GL_ARRAY_BUFFER, 0);
     _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
     // The array specifies client rendering only, or buffer objects
     // are configured off.
     // are configured off.
     if (_current_vbuffer_index != 0) {
     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";
           << "unbinding vertex buffer\n";
       }
       }
       _glBindBuffer(GL_ARRAY_BUFFER, 0);
       _glBindBuffer(GL_ARRAY_BUFFER, 0);
@@ -3765,6 +3766,8 @@ prepare_index_buffer(GeomPrimitive *data) {
     }
     }
 
 
     report_my_gl_errors();
     report_my_gl_errors();
+    GeomPrimitivePipelineReader reader(data, Thread::get_current_thread());
+    apply_index_buffer(gibc, &reader, false);
     return gibc;
     return gibc;
   }
   }
 
 
@@ -3787,8 +3790,8 @@ apply_index_buffer(IndexBufferContext *ibc,
   CLP(IndexBufferContext) *gibc = DCAST(CLP(IndexBufferContext), ibc);
   CLP(IndexBufferContext) *gibc = DCAST(CLP(IndexBufferContext), ibc);
 
 
   if (_current_ibuffer_index != gibc->_index) {
   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";
         << "binding index buffer " << gibc->_index << "\n";
     }
     }
     _glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gibc->_index);
     _glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gibc->_index);
@@ -3798,8 +3801,8 @@ apply_index_buffer(IndexBufferContext *ibc,
 
 
   if (gibc->was_modified(reader)) {
   if (gibc->was_modified(reader)) {
     int num_bytes = reader->get_data_size_bytes();
     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
         << "copying " << num_bytes
         << " bytes into index buffer " << gibc->_index << "\n";
         << " 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
   // help out a flaky driver, and we need to keep our internal state
   // consistent anyway.
   // consistent anyway.
   if (_current_ibuffer_index == gibc->_index) {
   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";
         << "unbinding index buffer\n";
     }
     }
     _glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
     _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
     // The array specifies client rendering only, or buffer objects
     // are configured off.
     // are configured off.
     if (_current_ibuffer_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";
           << "unbinding index buffer\n";
       }
       }
       _glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
       _glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

+ 1 - 0
panda/src/gobj/geomPrimitive.I

@@ -237,6 +237,7 @@ get_max_vertex() const {
 INLINE int GeomPrimitive::
 INLINE int GeomPrimitive::
 get_data_size_bytes() const {
 get_data_size_bytes() const {
   CDReader cdata(_cycler);
   CDReader cdata(_cycler);
+  nassertr(!cdata->_vertices.is_null(), 0);
   return cdata->_vertices.get_read_pointer()->get_data_size_bytes();
   return cdata->_vertices.get_read_pointer()->get_data_size_bytes();
 }
 }
 
 

+ 5 - 1
panda/src/gobj/geomPrimitive.cxx

@@ -1309,7 +1309,9 @@ get_num_unused_vertices_per_primitive() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void GeomPrimitive::
 void GeomPrimitive::
 prepare(PreparedGraphicsObjects *prepared_objects) {
 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::
 IndexBufferContext *GeomPrimitive::
 prepare_now(PreparedGraphicsObjects *prepared_objects, 
 prepare_now(PreparedGraphicsObjects *prepared_objects, 
             GraphicsStateGuardianBase *gsg) {
             GraphicsStateGuardianBase *gsg) {
+  nassertr(is_indexed(), NULL);
+
   Contexts::const_iterator ci;
   Contexts::const_iterator ci;
   ci = _contexts.find(prepared_objects);
   ci = _contexts.find(prepared_objects);
   if (ci != _contexts.end()) {
   if (ci != _contexts.end()) {

+ 31 - 5
panda/src/pgraph/geomNode.cxx

@@ -384,14 +384,40 @@ safe_to_combine() const {
 //               NodePath::prepare_scene() instead.
 //               NodePath::prepare_scene() instead.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void GeomNode::
 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);
   CDReader cdata(_cycler, current_thread);
   GeomList::const_iterator gi;
   GeomList::const_iterator gi;
   CPT(GeomList) geoms = cdata->get_geoms();
   CPT(GeomList) geoms = cdata->get_geoms();
   for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
   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 = 
     const RenderAttrib *attrib = 
       geom_state->get_attrib(TextureAttrib::get_class_slot());
       geom_state->get_attrib(TextureAttrib::get_class_slot());
     if (attrib != (const RenderAttrib *)NULL) {
     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);
 }
 }
 
 
 
 

+ 3 - 2
panda/src/pgraph/geomNode.h

@@ -60,8 +60,9 @@ public:
   virtual bool safe_to_flatten() const;
   virtual bool safe_to_flatten() const;
   virtual bool safe_to_combine() 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);
                                Thread *current_thread);
 
 
 PUBLISHED:
 PUBLISHED:

+ 4 - 5
panda/src/pgraph/nodePath.cxx

@@ -6588,16 +6588,15 @@ premunge_scene(GraphicsStateGuardianBase *gsg) {
 //               but this may take some of the overhead away from that
 //               but this may take some of the overhead away from that
 //               process.
 //               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::
 void NodePath::
 prepare_scene(GraphicsStateGuardianBase *gsg) {
 prepare_scene(GraphicsStateGuardianBase *gsg) {
   nassertv_always(!is_empty());
   nassertv_always(!is_empty());
 
 
-  CPT(RenderState) net_state = get_net_state();
-  node()->prepare_scene(gsg, net_state);
+  node()->prepare_scene(gsg, get_net_state());
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 12 - 13
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
 //               but this may take some of the overhead away from that
 //               process.
 //               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::
 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();
   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.
 //               NodePath::prepare_scene() instead.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void PandaNode::
 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);
   Children children = get_children(current_thread);
   // We must call get_num_children() each time through the loop, in
   // We must call get_num_children() each time through the loop, in
   // case we're running SIMPLE_THREADS and we get interrupted.
   // case we're running SIMPLE_THREADS and we get interrupted.
   int i;
   int i;
   for (i = 0; i < children.get_num_children(); i++) {
   for (i = 0; i < children.get_num_children(); i++) {
     PandaNode *child = children.get_child(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);
   Stashed stashed = get_stashed(current_thread);
   for (i = 0; i < stashed.get_num_stashed(); i++) {
   for (i = 0; i < stashed.get_num_stashed(); i++) {
     PandaNode *child = stashed.get_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);
   }
   }
 }
 }
 
 

+ 4 - 3
panda/src/pgraph/pandaNode.h

@@ -250,7 +250,7 @@ PUBLISHED:
   CollideMask get_net_collide_mask(Thread *current_thread = Thread::get_current_thread()) const;
   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;
   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_scene_root() const;
   bool is_under_scene_root() const;
   bool is_under_scene_root() const;
@@ -343,8 +343,9 @@ protected:
   void set_cull_callback();
   void set_cull_callback();
   void disable_cull_callback();
   void disable_cull_callback();
 public:
 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);
                                Thread *current_thread);
 
 
 protected:
 protected:

+ 5 - 6
panda/src/pgui/pgItem.cxx

@@ -359,21 +359,20 @@ compute_internal_bounds(CPT(BoundingVolume) &internal_bounds,
 //               NodePath::prepare_scene() instead.
 //               NodePath::prepare_scene() instead.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void PGItem::
 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);
   LightReMutexHolder holder(_lock);
   StateDefs::iterator di;
   StateDefs::iterator di;
   for (di = _state_defs.begin(); di != _state_defs.end(); ++di) {
   for (di = _state_defs.begin(); di != _state_defs.end(); ++di) {
     NodePath &root = (*di)._root;
     NodePath &root = (*di)._root;
     if (!root.is_empty()) {
     if (!root.is_empty()) {
       PandaNode *child = root.node();
       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);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 3 - 2
panda/src/pgui/pgItem.h

@@ -77,8 +77,9 @@ protected:
                                        int pipeline_stage,
                                        int pipeline_stage,
                                        Thread *current_thread) const;
                                        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);
                                Thread *current_thread);
 
 
 public:
 public:

+ 5 - 6
panda/src/text/textNode.cxx

@@ -757,18 +757,17 @@ compute_internal_bounds(CPT(BoundingVolume) &internal_bounds,
 //               NodePath::prepare_scene() instead.
 //               NodePath::prepare_scene() instead.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void TextNode::
 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();
   check_rebuild();
 
 
   PandaNode *child = _internal_geom;
   PandaNode *child = _internal_geom;
   if (child != (PandaNode *)NULL) {
   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);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 3 - 2
panda/src/text/textNode.h

@@ -259,8 +259,9 @@ public:
                                        int pipeline_stage,
                                        int pipeline_stage,
                                        Thread *current_thread) const;
                                        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);
                                Thread *current_thread);
 
 
 private:
 private: