Browse Source

egg loader and bam loader set a ColorAttrib on every Geom.

David Rose 18 years ago
parent
commit
775466b4bd

+ 37 - 0
panda/src/egg/eggVertexPool.cxx

@@ -272,6 +272,43 @@ has_nonwhite_colors() const {
   return false;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: EggVertexPool::check_overall_color
+//       Access: Public
+//  Description: Scans the vertex pool for different colors on
+//               different vertices.  If all vertices are the same
+//               color, sets has_overall_color to true and fills the
+//               color into overall_color.  If no vertices have any
+//               color, set has_overall_color to true and fills white
+//               into overall_color.  If at least two vertices have
+//               different colors, sets has_overall_color to false.
+////////////////////////////////////////////////////////////////////
+void EggVertexPool::
+check_overall_color(bool &has_overall_color, Colorf &overall_color) const {
+  if (empty()) {
+    has_overall_color = true;
+    overall_color.set(1.0f, 1.0f, 1.0f, 1.0f);
+    return;
+  }
+
+  IndexVertices::const_iterator ivi;
+  ivi = _index_vertices.begin();
+  EggVertex *vertex = (*ivi).second;
+  overall_color = vertex->get_color();
+
+  ++ivi;
+  while (ivi != _index_vertices.end()) {
+    vertex = (*ivi).second;
+    if (!vertex->get_color().almost_equal(overall_color)) {
+      has_overall_color = false;
+      return;
+    }
+    ++ivi;
+  }
+
+  has_overall_color = true;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: EggVertexPool::has_uvs
 //       Access: Public

+ 1 - 0
panda/src/egg/eggVertexPool.h

@@ -98,6 +98,7 @@ PUBLISHED:
   bool has_normals() const;
   bool has_colors() const;
   bool has_nonwhite_colors() const;
+  void check_overall_color(bool &has_overall_color, Colorf &overall_color) const;
   bool has_uvs() const;
   void get_uv_names(vector_string &uv_names, vector_string &uvw_names, 
                     vector_string &tbn_names) const;

+ 22 - 9
panda/src/egg2pg/eggLoader.cxx

@@ -366,6 +366,10 @@ make_polyset(EggBin *egg_bin, PandaNode *parent, const LMatrix4d *transform,
     EggVertexPool *vertex_pool = (*vpi);
     vertex_pool->remove_unused_vertices();
     //  vertex_pool->write(cerr, 0);
+
+    bool has_overall_color;
+    Colorf overall_color;
+    vertex_pool->check_overall_color(has_overall_color, overall_color);
     
     // Create a handful of GeomPrimitives corresponding to the various
     // types of primitives that reference this vertex pool.
@@ -375,7 +379,8 @@ make_polyset(EggBin *egg_bin, PandaNode *parent, const LMatrix4d *transform,
       EggPrimitive *egg_prim;
       DCAST_INTO_V(egg_prim, (*ci));
       if (egg_prim->get_pool() == vertex_pool) {
-        make_primitive(render_state, egg_prim, unique_primitives, primitives);
+        make_primitive(render_state, egg_prim, unique_primitives, primitives,
+                       has_overall_color, overall_color);
       }
     }
 
@@ -390,7 +395,7 @@ make_polyset(EggBin *egg_bin, PandaNode *parent, const LMatrix4d *transform,
       // Now convert this vertex pool to a GeomVertexData.
       PT(GeomVertexData) vertex_data = 
         make_vertex_data(render_state, vertex_pool, egg_bin, mat,
-                         is_dynamic, character_maker);
+                         is_dynamic, character_maker, has_overall_color);
       nassertv(vertex_data != (GeomVertexData *)NULL);
 
       // And create a Geom to hold the primitives.
@@ -425,7 +430,14 @@ make_polyset(EggBin *egg_bin, PandaNode *parent, const LMatrix4d *transform,
         }
       }
 
-      geom_node->add_geom(geom, render_state->_state);
+      CPT(RenderState) geom_state = render_state->_state;
+      if (has_overall_color) {
+        geom_state = geom_state->add_attrib(ColorAttrib::make_flat(overall_color), -1);
+      } else {
+        geom_state = geom_state->add_attrib(ColorAttrib::make_vertex(), -1);
+      }
+
+      geom_node->add_geom(geom, geom_state);
     }
   }
    
@@ -2044,7 +2056,8 @@ PT(GeomVertexData) EggLoader::
 make_vertex_data(const EggRenderState *render_state, 
                  EggVertexPool *vertex_pool, EggNode *primitive_home,
                  const LMatrix4d &transform,
-                 bool is_dynamic, CharacterMaker *character_maker) {
+                 bool is_dynamic, CharacterMaker *character_maker,
+                 bool ignore_color) {
   VertexPoolTransform vpt;
   vpt._vertex_pool = vertex_pool;
   vpt._bake_in_uvs = render_state->_bake_in_uvs;
@@ -2068,8 +2081,7 @@ make_vertex_data(const EggRenderState *render_state,
        Geom::NT_float32, Geom::C_vector);
   }
 
-  bool has_colors = vertex_pool->has_nonwhite_colors();
-  if (has_colors) {
+  if (!ignore_color) {
     array_format->add_column
       (InternalName::get_color(), 1, 
        Geom::NT_packed_dabc, Geom::C_color);
@@ -2149,7 +2161,7 @@ make_vertex_data(const EggRenderState *render_state,
                        InternalName::get_normal(), 3);
         }
       }
-      if (has_colors && vertex->has_color()) {
+      if (!ignore_color && vertex->has_color()) {
         EggMorphColorList::const_iterator mci;
         for (mci = vertex->_drgbas.begin(); mci != vertex->_drgbas.end(); ++mci) {
           slider_names[(*mci).get_name()].set_bit(vertex->get_index());
@@ -2248,7 +2260,7 @@ make_vertex_data(const EggRenderState *render_state,
       }
     }
 
-    if (has_colors && vertex->has_color()) {
+    if (!ignore_color && vertex->has_color()) {
       gvw.set_column(InternalName::get_color());
       gvw.add_data4f(vertex->get_color());
 
@@ -2379,7 +2391,8 @@ record_morph(GeomVertexArrayFormat *array_format,
 void EggLoader::
 make_primitive(const EggRenderState *render_state, EggPrimitive *egg_prim, 
                EggLoader::UniquePrimitives &unique_primitives,
-               EggLoader::Primitives &primitives) {
+               EggLoader::Primitives &primitives,
+               bool has_overall_color, const Colorf &overall_color) {
   PT(GeomPrimitive) primitive;
   if (egg_prim->is_of_type(EggPolygon::get_class_type())) {
     if (egg_prim->size() == 3) {

+ 3 - 2
panda/src/egg2pg/eggLoader.h

@@ -147,7 +147,7 @@ private:
   PT(GeomVertexData) make_vertex_data
   (const EggRenderState *render_state, EggVertexPool *vertex_pool, 
    EggNode *primitive_home, const LMatrix4d &transform, bool is_dynamic, 
-   CharacterMaker *character_maker);
+   CharacterMaker *character_maker, bool ignore_color);
   void record_morph
   (GeomVertexArrayFormat *array_format,
    CharacterMaker *character_maker, const string &morph_name, 
@@ -156,7 +156,8 @@ private:
   void make_primitive(const EggRenderState *render_state, 
                       EggPrimitive *egg_prim, 
                       UniquePrimitives &unique_primitives,
-                      Primitives &primitives);
+                      Primitives &primitives,
+                      bool has_overall_color, const Colorf &overall_color);
 
   void set_portal_polygon(EggGroup *egg_group, PortalNode *pnode);
   PT(EggPolygon) find_first_polygon(EggGroup *egg_group);

+ 2 - 5
panda/src/framework/windowFramework.cxx

@@ -652,6 +652,8 @@ NodePath WindowFramework::
 load_default_model(const NodePath &parent) {
   CPT(RenderState) state = RenderState::make_empty();
 
+  state = state->add_attrib(ColorAttrib::make_flat(Colorf(0.5, 0.5, 1.0, 1.0)));
+
   // Get the default texture to apply to the triangle; it's compiled
   // into the code these days.
   string rock_floor_string((const char *)rock_floor, rock_floor_len);
@@ -673,7 +675,6 @@ load_default_model(const NodePath &parent) {
      Geom::UH_static);
   GeomVertexWriter vertex(vdata, InternalName::get_vertex());
   GeomVertexWriter normal(vdata, InternalName::get_normal());
-  GeomVertexWriter color(vdata, InternalName::get_color());
   GeomVertexWriter texcoord(vdata, InternalName::get_texcoord());
 
   vertex.add_data3f(Vertexf::rfu(0.0, 0.0, 0.0));
@@ -684,10 +685,6 @@ load_default_model(const NodePath &parent) {
   normal.add_data3f(Normalf::back());
   normal.add_data3f(Normalf::back());
 
-  color.add_data4f(0.5, 0.5, 1.0, 1.0);
-  color.add_data4f(0.5, 0.5, 1.0, 1.0);
-  color.add_data4f(0.5, 0.5, 1.0, 1.0);
-
   texcoord.add_data2f(0.0, 0.0);
   texcoord.add_data2f(1.0, 0.0);
   texcoord.add_data2f(0.0, 1.0);

+ 25 - 13
panda/src/gobj/geomVertexFormat.cxx

@@ -474,24 +474,36 @@ get_array_with(const InternalName *name) const {
 //               NULL if the name is not used.  Use get_array_with()
 //               to determine which array this column is associated
 //               with.
-//
-//               This may only be called after the format has been
-//               registered.
 ////////////////////////////////////////////////////////////////////
 const GeomVertexColumn *GeomVertexFormat::
 get_column(const InternalName *name) const {
-  nassertr(_is_registered, NULL);
-
-  DataTypesByName::const_iterator ai;
-  ai = _columns_by_name.find(name);
-  if (ai != _columns_by_name.end()) {
-    int array_index = (*ai).second._array_index;
-    int column_index = (*ai).second._column_index;
+  if (!_is_registered) {
+    // If the format hasn't yet been registered, we have to search for
+    // the column the hard way.
+    Arrays::const_iterator ai;
+    for (ai = _arrays.begin(); ai != _arrays.end(); ++ai) {
+      const GeomVertexColumn *column = (*ai)->get_column(name);
+      if (column != (GeomVertexColumn *)NULL) {
+        return column;
+      }
+    }
+    return NULL;
 
-    nassertr(array_index >= 0 && array_index < (int)_arrays.size(), NULL);
-    return _arrays[array_index]->get_column(column_index);
+  } else {
+    // If the format has been registered, we can just check the
+    // toplevel index.
+
+    DataTypesByName::const_iterator ai;
+    ai = _columns_by_name.find(name);
+    if (ai != _columns_by_name.end()) {
+      int array_index = (*ai).second._array_index;
+      int column_index = (*ai).second._column_index;
+      
+      nassertr(array_index >= 0 && array_index < (int)_arrays.size(), NULL);
+      return _arrays[array_index]->get_column(column_index);
+    }
+    return NULL;
   }
-  return NULL;
 }
 
 ////////////////////////////////////////////////////////////////////

+ 8 - 0
panda/src/gobj/transformBlendTable.I

@@ -71,6 +71,14 @@ get_modified(Thread *current_thread) const {
 INLINE int TransformBlendTable::
 get_num_transforms() const {
   consider_rebuild_index();
+
+  if (_num_transforms < 0) {
+    // Even if our index is otherwise accurate, we might have recently
+    // added a blend or two, which would necessitate recomputing this
+    // value--which means we need to rebuild the index.
+    ((TransformBlendTable *)this)->rebuild_index();
+  }
+
   return _num_transforms;
 }
 

+ 19 - 1
panda/src/gobj/transformBlendTable.cxx

@@ -116,9 +116,27 @@ add_blend(const TransformBlend &blend) {
     return (*bi).second;
   }
 
+  bool needs_realloc = (_blends.size() >= _blends.capacity());
   int new_position = (int)_blends.size();
   _blends.push_back(blend);
-  clear_index();
+
+  if (needs_realloc) {
+    // We just reallocated the blends vector, so we must rebuild the
+    // index.
+    clear_index();
+
+  } else {
+    // Since we didn't realloc the blends vector, just update it with
+    // the latest.
+    const TransformBlend &added_blend = _blends[new_position];
+    _blend_index[&added_blend] = new_position;
+    _max_simultaneous_transforms = max(_max_simultaneous_transforms,
+                                       blend.get_num_transforms());
+
+    // We can't compute this one as we go, so set it to a special
+    // value to indicate it needs to be recomputed.
+    _num_transforms = -1;
+  }
 
   return new_position;
 }

+ 50 - 0
panda/src/pgraph/geomNode.cxx

@@ -812,6 +812,52 @@ write_datagram(BamWriter *manager, Datagram &dg) {
   manager->write_cdata(dg, _cycler);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: GeomNode::finalize
+//       Access: Public, Virtual
+//  Description: Called by the BamReader to perform any final actions
+//               needed for setting up the object after all objects
+//               have been read and all pointers have been completed.
+////////////////////////////////////////////////////////////////////
+void GeomNode::
+finalize(BamReader *manager) {
+  if (manager->get_file_minor_ver() < 14) {
+    // With version 6.14, we changed the default ColorAttrib
+    // behavior from make_vertex() to make_flat().  This means that
+    // every Geom that contains vertex colors now needs to have an
+    // explicit ColorAttrib::make_vertex() on its state.
+
+    // Since we shouldn't override a different ColorAttrib inherited
+    // from above, we create this new attrib with an override of -1.
+
+    CPT(InternalName) color = InternalName::get_color();
+    CPT(RenderAttrib) vertex_color = ColorAttrib::make_vertex();
+
+    Thread *current_thread = Thread::get_current_thread();
+    OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
+      CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
+
+      GeomList::iterator gi;
+      PT(GeomList) geoms = cdata->modify_geoms();
+      for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
+        GeomEntry &entry = (*gi);
+        CPT(Geom) geom = entry._geom.get_read_pointer();
+        if (geom->get_vertex_data(current_thread)->has_column(color) &&
+            entry._state->get_color() == (ColorAttrib *)NULL) {
+          // We'll be reassigning the RenderState.  Therefore, save it
+          // temporarily to increment its reference count.
+          PT(BamAuxData) aux_data = new BamAuxData;
+          aux_data->_hold_state = entry._state;
+          manager->set_aux_data((RenderState *)entry._state.p(), "hold_state", aux_data);
+
+          entry._state = entry._state->add_attrib(vertex_color, -1);
+        }
+      }
+    }
+    CLOSE_ITERATE_CURRENT_AND_UPSTREAM(_cycler);
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GeomNode::make_from_bam
 //       Access: Protected, Static
@@ -829,6 +875,10 @@ make_from_bam(const FactoryParams &params) {
   parse_params(params, scan, manager);
   node->fillin(scan, manager);
 
+  if (manager->get_file_minor_ver() < 14) {
+    manager->register_finalize(node);
+  }
+
   return node;
 }
 

+ 10 - 0
panda/src/pgraph/geomNode.h

@@ -169,10 +169,20 @@ public:
 
   INLINE Geoms get_geoms(Thread *current_thread = Thread::get_current_thread()) const;
 
+  // This data is only needed when reading from a bam file.
+  class BamAuxData : public BamReader::AuxData {
+  public:
+    // We just hold a pointer to the RenderState that may otherwise
+    // lose its pointers before it can finalize.
+    CPT(RenderState) _hold_state;
+  };
+
 public:
   static void register_with_read_factory();
   virtual void write_datagram(BamWriter *manager, Datagram &dg);
 
+  virtual void finalize(BamReader *manager);
+
 protected:
   static TypedWritable *make_from_bam(const FactoryParams &params);
   void fillin(DatagramIterator &scan, BamReader *manager);

+ 2 - 1
panda/src/putil/bam.h

@@ -36,7 +36,7 @@ static const unsigned short _bam_major_ver = 6;
 // Bumped to major version 5 on 5/6/05 for new Geom implementation.
 // Bumped to major version 6 on 2/11/06 to factor out PandaNode::CData.
 
-static const unsigned short _bam_minor_ver = 13;
+static const unsigned short _bam_minor_ver = 14;
 // Bumped to minor version 1 on 3/12/06 to add Texture::_compression.
 // Bumped to minor version 2 on 3/17/06 to add PandaNode::_draw_control_mask.
 // Bumped to minor version 3 on 3/21/06 to add Texture::_ram_images.
@@ -50,6 +50,7 @@ static const unsigned short _bam_minor_ver = 13;
 // Bumped to minor version 11 on 6/20/07 to write frozen joints to PartGroups.
 // Bumped to minor version 12 on 7/3/07 to rework control/frozen joints more.
 // Bumped to minor version 13 on 8/15/07 to reverse CollisionPolygon vertices.
+// Bumped to minor version 14 on 12/19/07 to change default ColorAttrib.
 
 
 #endif