From 71689ea198a6fd8686c8f225a0793233682aa9d3 Mon Sep 17 00:00:00 2001 From: David Rose Date: Fri, 8 Oct 2010 00:27:49 +0000 Subject: [PATCH] stf files --- panda/src/configfiles/panda.prc.pp | 6 +- panda/src/speedtree/Sources.pp | 2 + panda/src/speedtree/config_speedtree.cxx | 3 + panda/src/speedtree/loaderFileTypeStf.cxx | 79 ++++++++++ panda/src/speedtree/loaderFileTypeStf.h | 58 ++++++++ .../speedtree/pandaspeedtree_composite1.cxx | 1 + panda/src/speedtree/speedTreeNode.cxx | 137 +++++++++++++++++- panda/src/speedtree/speedTreeNode.h | 8 + panda/src/testbed/Sources.pp | 18 ++- panda/src/testbed/pview.cxx | 47 +++--- 10 files changed, 329 insertions(+), 30 deletions(-) create mode 100755 panda/src/speedtree/loaderFileTypeStf.cxx create mode 100755 panda/src/speedtree/loaderFileTypeStf.h diff --git a/panda/src/configfiles/panda.prc.pp b/panda/src/configfiles/panda.prc.pp index 9e2b650e02..1a844c3948 100644 --- a/panda/src/configfiles/panda.prc.pp +++ b/panda/src/configfiles/panda.prc.pp @@ -133,9 +133,11 @@ egg-object-type-glow blend { add } egg-object-type-keep-all-uvsets #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 stf pandaspeedtree #endif #end 20_panda.prc diff --git a/panda/src/speedtree/Sources.pp b/panda/src/speedtree/Sources.pp index 272c953fcc..3b6613c414 100644 --- a/panda/src/speedtree/Sources.pp +++ b/panda/src/speedtree/Sources.pp @@ -16,6 +16,7 @@ #define SOURCES \ config_speedtree.h \ loaderFileTypeSrt.h \ + loaderFileTypeStf.h \ speedtree_api.h \ speedTreeNode.h \ stTransform.h \ @@ -27,6 +28,7 @@ #define INCLUDED_SOURCES \ config_speedtree.cxx \ loaderFileTypeSrt.cxx \ + loaderFileTypeStf.cxx \ speedtree_api.cxx \ speedTreeNode.cxx \ stTransform.cxx \ diff --git a/panda/src/speedtree/config_speedtree.cxx b/panda/src/speedtree/config_speedtree.cxx index 64185ba6b0..8ff124d613 100644 --- a/panda/src/speedtree/config_speedtree.cxx +++ b/panda/src/speedtree/config_speedtree.cxx @@ -16,6 +16,7 @@ #include "speedTreeNode.h" #include "stTree.h" #include "loaderFileTypeSrt.h" +#include "loaderFileTypeStf.h" #include "loaderFileTypeRegistry.h" #include "dconfig.h" @@ -80,9 +81,11 @@ init_libspeedtree() { SpeedTreeNode::init_type(); STTree::init_type(); LoaderFileTypeSrt::init_type(); + LoaderFileTypeStf::init_type(); LoaderFileTypeRegistry *reg = LoaderFileTypeRegistry::get_global_ptr(); reg->register_type(new LoaderFileTypeSrt); + reg->register_type(new LoaderFileTypeStf); } // We need a SpeedTree custom allocator to integrate with Panda's diff --git a/panda/src/speedtree/loaderFileTypeStf.cxx b/panda/src/speedtree/loaderFileTypeStf.cxx new file mode 100755 index 0000000000..948de63b31 --- /dev/null +++ b/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(); +} diff --git a/panda/src/speedtree/loaderFileTypeStf.h b/panda/src/speedtree/loaderFileTypeStf.h new file mode 100755 index 0000000000..0b63d99687 --- /dev/null +++ b/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 + diff --git a/panda/src/speedtree/pandaspeedtree_composite1.cxx b/panda/src/speedtree/pandaspeedtree_composite1.cxx index 710b1e201b..9aa1d92ab0 100644 --- a/panda/src/speedtree/pandaspeedtree_composite1.cxx +++ b/panda/src/speedtree/pandaspeedtree_composite1.cxx @@ -1,5 +1,6 @@ #include "config_speedtree.cxx" #include "loaderFileTypeSrt.cxx" +#include "loaderFileTypeStf.cxx" #include "speedTreeNode.cxx" #include "speedtree_api.cxx" #include "stTransform.cxx" diff --git a/panda/src/speedtree/speedTreeNode.cxx b/panda/src/speedtree/speedTreeNode.cxx index 45a5f53a0e..e429996944 100644 --- a/panda/src/speedtree/speedTreeNode.cxx +++ b/panda/src/speedtree/speedTreeNode.cxx @@ -26,6 +26,8 @@ #include "geomDrawCallbackData.h" #include "graphicsStateGuardian.h" #include "textureAttrib.h" +#include "loader.h" +#include "deg_2_rad.h" #ifdef SPEEDTREE_OPENGL #include "glew/glew.h" @@ -271,6 +273,127 @@ add_instances(const NodePath &root, const TransformState *transform) { 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 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 // Access: Published, Static @@ -419,13 +542,6 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) { SpeedTree::Mat4x4(projection_mat.get_data()), SpeedTree::Mat4x4(modelview_mat.get_data()), 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) { // Don't bother culling now unless we're correctly fully @@ -865,6 +981,13 @@ setup_for_render(GraphicsStateGuardian *gsg) { _needs_repopulate = false; } + + if (!_forest.UploadViewShaderParameters(_view)) { + speedtree_cat.warning() + << "Couldn't set view parameters\n"; + speedtree_cat.warning() + << SpeedTree::CCore::GetError() << "\n"; + } } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/speedtree/speedTreeNode.h b/panda/src/speedtree/speedTreeNode.h index ccfc9679ff..3b5c0f7394 100644 --- a/panda/src/speedtree/speedTreeNode.h +++ b/panda/src/speedtree/speedTreeNode.h @@ -21,9 +21,12 @@ #include "stTree.h" #include "stTransform.h" #include "callbackObject.h" +#include "loaderOptions.h" #include "speedtree_api.h" +class Loader; + //////////////////////////////////////////////////////////////////// // Class : SpeedTreeNode // Description : Interfaces with the SpeedTree library to render @@ -87,6 +90,11 @@ PUBLISHED: void add_instance(const STTree *tree, const STTransform &transform); 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 = ""); diff --git a/panda/src/testbed/Sources.pp b/panda/src/testbed/Sources.pp index 72a8673b27..f46b3decd9 100644 --- a/panda/src/testbed/Sources.pp +++ b/panda/src/testbed/Sources.pp @@ -7,10 +7,10 @@ framework putil collide pgraph chan text \ pnmimage pnmimagetypes pnmtext event effects gobj display \ mathutil putil express dgraph device tform \ - linmath pstatclient panda + linmath pstatclient panda pandaspeedtree #begin bin_target - #define TARGET pview + #define TARGET pview1 #define SOURCES \ pview.cxx @@ -38,3 +38,17 @@ #define TARGET test_map #define SOURCES test_map.cxx #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 diff --git a/panda/src/testbed/pview.cxx b/panda/src/testbed/pview.cxx index 7cc865f941..53cf54e7d6 100644 --- a/panda/src/testbed/pview.cxx +++ b/panda/src/testbed/pview.cxx @@ -22,6 +22,8 @@ #include "partGroup.h" #include "cardMaker.h" #include "bamCache.h" +#include "speedTreeNode.h" +#include "randomizer.h" // By including checkPandaVersion.h, we guarantee that runtime // attempts to run pview will fail if it inadvertently links with the @@ -147,27 +149,34 @@ event_0(const Event *event, void *) { WindowFramework *wf; 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))); - - // 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)); - - // 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()); + 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()); - card_np.reparent_to(wf->get_render_2d()); - card_np.set_texture(buffer->get_texture()); + 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); + } + } + + NodePath stnp = framework.get_models().attach_new_node(st); + + NodePath axis = wf->load_model(framework.get_models(), "zup-axis.bam"); + wf->center_trackball(axis); } void