stf files

This commit is contained in:
David Rose 2010-10-08 00:27:49 +00:00
parent 48c6a8756a
commit 71689ea198
10 changed files with 329 additions and 30 deletions

View File

@ -133,9 +133,11 @@ egg-object-type-glow <Scalar> 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

View File

@ -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 \

View File

@ -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

View File

@ -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();
}

View File

@ -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

View File

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

View File

@ -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<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
// 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";
}
}
////////////////////////////////////////////////////////////////////

View File

@ -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 = "");

View File

@ -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

View File

@ -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