Browse Source

stf files

David Rose 15 years ago
parent
commit
71689ea198

+ 4 - 2
panda/src/configfiles/panda.prc.pp

@@ -133,9 +133,11 @@ egg-object-type-glow            <Scalar> blend { add }
 egg-object-type-keep-all-uvsets
 egg-object-type-keep-all-uvsets
 
 
 #if $[HAVE_SPEEDTREE]
 #if $[HAVE_SPEEDTREE]
-# If we have the SpeedTree library available, we'll want to use it
-# for loading compiled SpeedTree tree objects.
+# If we have the SpeedTree library available, we'll want to use it for
+# loading compiled SpeedTree tree objects, and SpeedTree forest
+# tables.
 load-file-type srt pandaspeedtree
 load-file-type srt pandaspeedtree
+load-file-type stf pandaspeedtree
 #endif
 #endif
 
 
 #end 20_panda.prc
 #end 20_panda.prc

+ 2 - 0
panda/src/speedtree/Sources.pp

@@ -16,6 +16,7 @@
   #define SOURCES \
   #define SOURCES \
     config_speedtree.h \
     config_speedtree.h \
     loaderFileTypeSrt.h \
     loaderFileTypeSrt.h \
+    loaderFileTypeStf.h \
     speedtree_api.h \
     speedtree_api.h \
     speedTreeNode.h \
     speedTreeNode.h \
     stTransform.h \
     stTransform.h \
@@ -27,6 +28,7 @@
   #define INCLUDED_SOURCES \
   #define INCLUDED_SOURCES \
     config_speedtree.cxx \
     config_speedtree.cxx \
     loaderFileTypeSrt.cxx \
     loaderFileTypeSrt.cxx \
+    loaderFileTypeStf.cxx \
     speedtree_api.cxx \
     speedtree_api.cxx \
     speedTreeNode.cxx \
     speedTreeNode.cxx \
     stTransform.cxx \
     stTransform.cxx \

+ 3 - 0
panda/src/speedtree/config_speedtree.cxx

@@ -16,6 +16,7 @@
 #include "speedTreeNode.h"
 #include "speedTreeNode.h"
 #include "stTree.h"
 #include "stTree.h"
 #include "loaderFileTypeSrt.h"
 #include "loaderFileTypeSrt.h"
+#include "loaderFileTypeStf.h"
 #include "loaderFileTypeRegistry.h"
 #include "loaderFileTypeRegistry.h"
 #include "dconfig.h"
 #include "dconfig.h"
 
 
@@ -80,9 +81,11 @@ init_libspeedtree() {
   SpeedTreeNode::init_type();
   SpeedTreeNode::init_type();
   STTree::init_type();
   STTree::init_type();
   LoaderFileTypeSrt::init_type();
   LoaderFileTypeSrt::init_type();
+  LoaderFileTypeStf::init_type();
 
 
   LoaderFileTypeRegistry *reg = LoaderFileTypeRegistry::get_global_ptr();
   LoaderFileTypeRegistry *reg = LoaderFileTypeRegistry::get_global_ptr();
   reg->register_type(new LoaderFileTypeSrt);
   reg->register_type(new LoaderFileTypeSrt);
+  reg->register_type(new LoaderFileTypeStf);
 }
 }
 
 
 // We need a SpeedTree custom allocator to integrate with Panda's
 // We need a SpeedTree custom allocator to integrate with Panda's

+ 79 - 0
panda/src/speedtree/loaderFileTypeStf.cxx

@@ -0,0 +1,79 @@
+// Filename: loaderFileTypeStf.cxx
+// Created by:  drose (06Oct10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#include "loaderFileTypeStf.h"
+#include "speedTreeNode.h"
+
+TypeHandle LoaderFileTypeStf::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: LoaderFileTypeStf::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+LoaderFileTypeStf::
+LoaderFileTypeStf() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LoaderFileTypeStf::get_name
+//       Access: Public, Virtual
+//  Description:
+////////////////////////////////////////////////////////////////////
+string LoaderFileTypeStf::
+get_name() const {
+  return "SpeedTree compiled tree";
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LoaderFileTypeStf::get_extension
+//       Access: Public, Virtual
+//  Description:
+////////////////////////////////////////////////////////////////////
+string LoaderFileTypeStf::
+get_extension() const {
+  return "stf";
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LoaderFileTypeStf::supports_compressed
+//       Access: Published, Virtual
+//  Description: Returns true if this file type can transparently load
+//               compressed files (with a .pz extension), false
+//               otherwise.
+////////////////////////////////////////////////////////////////////
+bool LoaderFileTypeStf::
+supports_compressed() const {
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LoaderFileTypeStf::load_file
+//       Access: Public, Virtual
+//  Description:
+////////////////////////////////////////////////////////////////////
+PT(PandaNode) LoaderFileTypeStf::
+load_file(const Filename &path, const LoaderOptions &options, 
+          BamCacheRecord *record) const {
+  if (!path.is_regular_file()) {
+    // Quietly fail if the file doesn't exist.  The Loader expects
+    // this.
+    return NULL;
+  }
+
+  PT(SpeedTreeNode) st = new SpeedTreeNode(path.get_basename());
+  st->add_from_stf(path, options);
+
+  return st.p();
+}

+ 58 - 0
panda/src/speedtree/loaderFileTypeStf.h

@@ -0,0 +1,58 @@
+// Filename: loaderFileTypeStf.h
+// Created by:  drose (07Oct10)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef LOADERFILETYPESTF_H
+#define LOADERFILETYPESTF_H
+
+#include "pandabase.h"
+
+#include "loaderFileType.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : LoaderFileTypeStf
+// Description : This defines the Loader interface to read SpeedTree
+//               STF files--a simple text file that describes a forest
+//               of trees (references to SRT files).
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDASPEEDTREE LoaderFileTypeStf : public LoaderFileType {
+public:
+  LoaderFileTypeStf();
+
+  virtual string get_name() const;
+  virtual string get_extension() const;
+  virtual bool supports_compressed() const;
+
+  virtual PT(PandaNode) load_file(const Filename &path, const LoaderOptions &options,
+                                  BamCacheRecord *record) const;
+
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    LoaderFileType::init_type();
+    register_type(_type_handle, "LoaderFileTypeStf",
+                  LoaderFileType::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#endif
+

+ 1 - 0
panda/src/speedtree/pandaspeedtree_composite1.cxx

@@ -1,5 +1,6 @@
 #include "config_speedtree.cxx"
 #include "config_speedtree.cxx"
 #include "loaderFileTypeSrt.cxx"
 #include "loaderFileTypeSrt.cxx"
+#include "loaderFileTypeStf.cxx"
 #include "speedTreeNode.cxx"
 #include "speedTreeNode.cxx"
 #include "speedtree_api.cxx"
 #include "speedtree_api.cxx"
 #include "stTransform.cxx"
 #include "stTransform.cxx"

+ 130 - 7
panda/src/speedtree/speedTreeNode.cxx

@@ -26,6 +26,8 @@
 #include "geomDrawCallbackData.h"
 #include "geomDrawCallbackData.h"
 #include "graphicsStateGuardian.h"
 #include "graphicsStateGuardian.h"
 #include "textureAttrib.h"
 #include "textureAttrib.h"
+#include "loader.h"
+#include "deg_2_rad.h"
 
 
 #ifdef SPEEDTREE_OPENGL
 #ifdef SPEEDTREE_OPENGL
 #include "glew/glew.h"
 #include "glew/glew.h"
@@ -271,6 +273,127 @@ add_instances(const NodePath &root, const TransformState *transform) {
 		  Thread::get_current_thread());
 		  Thread::get_current_thread());
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: SpeedTreeNode::add_from_stf
+//       Access: Published
+//  Description: Opens and reads the named STF (SpeedTree Forest)
+//               file, and adds the SRT files named within as
+//               instances of this node.  Returns true on success,
+//               false on failure.
+////////////////////////////////////////////////////////////////////
+bool SpeedTreeNode::
+add_from_stf(const Filename &pathname, const LoaderOptions &options) {
+  VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
+
+  Filename filename = Filename::text_filename(pathname);
+  PT(VirtualFile) file = vfs->get_file(filename);
+  if (file == (VirtualFile *)NULL) {
+    // No such file.
+    speedtree_cat.error()
+      << "Could not find " << pathname << "\n";
+    return false;
+  }
+
+  if (speedtree_cat.is_debug()) {
+    speedtree_cat.debug()
+      << "Reading STF file " << filename << "\n";
+  }
+
+  istream *in = file->open_read_file(true);
+  bool success = add_from_stf(*in, pathname, options);
+  vfs->close_read_file(in);
+
+  return success;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SpeedTreeNode::add_from_stf
+//       Access: Published
+//  Description: Reads text data from the indicated stream, which is
+//               understood to represent the named STF (SpeedTree
+//               Forest) file, and adds the SRT files named within as
+//               instances of this node.  Returns true on success,
+//               false on failure.
+//
+//               The pathname is used for reference only; if nonempty,
+//               it provides a search directory for named SRT files.
+//
+//               The Loader and LoaderOptions, if provided, are used
+//               to load the SRT files.  If the Loader pointer is
+//               NULL, the default global Loader is used instead.
+////////////////////////////////////////////////////////////////////
+bool SpeedTreeNode::
+add_from_stf(istream &in, const Filename &pathname, 
+	     const LoaderOptions &options, Loader *loader) {
+  if (loader == NULL) {
+    loader = Loader::get_global_ptr();
+  }
+  string os_filename;
+
+  Filename dirname = pathname.get_dirname();
+  dirname.make_absolute();
+  DSearchPath search;
+  search.append_directory(dirname);
+
+  typedef pmap<Filename, CPT(STTree) > AlreadyLoaded;
+  AlreadyLoaded already_loaded;
+
+  // The STF file format doesn't allow for spaces in the SRT filename.
+  in >> os_filename;
+  while (in && !in.eof()) {
+    CPT(STTree) tree;
+    Filename srt_filename = Filename::from_os_specific(os_filename);
+    AlreadyLoaded::iterator ai = already_loaded.find(srt_filename);
+    if (ai != already_loaded.end()) {
+      tree = (*ai).second;
+    } else {
+      // Resolve the SRT filename relative to the STF file first.
+      srt_filename.resolve_filename(search);
+
+      // Now load up the SRT file using the Panda loader (which will
+      // also search the model-path if necessary).
+      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 = srt_node->get_tree(0);
+	  }
+	}
+      }
+      already_loaded[srt_filename] = tree;
+    }
+
+    // Now we've loaded the SRT data, so apply it the appropriate
+    // number of times to the locations specified.
+    int num_instances;
+    in >> num_instances;
+    for (int ni = 0; ni < num_instances && in && !in.eof(); ++ni) {
+      LPoint3f pos;
+      float rotate, scale, elev_min, elev_max, slope_min, slope_max;
+      in >> pos[0] >> pos[1] >> pos[2] >> rotate >> scale >> elev_min >> elev_max >> slope_min >> slope_max;
+      if (tree != NULL) {
+	add_instance(tree, STTransform(pos, rad_2_deg(rotate), scale));
+      }
+    }
+    in >> os_filename;
+  }
+
+  if (!in.eof()) {
+    // If we didn't read all the way to end-of-file, there was an
+    // error.
+    speedtree_cat.error()
+      << "Syntax error in " << pathname << "\n";
+    return false;
+  }
+
+  // Return true if we successfully read all the way to end-of-file.
+  return true;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: SpeedTreeNode::authorize
 //     Function: SpeedTreeNode::authorize
 //       Access: Published, Static
 //       Access: Published, Static
@@ -419,13 +542,6 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
 	    SpeedTree::Mat4x4(projection_mat.get_data()),
 	    SpeedTree::Mat4x4(projection_mat.get_data()),
 	    SpeedTree::Mat4x4(modelview_mat.get_data()),
 	    SpeedTree::Mat4x4(modelview_mat.get_data()),
 	    lens->get_near(), lens->get_far());
 	    lens->get_near(), lens->get_far());
-  
-  if (!_forest.UploadViewShaderParameters(_view)) {
-    speedtree_cat.warning()
-      << "Couldn't set view parameters\n";
-    speedtree_cat.warning()
-      << SpeedTree::CCore::GetError() << "\n";
-  }
 
 
   if (!_needs_repopulate) {
   if (!_needs_repopulate) {
     // Don't bother culling now unless we're correctly fully
     // Don't bother culling now unless we're correctly fully
@@ -865,6 +981,13 @@ setup_for_render(GraphicsStateGuardian *gsg) {
 
 
     _needs_repopulate = false;
     _needs_repopulate = false;
   }
   }
+
+  if (!_forest.UploadViewShaderParameters(_view)) {
+    speedtree_cat.warning()
+      << "Couldn't set view parameters\n";
+    speedtree_cat.warning()
+      << SpeedTree::CCore::GetError() << "\n";
+  }
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 8 - 0
panda/src/speedtree/speedTreeNode.h

@@ -21,9 +21,12 @@
 #include "stTree.h"
 #include "stTree.h"
 #include "stTransform.h"
 #include "stTransform.h"
 #include "callbackObject.h"
 #include "callbackObject.h"
+#include "loaderOptions.h"
 
 
 #include "speedtree_api.h"
 #include "speedtree_api.h"
 
 
+class Loader;
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //       Class : SpeedTreeNode
 //       Class : SpeedTreeNode
 // Description : Interfaces with the SpeedTree library to render
 // Description : Interfaces with the SpeedTree library to render
@@ -87,6 +90,11 @@ PUBLISHED:
 
 
   void add_instance(const STTree *tree, const STTransform &transform);
   void add_instance(const STTree *tree, const STTransform &transform);
   void add_instances(const NodePath &root, const TransformState *transform = TransformState::make_identity());
   void add_instances(const NodePath &root, const TransformState *transform = TransformState::make_identity());
+  bool add_from_stf(const Filename &pathname, 
+		    const LoaderOptions &options = LoaderOptions());
+  bool add_from_stf(istream &in, const Filename &pathname, 
+		    const LoaderOptions &options = LoaderOptions(),
+		    Loader *loader = NULL);
 
 
   static bool authorize(const string &license = "");
   static bool authorize(const string &license = "");
 
 

+ 16 - 2
panda/src/testbed/Sources.pp

@@ -7,10 +7,10 @@
     framework putil collide pgraph chan text \
     framework putil collide pgraph chan text \
     pnmimage pnmimagetypes pnmtext event effects gobj display \
     pnmimage pnmimagetypes pnmtext event effects gobj display \
     mathutil putil express dgraph device tform \
     mathutil putil express dgraph device tform \
-    linmath pstatclient panda
+    linmath pstatclient panda pandaspeedtree
 
 
 #begin bin_target
 #begin bin_target
-  #define TARGET pview
+  #define TARGET pview1
 
 
   #define SOURCES \
   #define SOURCES \
     pview.cxx
     pview.cxx
@@ -38,3 +38,17 @@
   #define TARGET test_map
   #define TARGET test_map
   #define SOURCES test_map.cxx
   #define SOURCES test_map.cxx
 #end test_bin_target
 #end test_bin_target
+
+#begin test_bin_target
+  #define USE_PACKAGES gl
+  #define LOCAL_LIBS
+  #define TARGET gm
+  #define SOURCES gm.cxx
+#end test_bin_target
+
+#begin test_bin_target
+  #define USE_PACKAGES gl
+  #define LOCAL_LIBS
+  #define TARGET om
+  #define SOURCES om.cxx
+#end test_bin_target

+ 27 - 18
panda/src/testbed/pview.cxx

@@ -22,6 +22,8 @@
 #include "partGroup.h"
 #include "partGroup.h"
 #include "cardMaker.h"
 #include "cardMaker.h"
 #include "bamCache.h"
 #include "bamCache.h"
+#include "speedTreeNode.h"
+#include "randomizer.h"
 
 
 // By including checkPandaVersion.h, we guarantee that runtime
 // By including checkPandaVersion.h, we guarantee that runtime
 // attempts to run pview will fail if it inadvertently links with the
 // attempts to run pview will fail if it inadvertently links with the
@@ -147,27 +149,34 @@ event_0(const Event *event, void *) {
   WindowFramework *wf;
   WindowFramework *wf;
   DCAST_INTO_V(wf, param.get_ptr());
   DCAST_INTO_V(wf, param.get_ptr());
 
 
-  // Create a new offscreen buffer.
-  GraphicsOutput *win = wf->get_graphics_output();
-  PT(GraphicsOutput) buffer = win->make_texture_buffer("tex", 256, 256);
-  cerr << buffer->get_type() << "\n";
+  PT(SpeedTreeNode) st = new SpeedTreeNode("st");
+  Filename dirname("/c/Users/drose/Desktop/SpeedTree/SpeedTree SDK v5.1.1 Full/Bin/Forests/Huangshan");
+  vector_string basenames;
+  dirname.scan_directory(basenames);
 
 
-  // Set the offscreen buffer to render the same scene as the main camera.
-  DisplayRegion *dr = buffer->make_display_region();
-  dr->set_camera(NodePath(wf->get_camera(0)));
+  vector_string srts;
+  for (size_t bi = 0; bi < basenames.size(); ++bi) {
+    if (Filename(basenames[bi]).get_extension() == "srt") {
+      srts.push_back(basenames[bi]);
+    }
+  }
+  nassertv(!srts.empty());
+  
+  Randomizer random;
+  for (int xi = 0; xi < 20; ++xi) {
+    for (int yi = 0; yi < 20; ++yi) {
+      int ri = random.random_int(srts.size());
+      Filename filename(dirname, srts[ri]);
+      NodePath tree1 = wf->load_model(NodePath(), filename);
+      tree1.set_pos(xi * 50, yi * 50, 0);
+      st->add_instances(tree1);
+    }
+  }
 
 
-  // Make the clear color on the buffer be yellow, so it's obviously
-  // different from the main scene's background color.
-  buffer->set_clear_color(Colorf(1, 1, 0, 0));
+  NodePath stnp = framework.get_models().attach_new_node(st);
 
 
-  // Apply the offscreen buffer's texture to a card in the main
-  // window.
-  CardMaker cm("card");
-  cm.set_frame(0, 1, 0, 1);
-  NodePath card_np(cm.generate());
-  
-  card_np.reparent_to(wf->get_render_2d());
-  card_np.set_texture(buffer->get_texture());
+  NodePath axis = wf->load_model(framework.get_models(), "zup-axis.bam");
+  wf->center_trackball(axis);
 }
 }
 
 
 void 
 void