diff --git a/panda/src/speedtree/config_speedtree.cxx b/panda/src/speedtree/config_speedtree.cxx index c9afae51e6..94da5ff245 100644 --- a/panda/src/speedtree/config_speedtree.cxx +++ b/panda/src/speedtree/config_speedtree.cxx @@ -246,6 +246,8 @@ init_libspeedtree() { LoaderFileTypeSrt::init_type(); LoaderFileTypeStf::init_type(); + SpeedTreeNode::register_with_read_factory(); + LoaderFileTypeRegistry *reg = LoaderFileTypeRegistry::get_global_ptr(); reg->register_type(new LoaderFileTypeSrt); reg->register_type(new LoaderFileTypeStf); diff --git a/panda/src/speedtree/speedTreeNode.cxx b/panda/src/speedtree/speedTreeNode.cxx index 72b2f6d50d..31707a1e8c 100644 --- a/panda/src/speedtree/speedTreeNode.cxx +++ b/panda/src/speedtree/speedTreeNode.cxx @@ -704,6 +704,7 @@ SpeedTreeNode(const SpeedTreeNode ©) : _trees.push_back(new InstanceList(*instance_list)); } + _trees.sort(); _needs_repopulate = true; mark_internal_bounds_stale(); @@ -716,6 +717,7 @@ SpeedTreeNode(const SpeedTreeNode ©) : //////////////////////////////////////////////////////////////////// SpeedTreeNode:: ~SpeedTreeNode() { + remove_all_trees(); // Help reduce memory waste from ST_DELETE_FOREST_HACK. _forest_render.ClearInstances(); } @@ -1497,6 +1499,14 @@ register_with_read_factory() { void SpeedTreeNode:: write_datagram(BamWriter *manager, Datagram &dg) { PandaNode::write_datagram(manager, dg); + + int num_trees = _trees.size(); + dg.add_uint32(num_trees); + Trees::const_iterator ti; + for (ti = _trees.begin(); ti != _trees.end(); ++ti) { + InstanceList *instance_list = (*ti); + instance_list->write_datagram(manager, dg); + } } //////////////////////////////////////////////////////////////////// @@ -1529,6 +1539,21 @@ make_from_bam(const FactoryParams ¶ms) { void SpeedTreeNode:: fillin(DatagramIterator &scan, BamReader *manager) { PandaNode::fillin(scan, manager); + + int num_trees = scan.get_uint32(); + _trees.reserve(num_trees); + for (int i = 0; i < num_trees; i++) { + InstanceList *instance_list = new InstanceList(NULL); + instance_list->fillin(scan, manager); + if (instance_list->get_tree() == (STTree *)NULL) { + // The tree wasn't successfully loaded. Don't keep it. + delete instance_list; + } else { + _trees.push_back(instance_list); + } + } + + _trees.sort(); } //////////////////////////////////////////////////////////////////// @@ -1557,6 +1582,76 @@ write(ostream &out, int indent_level) const { } } +//////////////////////////////////////////////////////////////////// +// Function: SpeedTreeNode::InstanceList::write_datagram +// Access: Public +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void SpeedTreeNode::InstanceList:: +write_datagram(BamWriter *manager, Datagram &dg) { + // Compute the relative pathname to the SRT file. + VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); + + bool has_bam_dir = !manager->get_filename().empty(); + Filename bam_dir = manager->get_filename().get_dirname(); + Filename srt_filename = _tree->get_fullpath(); + + bam_dir.make_absolute(vfs->get_cwd()); + if (!has_bam_dir || !srt_filename.make_relative_to(bam_dir, true)) { + srt_filename.find_on_searchpath(get_model_path()); + } + + dg.add_string(srt_filename); + + // Now record the instances. + int num_instances = _instances.size(); + dg.add_uint32(num_instances); + STInstances::const_iterator ii; + for (ii = _instances.begin(); ii != _instances.end(); ++ii) { + STTransform transform = (*ii); + transform.write_datagram(manager, dg); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: SpeedTreeNode::InstanceList::fillin +// Access: Public +// Description: This internal function is called by make_from_bam to +// read in all of the relevant data from the BamFile for +// the new SpeedTreeNode. +//////////////////////////////////////////////////////////////////// +void SpeedTreeNode::InstanceList:: +fillin(DatagramIterator &scan, BamReader *manager) { + // Get the relative pathname to the SRT file. + string srt_filename = scan.get_string(); + + // Now load up the SRT file using the Panda loader (which will + // also search the model-path if necessary). + Loader *loader = Loader::get_global_ptr(); + PT(PandaNode) srt_root = loader->load_sync(srt_filename); + + if (srt_root != NULL) { + NodePath srt(srt_root); + NodePath srt_np = srt.find("**/+SpeedTreeNode"); + if (!srt_np.is_empty()) { + SpeedTreeNode *srt_node = DCAST(SpeedTreeNode, srt_np.node()); + if (srt_node->get_num_trees() >= 1) { + _tree = (STTree *)srt_node->get_tree(0); + } + } + } + + // Now read the instances. + int num_instances = scan.get_uint32(); + _instances.reserve(num_instances); + for (int i = 0; i < num_instances; i++) { + STTransform transform; + transform.fillin(scan, manager); + _instances.push_back(transform); + } +} + //////////////////////////////////////////////////////////////////// // Function: SpeedTreeNode::DrawCallback::do_callback // Access: Public, Virtual diff --git a/panda/src/speedtree/speedTreeNode.h b/panda/src/speedtree/speedTreeNode.h index 017db2cec6..dbb4f8da63 100644 --- a/panda/src/speedtree/speedTreeNode.h +++ b/panda/src/speedtree/speedTreeNode.h @@ -77,6 +77,10 @@ PUBLISHED: void output(ostream &out) const; void write(ostream &out, int indent_level = 0) const; + public: + void write_datagram(BamWriter *manager, Datagram &dg); + void fillin(DatagramIterator &scan, BamReader *manager); + private: PT(STTree) _tree; STInstances _instances; diff --git a/panda/src/speedtree/stTransform.cxx b/panda/src/speedtree/stTransform.cxx index d5564a2a8a..56464a8e33 100644 --- a/panda/src/speedtree/stTransform.cxx +++ b/panda/src/speedtree/stTransform.cxx @@ -52,3 +52,30 @@ void STTransform:: output(ostream &out) const { out << "STTransform(" << _pos << ", " << _rotate << ", " << _scale << ")"; } + +//////////////////////////////////////////////////////////////////// +// Function: STTransform::write_datagram +// Access: Public +// Description: Writes the contents of this object to the datagram +// for shipping out to a Bam file. +//////////////////////////////////////////////////////////////////// +void STTransform:: +write_datagram(BamWriter *manager, Datagram &dg) { + _pos.write_datagram(dg); + dg.add_float32(_rotate); + dg.add_float32(_scale); +} + +//////////////////////////////////////////////////////////////////// +// Function: STTransform::fillin +// Access: Public +// Description: This internal function is called by make_from_bam to +// read in all of the relevant data from the BamFile for +// the new SpeedTreeNode. +//////////////////////////////////////////////////////////////////// +void STTransform:: +fillin(DatagramIterator &scan, BamReader *manager) { + _pos.read_datagram(scan); + _rotate = scan.get_float32(); + _scale = scan.get_float32(); +} diff --git a/panda/src/speedtree/stTransform.h b/panda/src/speedtree/stTransform.h index 72e8373c5a..a5c06901fc 100644 --- a/panda/src/speedtree/stTransform.h +++ b/panda/src/speedtree/stTransform.h @@ -55,6 +55,10 @@ PUBLISHED: void output(ostream &out) const; +public: + void write_datagram(BamWriter *manager, Datagram &dg); + void fillin(DatagramIterator &scan, BamReader *manager); + private: LPoint3f _pos; float _rotate;