Browse Source

Introduce ability to write older .bam versions, down to 6.21
See https://www.panda3d.org/manual/index.php/Dev:Bam_Format

rdb 9 years ago
parent
commit
a2ae62dbda

+ 4 - 1
panda/src/gobj/geomVertexArrayFormat.cxx

@@ -708,7 +708,10 @@ write_datagram(BamWriter *manager, Datagram &dg) {
   dg.add_uint16(_stride);
   dg.add_uint16(_total_bytes);
   dg.add_uint8(_pad_to);
-  dg.add_uint16(_divisor);
+
+  if (manager->get_file_minor_ver() > 36) {
+    dg.add_uint16(_divisor);
+  }
 
   consider_sort_columns();
 

+ 12 - 2
panda/src/gobj/geomVertexColumn.cxx

@@ -378,9 +378,19 @@ write_datagram(BamWriter *manager, Datagram &dg) {
   manager->write_pointer(dg, _name);
   dg.add_uint8(_num_components);
   dg.add_uint8(_numeric_type);
-  dg.add_uint8(_contents);
+
+  if (_contents == C_normal && manager->get_file_minor_ver() < 38) {
+    // Panda 1.9 did not have C_normal.
+    dg.add_uint8(C_vector);
+  } else {
+    dg.add_uint8(_contents);
+  }
+
   dg.add_uint16(_start);
-  dg.add_uint8(_column_alignment);
+
+  if (manager->get_file_minor_ver() >= 29) {
+    dg.add_uint8(_column_alignment);
+  }
 }
 
 /**

+ 23 - 14
panda/src/gobj/material.cxx

@@ -257,7 +257,7 @@ set_roughness(PN_stdfloat roughness) {
   // Calculate the specular exponent from the roughness as it is used in
   // Blinn-Phong shading model.  We use the popular Disney method of squaring
   // the roughness to get a more perceptually linear scale.  From:
-  // http:graphicrants.blogspot.de201308specular-brdf-reference.html
+  // http://graphicrants.blogspot.de/2013/08/specular-brdf-reference.html
   if (roughness <= 0 || IS_NEARLY_ZERO(roughness)) {
     _shininess = make_inf((PN_stdfloat)0);
   } else {
@@ -481,26 +481,35 @@ void Material::
 write_datagram(BamWriter *manager, Datagram &me) {
   me.add_string(get_name());
 
-  me.add_int32(_flags);
+  if (manager->get_file_minor_ver() >= 39) {
+    me.add_int32(_flags);
 
-  if (_flags & F_metallic) {
-    // Metalness workflow.
-    _base_color.write_datagram(me);
-    me.add_stdfloat(_metallic);
+    if (_flags & F_metallic) {
+      // Metalness workflow.
+      _base_color.write_datagram(me);
+      me.add_stdfloat(_metallic);
+    } else {
+      _ambient.write_datagram(me);
+      _diffuse.write_datagram(me);
+      _specular.write_datagram(me);
+    }
+    _emission.write_datagram(me);
+
+    if (_flags & F_roughness) {
+      me.add_stdfloat(_roughness);
+    } else {
+      me.add_stdfloat(_shininess);
+    }
+
+    me.add_stdfloat(_refractive_index);
   } else {
     _ambient.write_datagram(me);
     _diffuse.write_datagram(me);
     _specular.write_datagram(me);
-  }
-  _emission.write_datagram(me);
-
-  if (_flags & F_roughness) {
-    me.add_stdfloat(_roughness);
-  } else {
+    _emission.write_datagram(me);
     me.add_stdfloat(_shininess);
+    me.add_int32(_flags & 0x7f);
   }
-
-  me.add_stdfloat(_refractive_index);
 }
 
 /**

+ 11 - 7
panda/src/gobj/matrixLens.cxx

@@ -83,14 +83,18 @@ register_with_read_factory() {
  */
 void MatrixLens::
 write_datagram(BamWriter *manager, Datagram &dg) {
-  dg.add_uint8(_ml_flags);
-  _user_mat.write_datagram(dg);
+  Lens::write_datagram(manager, dg);
 
-  if (_ml_flags & MF_has_left_eye) {
-    _left_eye_mat.write_datagram(dg);
-  }
-  if (_ml_flags & MF_has_right_eye) {
-    _left_eye_mat.write_datagram(dg);
+  if (manager->get_file_minor_ver() >= 41) {
+    dg.add_uint8(_ml_flags);
+    _user_mat.write_datagram(dg);
+
+    if (_ml_flags & MF_has_left_eye) {
+      _left_eye_mat.write_datagram(dg);
+    }
+    if (_ml_flags & MF_has_right_eye) {
+      _left_eye_mat.write_datagram(dg);
+    }
   }
 }
 

+ 36 - 8
panda/src/gobj/texture.cxx

@@ -8663,8 +8663,19 @@ do_write_datagram_header(CData *cdata, BamWriter *manager, Datagram &me, bool &h
   me.add_uint8(cdata->_primary_file_num_channels);
   me.add_uint8(cdata->_alpha_file_channel);
   me.add_bool(has_rawdata);
-  me.add_uint8(cdata->_texture_type);
-  me.add_bool(cdata->_has_read_mipmaps);
+
+  if (manager->get_file_minor_ver() < 25 &&
+      cdata->_texture_type == TT_cube_map) {
+    // Between Panda3D releases 1.7.2 and 1.8.0 (bam versions 6.24 and 6.25),
+    // we added TT_2d_texture_array, shifting the definition for TT_cube_map.
+    me.add_uint8(TT_2d_texture_array);
+  } else {
+    me.add_uint8(cdata->_texture_type);
+  }
+
+  if (manager->get_file_minor_ver() >= 32) {
+    me.add_bool(cdata->_has_read_mipmaps);
+  }
 }
 
 /**
@@ -8673,7 +8684,18 @@ do_write_datagram_header(CData *cdata, BamWriter *manager, Datagram &me, bool &h
  */
 void Texture::
 do_write_datagram_body(CData *cdata, BamWriter *manager, Datagram &me) {
-  cdata->_default_sampler.write_datagram(me);
+  if (manager->get_file_minor_ver() >= 36) {
+    cdata->_default_sampler.write_datagram(me);
+  } else {
+    const SamplerState &s = cdata->_default_sampler;
+    me.add_uint8(s.get_wrap_u());
+    me.add_uint8(s.get_wrap_v());
+    me.add_uint8(s.get_wrap_w());
+    me.add_uint8(s.get_minfilter());
+    me.add_uint8(s.get_magfilter());
+    me.add_int16(s.get_anisotropic_degree());
+    s.get_border_color().write_datagram(me);
+  }
 
   me.add_uint8(cdata->_compression);
   me.add_uint8(cdata->_quality_level);
@@ -8685,7 +8707,9 @@ do_write_datagram_body(CData *cdata, BamWriter *manager, Datagram &me) {
     me.add_uint8(cdata->_usage_hint);
   }
 
-  me.add_uint8(cdata->_auto_texture_scale);
+  if (manager->get_file_minor_ver() >= 28) {
+    me.add_uint8(cdata->_auto_texture_scale);
+  }
   me.add_uint32(cdata->_orig_file_x_size);
   me.add_uint32(cdata->_orig_file_y_size);
 
@@ -8711,11 +8735,15 @@ do_write_datagram_rawdata(CData *cdata, BamWriter *manager, Datagram &me) {
   me.add_uint32(cdata->_y_size);
   me.add_uint32(cdata->_z_size);
 
-  me.add_uint32(cdata->_pad_x_size);
-  me.add_uint32(cdata->_pad_y_size);
-  me.add_uint32(cdata->_pad_z_size);
+  if (manager->get_file_minor_ver() >= 30) {
+    me.add_uint32(cdata->_pad_x_size);
+    me.add_uint32(cdata->_pad_y_size);
+    me.add_uint32(cdata->_pad_z_size);
+  }
 
-  me.add_uint32(cdata->_num_views);
+  if (manager->get_file_minor_ver() >= 26) {
+    me.add_uint32(cdata->_num_views);
+  }
   me.add_uint8(cdata->_component_type);
   me.add_uint8(cdata->_component_width);
   me.add_uint8(cdata->_ram_image_compression);

+ 4 - 1
panda/src/gobj/textureStage.cxx

@@ -438,7 +438,10 @@ write_datagram(BamWriter *manager, Datagram &me) {
     me.add_uint8(_rgb_scale);
     me.add_uint8(_alpha_scale);
     me.add_bool(_saved_result);
-    me.add_int32(_tex_view_offset);
+
+    if (manager->get_file_minor_ver() >= 26) {
+      me.add_int32(_tex_view_offset);
+    }
 
     me.add_uint8(_combine_rgb_mode);
     me.add_uint8(_num_combine_rgb_operands);

+ 4 - 1
panda/src/grutil/movieTexture.cxx

@@ -816,7 +816,10 @@ do_write_datagram_rawdata(Texture::CData *cdata_tex, BamWriter *manager, Datagra
   CDReader cdata(_cycler);
 
   dg.add_uint16(cdata_tex->_z_size);
-  dg.add_uint16(cdata_tex->_num_views);
+  if (manager->get_file_minor_ver() >= 26) {
+    dg.add_uint16(cdata_tex->_num_views);
+  }
+
   nassertv(cdata->_pages.size() == (size_t)(cdata_tex->_z_size * cdata_tex->_num_views));
   for (size_t n = 0; n < cdata->_pages.size(); ++n) {
     const VideoPage &page = cdata->_pages[n];

+ 18 - 4
panda/src/pgraph/clipPlaneAttrib.cxx

@@ -872,18 +872,32 @@ write_datagram(BamWriter *manager, Datagram &dg) {
 
   // write the number of off_planes
   dg.add_uint16(get_num_off_planes());
+
   // write the off planes pointers if any
   Planes::const_iterator fi;
-  for (fi = _off_planes.begin(); fi != _off_planes.end(); ++fi) {
-    (*fi).write_datagram(manager, dg);
+  if (manager->get_file_minor_ver() < 40) {
+    for (fi = _off_planes.begin(); fi != _off_planes.end(); ++fi) {
+      manager->write_pointer(dg, fi->node());
+    }
+  } else {
+    for (fi = _off_planes.begin(); fi != _off_planes.end(); ++fi) {
+      (*fi).write_datagram(manager, dg);
+    }
   }
 
   // write the number of on planes
   dg.add_uint16(get_num_on_planes());
+
   // write the on planes pointers if any
   Planes::const_iterator nti;
-  for (nti = _on_planes.begin(); nti != _on_planes.end(); ++nti) {
-    (*nti).write_datagram(manager, dg);
+  if (manager->get_file_minor_ver() < 40) {
+    for (nti = _on_planes.begin(); nti != _on_planes.end(); ++nti) {
+      manager->write_pointer(dg, nti->node());
+    }
+  } else {
+    for (nti = _on_planes.begin(); nti != _on_planes.end(); ++nti) {
+      (*nti).write_datagram(manager, dg);
+    }
   }
 }
 

+ 4 - 2
panda/src/pgraph/depthOffsetAttrib.cxx

@@ -162,8 +162,10 @@ write_datagram(BamWriter *manager, Datagram &dg) {
   RenderAttrib::write_datagram(manager, dg);
 
   dg.add_int32(_offset);
-  dg.add_stdfloat(_min_value);
-  dg.add_stdfloat(_max_value);
+  if (manager->get_file_minor_ver() >= 31) {
+    dg.add_stdfloat(_min_value);
+    dg.add_stdfloat(_max_value);
+  }
 }
 
 /**

+ 7 - 3
panda/src/pgraph/light.cxx

@@ -206,9 +206,13 @@ fill_viz_geom(GeomNode *) {
  */
 void Light::
 write_datagram(BamWriter *manager, Datagram &dg) {
-  dg.add_bool(_has_color_temperature);
-  if (_has_color_temperature) {
-    dg.add_stdfloat(_color_temperature);
+  if (manager->get_file_minor_ver() >= 39) {
+    dg.add_bool(_has_color_temperature);
+    if (_has_color_temperature) {
+      dg.add_stdfloat(_color_temperature);
+    } else {
+      manager->write_cdata(dg, _cycler);
+    }
   } else {
     manager->write_cdata(dg, _cycler);
   }

+ 17 - 4
panda/src/pgraph/lightAttrib.cxx

@@ -898,18 +898,31 @@ write_datagram(BamWriter *manager, Datagram &dg) {
 
   // write the number of off_lights
   dg.add_uint16(get_num_off_lights());
+
   // write the off lights pointers if any
   Lights::const_iterator fi;
-  for (fi = _off_lights.begin(); fi != _off_lights.end(); ++fi) {
-    (*fi).write_datagram(manager, dg);
+  if (manager->get_file_minor_ver() < 40) {
+    for (fi = _off_lights.begin(); fi != _off_lights.end(); ++fi) {
+      manager->write_pointer(dg, fi->node());
+    }
+  } else {
+    for (fi = _off_lights.begin(); fi != _off_lights.end(); ++fi) {
+      (*fi).write_datagram(manager, dg);
+    }
   }
 
   // write the number of on lights
   dg.add_uint16(get_num_on_lights());
   // write the on lights pointers if any
   Lights::const_iterator nti;
-  for (nti = _on_lights.begin(); nti != _on_lights.end(); ++nti) {
-    (*nti).write_datagram(manager, dg);
+  if (manager->get_file_minor_ver() < 40) {
+    for (nti = _on_lights.begin(); nti != _on_lights.end(); ++nti) {
+      manager->write_pointer(dg, nti->node());
+    }
+  } else {
+    for (nti = _on_lights.begin(); nti != _on_lights.end(); ++nti) {
+      (*nti).write_datagram(manager, dg);
+    }
   }
 }
 

+ 9 - 2
panda/src/pgraph/occluderEffect.cxx

@@ -146,10 +146,17 @@ write_datagram(BamWriter *manager, Datagram &dg) {
 
   // write the number of on occluders
   dg.add_uint16(get_num_on_occluders());
+
   // write the on occluders pointers if any
   Occluders::const_iterator nti;
-  for (nti = _on_occluders.begin(); nti != _on_occluders.end(); ++nti) {
-    (*nti).write_datagram(manager, dg);
+  if (manager->get_file_minor_ver() < 40) {
+    for (nti = _on_occluders.begin(); nti != _on_occluders.end(); ++nti) {
+      manager->write_pointer(dg, nti->node());
+    }
+  } else {
+    for (nti = _on_occluders.begin(); nti != _on_occluders.end(); ++nti) {
+      (*nti).write_datagram(manager, dg);
+    }
   }
 }
 

+ 12 - 1
panda/src/pgraph/paramNodePath.cxx

@@ -40,7 +40,18 @@ register_with_read_factory() {
 void ParamNodePath::
 write_datagram(BamWriter *manager, Datagram &dg) {
   ParamValueBase::write_datagram(manager, dg);
-  _node_path.write_datagram(manager, dg);
+
+  if (manager->get_file_minor_ver() < 40) {
+    // Before bam 6.40, we did not support writing NodePaths.  Instaed, we
+    // write the PandaNode pointer and pray there is an unambiguous path.
+    if (_node_path.is_empty()) {
+      manager->write_pointer(dg, NULL);
+    } else {
+      manager->write_pointer(dg, _node_path.node());
+    }
+  } else {
+    _node_path.write_datagram(manager, dg);
+  }
 }
 
 /**

+ 3 - 1
panda/src/pgraph/scissorAttrib.cxx

@@ -177,7 +177,9 @@ write_datagram(BamWriter *manager, Datagram &dg) {
   RenderAttrib::write_datagram(manager, dg);
 
   _frame.write_datagram(dg);
-  dg.add_bool(_off);
+  if (manager->get_file_minor_ver() >= 34) {
+    dg.add_bool(_off);
+  }
 }
 
 /**

+ 20 - 2
panda/src/pgraph/stencilAttrib.cxx

@@ -338,8 +338,26 @@ void StencilAttrib::
 write_datagram(BamWriter *manager, Datagram &dg) {
   RenderAttrib::write_datagram(manager, dg);
 
-  for (int index = 0; index < SRS_total; ++index) {
-    dg.add_uint32(_stencil_render_states[index]);
+  if (manager->get_file_minor_ver() < 35) {
+    dg.add_int32(_stencil_render_states[SRS_front_comparison_function] != M_none);
+    dg.add_int32(_stencil_render_states[SRS_back_comparison_function] != M_none);
+
+    for (int index = 0; index < SRS_total; ++index) {
+      if (index == SRS_front_comparison_function ||
+          index == SRS_back_comparison_function) {
+        if (_stencil_render_states[index] == M_none) {
+          dg.add_uint32(7);
+        } else {
+          dg.add_uint32(_stencil_render_states[index] - 1);
+        }
+      } else {
+        dg.add_uint32(_stencil_render_states[index]);
+      }
+    }
+  } else {
+    for (int index = 0; index < SRS_total; ++index) {
+      dg.add_uint32(_stencil_render_states[index]);
+    }
   }
 }
 

+ 4 - 1
panda/src/pgraph/texMatrixAttrib.cxx

@@ -461,7 +461,10 @@ write_datagram(BamWriter *manager, Datagram &dg) {
 
     manager->write_pointer(dg, sn._stage);
     manager->write_pointer(dg, sn._transform);
-    dg.add_int32(sn._override);
+
+    if (manager->get_file_minor_ver() >= 24) {
+      dg.add_int32(sn._override);
+    }
   }
 }
 

+ 10 - 4
panda/src/pgraph/textureAttrib.cxx

@@ -778,10 +778,16 @@ write_datagram(BamWriter *manager, Datagram &dg) {
     manager->write_pointer(dg, stage);
     manager->write_pointer(dg, tex);
     dg.add_uint16((*si)._implicit_sort);
-    dg.add_int32((*si)._override);
-    dg.add_bool((*si)._has_sampler);
-    if ((*si)._has_sampler) {
-      (*si)._sampler.write_datagram(dg);
+
+    if (manager->get_file_minor_ver() >= 23) {
+      dg.add_int32((*si)._override);
+    }
+
+    if (manager->get_file_minor_ver() >= 36) {
+      dg.add_bool((*si)._has_sampler);
+      if ((*si)._has_sampler) {
+        (*si)._sampler.write_datagram(dg);
+      }
     }
   }
 }

+ 3 - 1
panda/src/pgraphnodes/directionalLight.cxx

@@ -167,7 +167,9 @@ register_with_read_factory() {
 void DirectionalLight::
 write_datagram(BamWriter *manager, Datagram &dg) {
   LightLensNode::write_datagram(manager, dg);
-  dg.add_bool(_has_specular_color);
+  if (manager->get_file_minor_ver() >= 39) {
+    dg.add_bool(_has_specular_color);
+  }
   manager->write_cdata(dg, _cycler);
 }
 

+ 3 - 1
panda/src/pgraphnodes/pointLight.cxx

@@ -196,7 +196,9 @@ register_with_read_factory() {
 void PointLight::
 write_datagram(BamWriter *manager, Datagram &dg) {
   LightLensNode::write_datagram(manager, dg);
-  dg.add_bool(_has_specular_color);
+  if (manager->get_file_minor_ver() >= 39) {
+    dg.add_bool(_has_specular_color);
+  }
   manager->write_cdata(dg, _cycler);
 }
 

+ 3 - 1
panda/src/pgraphnodes/spotlight.cxx

@@ -252,7 +252,9 @@ register_with_read_factory() {
 void Spotlight::
 write_datagram(BamWriter *manager, Datagram &dg) {
   LightLensNode::write_datagram(manager, dg);
-  dg.add_bool(_has_specular_color);
+  if (manager->get_file_minor_ver() >= 39) {
+    dg.add_bool(_has_specular_color);
+  }
   manager->write_cdata(dg, _cycler);
 }
 

+ 6 - 2
panda/src/pgraphnodes/uvScrollNode.cxx

@@ -53,8 +53,12 @@ write_datagram(BamWriter *manager, Datagram &dg) {
   PandaNode::write_datagram(manager, dg);
   dg.add_stdfloat(_u_speed);
   dg.add_stdfloat(_v_speed);
-  dg.add_stdfloat(_w_speed);
-  dg.add_stdfloat(_r_speed);
+  if (manager->get_file_minor_ver() >= 33) {
+    dg.add_stdfloat(_w_speed);
+  }
+  if (manager->get_file_minor_ver() >= 22) {
+    dg.add_stdfloat(_r_speed);
+  }
 }
 
 /**

+ 1 - 1
panda/src/pnmimage/pnmFileTypeRegistry.cxx

@@ -127,7 +127,7 @@ get_type_from_extension(const string &filename) const {
   }
 
 #ifdef HAVE_ZLIB
-  if (extension == "pz") {
+  if (extension == "pz" || extension == "gz") {
     // If the extension is .pz, then we've got a Panda-compressed image file.
     // Back up some more and get the extension before that.
     size_t prev_dot = filename.rfind('.', dot - 1);

+ 10 - 0
panda/src/putil/bamWriter.I

@@ -42,6 +42,16 @@ get_file_major_ver() const {
   return _file_major;
 }
 
+/**
+ * Changes the minor .bam version to write.  This should be called before
+ * init().  Each Panda version has only a fairly narrow range of versions it
+ * is able to write; consult the .bam documentation for more information.
+ */
+INLINE void BamWriter::
+set_file_minor_ver(int minor_ver) {
+  _file_minor = minor_ver;
+}
+
 /**
  * Returns the minor version number of the Bam file currently being written.
  */

+ 48 - 7
panda/src/putil/bamWriter.cxx

@@ -41,8 +41,43 @@ BamWriter(DatagramSink *target) :
   _next_pta_id = 1;
   _long_pta_id = false;
 
-  _file_major = _bam_major_ver;
-  _file_minor = _bam_minor_ver;
+  // Check which version .bam files we should write.
+  if (bam_version.get_num_words() > 0) {
+    if (bam_version.get_num_words() != 2) {
+      util_cat.error()
+        << "bam-version configuration variable requires two arguments.\n";
+    }
+    _file_major = bam_version[0];
+    _file_minor = bam_version[1];
+
+    if (_file_major < _bam_major_ver || _file_minor < 21) {
+      util_cat.error()
+        << "bam-version is set to " << bam_version << ", but this version of "
+           "Panda3D cannot produce .bam files older than 6.21.  Set "
+           "bam-version to 6 21 in Config.prc to suppress this error, or "
+           "leave it blank to write version " << _bam_major_ver << "."
+           << _bam_minor_ver << " files.\n";
+      _file_major = 6;
+      _file_minor = 21;
+      bam_version.set_string_value("6 21");
+
+    } else if (_file_major > _bam_major_ver || _file_minor > _bam_minor_ver) {
+      util_cat.error()
+        << "bam-version is set to " << bam_version << ", but this version of "
+           "Panda3D cannot produce .bam files newer than " << _bam_major_ver
+        << "." << _bam_minor_ver << ".  Set bam-version to a supported "
+           "version or leave it blank to write version " << _bam_major_ver
+        << "." << _bam_minor_ver << " files.\n";
+
+      _file_major = _bam_major_ver;
+      _file_minor = _bam_minor_ver;
+      bam_version.set_word(0, _bam_major_ver);
+      bam_version.set_word(1, _bam_minor_ver);
+    }
+  } else {
+    _file_major = _bam_major_ver;
+    _file_minor = _bam_minor_ver;
+  }
   _file_endian = bam_endian;
   _file_stdfloat_double = bam_stdfloat_double;
   _file_texture_mode = bam_texture_mode;
@@ -98,18 +133,24 @@ init() {
   _next_pta_id = 1;
   _long_pta_id = false;
 
-  _file_major = _bam_major_ver;
-  _file_minor = _bam_minor_ver;
+  nassertr_always(_file_major == _bam_major_ver, false);
+  nassertr_always(_file_minor <= _bam_minor_ver && _file_minor >= 21, false);
+
   _file_endian = bam_endian;
   _file_texture_mode = bam_texture_mode;
 
   // Write out the current major and minor BAM file version numbers.
   Datagram header;
 
-  header.add_uint16(_bam_major_ver);
-  header.add_uint16(_bam_minor_ver);
+  header.add_uint16(_file_major);
+  header.add_uint16(_file_minor);
   header.add_uint8(_file_endian);
-  header.add_bool(_file_stdfloat_double);
+
+  if (_file_major >= 6 || _file_minor >= 27) {
+    header.add_bool(_file_stdfloat_double);
+  } else {
+    _file_stdfloat_double = false;
+  }
 
   if (!_target->put_datagram(header)) {
     util_cat.error()

+ 1 - 0
panda/src/putil/bamWriter.h

@@ -76,6 +76,7 @@ PUBLISHED:
 
   INLINE int get_file_major_ver() const;
   INLINE int get_file_minor_ver() const;
+  INLINE void set_file_minor_ver(int minor_ver);
 
   INLINE BamEndian get_file_endian() const;
   INLINE bool get_file_stdfloat_double() const;

+ 6 - 0
panda/src/putil/config_util.cxx

@@ -51,6 +51,12 @@ ConfigureDef(config_util);
 NotifyCategoryDef(util, "");
 NotifyCategoryDef(bam, util_cat);
 
+ConfigVariableInt bam_version
+("bam-version", "",
+ PRC_DESC("Set this to specify which version .bam files to generate.  Each "
+          "Panda version only supports outputting a limited number of .bam "
+          "versions.  The default is to use the latest supported version."));
+
 ConfigVariableEnum<BamEnums::BamEndian> bam_endian
 ("bam-endian", BamEnums::BE_native,
  PRC_DESC("The default endianness to use for writing major numeric data "

+ 1 - 0
panda/src/putil/config_util.h

@@ -33,6 +33,7 @@ NotifyCategoryDecl(bam, EXPCL_PANDA_PUTIL, EXPTP_PANDA_PUTIL);
 // a global constant, we'll make it a member of MemoryUsage.  extern
 // EXPCL_PANDA_PUTIL const bool track_memory_usage;
 
+extern EXPCL_PANDA_PUTIL ConfigVariableInt bam_version;
 extern EXPCL_PANDA_PUTIL ConfigVariableEnum<BamEnums::BamEndian> bam_endian;
 extern EXPCL_PANDA_PUTIL ConfigVariableBool bam_stdfloat_double;
 extern EXPCL_PANDA_PUTIL ConfigVariableEnum<BamEnums::BamTextureMode> bam_texture_mode;