steps toward async flatten

This commit is contained in:
David Rose 2007-04-03 23:21:49 +00:00
parent 301e051f35
commit 9b575fbe58
30 changed files with 392 additions and 96 deletions

View File

@ -146,15 +146,27 @@ get_root_xform() const {
return cdata->_root_xform; return cdata->_root_xform;
} }
////////////////////////////////////////////////////////////////////
// Function: PartBundle::get_num_nodes
// Access: Published
// Description: Returns the number of PartBundleNodes that contain a
// pointer to this PartBundle.
////////////////////////////////////////////////////////////////////
INLINE int PartBundle::
get_num_nodes() const {
return _nodes.size();
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: PartBundle::get_node // Function: PartBundle::get_node
// Access: Published // Access: Published
// Description: Returns the PartBundleNode associated with this // Description: Returns the nth PartBundleNode associated with
// PartBundle. // this PartBundle.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE PartBundleNode *PartBundle:: INLINE PartBundleNode *PartBundle::
get_node() const { get_node(int n) const {
return _node; nassertr(n >= 0 && n < (int)_nodes.size(), NULL);
return _nodes[n];
} }

View File

@ -30,6 +30,8 @@
#include "bamWriter.h" #include "bamWriter.h"
#include "configVariableEnum.h" #include "configVariableEnum.h"
#include <algorithm>
TypeHandle PartBundle::_type_handle; TypeHandle PartBundle::_type_handle;
@ -64,8 +66,7 @@ PartBundle(const PartBundle &copy) :
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
PartBundle:: PartBundle::
PartBundle(const string &name) : PartBundle(const string &name) :
PartGroup(name), PartGroup(name)
_node(NULL)
{ {
} }
@ -319,16 +320,33 @@ control_activated(AnimControl *control) {
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: PartBundle::set_node // Function: PartBundle::add_node
// Access: Protected, Virtual // Access: Protected, Virtual
// Description: Changes the PartBundleNode pointer associated with // Description: Adds the PartBundleNode pointer to the set of nodes
// the PartBundle. Normally called only by the // associated with the PartBundle. Normally called only
// PartBundleNode itself, for instance when the bundle // by the PartBundleNode itself, for instance when the
// is flattened with another node. // bundle is flattened with another node.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void PartBundle:: void PartBundle::
set_node(PartBundleNode *node) { add_node(PartBundleNode *node) {
_node = node; nassertv(find(_nodes.begin(), _nodes.end(), node) == _nodes.end());
_nodes.push_back(node);
}
////////////////////////////////////////////////////////////////////
// Function: PartBundle::remove_node
// Access: Protected, Virtual
// Description: Removes the PartBundleNode pointer from the set of
// nodes associated with the PartBundle. Normally
// called only by the PartBundleNode itself, for
// instance when the bundle is flattened with another
// node.
////////////////////////////////////////////////////////////////////
void PartBundle::
remove_node(PartBundleNode *node) {
Nodes::iterator ni = find(_nodes.begin(), _nodes.end(), node);
nassertv(ni != _nodes.end());
_nodes.erase(ni);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////

View File

@ -31,6 +31,7 @@
#include "cycleDataReader.h" #include "cycleDataReader.h"
#include "cycleDataWriter.h" #include "cycleDataWriter.h"
#include "luse.h" #include "luse.h"
#include "pvector.h"
class AnimBundle; class AnimBundle;
class PartBundleNode; class PartBundleNode;
@ -105,7 +106,8 @@ PUBLISHED:
INLINE void xform(const LMatrix4f &mat); INLINE void xform(const LMatrix4f &mat);
INLINE const LMatrix4f &get_root_xform() const; INLINE const LMatrix4f &get_root_xform() const;
INLINE PartBundleNode *get_node() const; INLINE int get_num_nodes() const;
INLINE PartBundleNode *get_node(int n) const;
void clear_control_effects(); void clear_control_effects();
INLINE void set_control_effect(AnimControl *control, float effect); INLINE void set_control_effect(AnimControl *control, float effect);
@ -128,7 +130,8 @@ public:
virtual void control_activated(AnimControl *control); virtual void control_activated(AnimControl *control);
protected: protected:
virtual void set_node(PartBundleNode *node); virtual void add_node(PartBundleNode *node);
virtual void remove_node(PartBundleNode *node);
private: private:
class CData; class CData;
@ -138,7 +141,8 @@ private:
void recompute_net_blend(CData *cdata); void recompute_net_blend(CData *cdata);
void clear_and_stop_intersecting(AnimControl *control, CData *cdata); void clear_and_stop_intersecting(AnimControl *control, CData *cdata);
PartBundleNode *_node; typedef pvector<PartBundleNode *> Nodes;
Nodes _nodes;
// This is the data that must be cycled between pipeline stages. // This is the data that must be cycled between pipeline stages.
class CData : public CycleData { class CData : public CycleData {

View File

@ -33,23 +33,29 @@ PartBundleNode::
~PartBundleNode() { ~PartBundleNode() {
Bundles::iterator bi; Bundles::iterator bi;
for (bi = _bundles.begin(); bi != _bundles.end(); ++bi) { for (bi = _bundles.begin(); bi != _bundles.end(); ++bi) {
nassertv((*bi)->_node == this); (*bi)->remove_node(this);
(*bi)->_node = NULL;
} }
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: PartBundleNode::safe_to_flatten // Function: PartBundleNode::safe_to_transform
// Access: Public, Virtual // Access: Public, Virtual
// Description: Returns true if it is generally safe to flatten out // Description: Returns true if it is generally safe to transform
// this particular kind of Node by duplicating // this particular kind of PandaNode by calling the
// instances, false otherwise (for instance, a Camera // xform() method, false otherwise.
// cannot be safely flattened, because the Camera
// pointer itself is meaningful).
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
bool PartBundleNode:: bool PartBundleNode::
safe_to_flatten() const { safe_to_transform() const {
return false; // If any of our bundles appear on multiple nodes, we can't
// transform any of them without transforming all of them at once.
Bundles::const_iterator bi;
for (bi = _bundles.begin(); bi != _bundles.end(); ++bi) {
if ((*bi)->get_num_nodes() > 1) {
return false;
}
}
return true;
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -61,6 +67,11 @@ safe_to_flatten() const {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void PartBundleNode:: void PartBundleNode::
xform(const LMatrix4f &mat) { xform(const LMatrix4f &mat) {
if (mat.almost_equal(LMatrix4f::ident_mat())) {
// Don't bother.
return;
}
Bundles::iterator bi; Bundles::iterator bi;
for (bi = _bundles.begin(); bi != _bundles.end(); ++bi) { for (bi = _bundles.begin(); bi != _bundles.end(); ++bi) {
(*bi)->xform(mat); (*bi)->xform(mat);
@ -74,9 +85,8 @@ xform(const LMatrix4f &mat) {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void PartBundleNode:: void PartBundleNode::
add_bundle(PartBundle *bundle) { add_bundle(PartBundle *bundle) {
nassertv(bundle->_node == NULL);
_bundles.push_back(bundle); _bundles.push_back(bundle);
bundle->set_node(this); bundle->add_node(this);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -91,7 +101,8 @@ steal_bundles(PartBundleNode *other) {
for (bi = other->_bundles.begin(); bi != other->_bundles.end(); ++bi) { for (bi = other->_bundles.begin(); bi != other->_bundles.end(); ++bi) {
PartBundle *bundle = (*bi); PartBundle *bundle = (*bi);
_bundles.push_back(bundle); _bundles.push_back(bundle);
bundle->set_node(this); bundle->remove_node(other);
bundle->add_node(this);
} }
other->_bundles.clear(); other->_bundles.clear();
} }
@ -127,7 +138,7 @@ complete_pointers(TypedWritable **p_list, BamReader* manager) {
Bundles::iterator bi; Bundles::iterator bi;
for (bi = _bundles.begin(); bi != _bundles.end(); ++bi) { for (bi = _bundles.begin(); bi != _bundles.end(); ++bi) {
(*bi) = DCAST(PartBundle, p_list[pi++]); (*bi) = DCAST(PartBundle, p_list[pi++]);
(*bi)->_node = this; (*bi)->add_node(this);
} }
return pi; return pi;

View File

@ -43,7 +43,7 @@ protected:
public: public:
virtual ~PartBundleNode(); virtual ~PartBundleNode();
virtual bool safe_to_flatten() const; virtual bool safe_to_transform() const;
virtual void xform(const LMatrix4f &mat); virtual void xform(const LMatrix4f &mat);
PUBLISHED: PUBLISHED:

View File

@ -40,25 +40,29 @@ PStatCollector Character::_animation_pcollector("*:Animation");
// Description: Use make_copy() or copy_subgraph() to copy a Character. // Description: Use make_copy() or copy_subgraph() to copy a Character.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
Character:: Character::
Character(const Character &copy) : Character(const Character &copy, bool copy_bundles) :
PartBundleNode(copy), PartBundleNode(copy),
_joints_pcollector(copy._joints_pcollector), _joints_pcollector(copy._joints_pcollector),
_skinning_pcollector(copy._skinning_pcollector) _skinning_pcollector(copy._skinning_pcollector)
{ {
set_cull_callback(); set_cull_callback();
// Copy the bundle(s). if (copy_bundles) {
int num_bundles = copy.get_num_bundles(); // Copy the bundle(s).
for (int i = 0; i < num_bundles; ++i) { int num_bundles = copy.get_num_bundles();
PartBundle *orig_bundle = copy.get_bundle(i); for (int i = 0; i < num_bundles; ++i) {
PartBundle *new_bundle = PartBundle *orig_bundle = copy.get_bundle(i);
new CharacterJointBundle(orig_bundle->get_name()); PT(PartBundle) new_bundle = DCAST(PartBundle, orig_bundle->copy_subgraph());
add_bundle(new_bundle); add_bundle(new_bundle);
}
// Make a copy of the joint/slider hierarchy. } else {
copy_joints(new_bundle, orig_bundle); // Share the bundles.
} int num_bundles = copy.get_num_bundles();
for (int i = 0; i < num_bundles; ++i) {
PartBundle *orig_bundle = copy.get_bundle(i);
add_bundle(orig_bundle);
}
}
_last_auto_update = -1.0; _last_auto_update = -1.0;
} }
@ -102,7 +106,22 @@ Character::
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
PandaNode *Character:: PandaNode *Character::
make_copy() const { make_copy() const {
return new Character(*this); return new Character(*this, true);
}
////////////////////////////////////////////////////////////////////
// Function: Character::dupe_for_flatten
// Access: Public, Virtual
// Description: This is similar to make_copy(), but it makes a copy
// for the specific purpose of flatten. Typically, this
// will be a new PandaNode with a new pointer, but all
// of the internal data will always be shared with the
// original; whereas the new node returned by
// make_copy() might not share the internal data.
////////////////////////////////////////////////////////////////////
PandaNode *Character::
dupe_for_flatten() const {
return new Character(*this, false);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -352,31 +371,6 @@ do_update() {
} }
} }
////////////////////////////////////////////////////////////////////
// Function: Character::copy_joints
// Access: Private
// Description: Recursively walks the joint/slider hierarchy and
// creates a new copy of the hierarchy.
////////////////////////////////////////////////////////////////////
void Character::
copy_joints(PartGroup *copy, PartGroup *orig) {
if (copy->get_type() != orig->get_type()) {
char_cat.warning()
<< "Don't know how to copy " << orig->get_type() << "\n";
}
PartGroup::Children::const_iterator ci;
for (ci = orig->_children.begin(); ci != orig->_children.end(); ++ci) {
PartGroup *orig_child = (*ci);
PartGroup *copy_child = orig_child->make_copy();
if (copy_child->is_of_type(CharacterJoint::get_class_type())) {
DCAST(CharacterJoint, copy_child)->set_character(this);
}
copy->_children.push_back(copy_child);
copy_joints(copy_child, orig_child);
}
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: Character::r_copy_children // Function: Character::r_copy_children
// Access: Protected, Virtual // Access: Protected, Virtual

View File

@ -44,13 +44,14 @@ class ComputedVertices;
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
class EXPCL_PANDA Character : public PartBundleNode { class EXPCL_PANDA Character : public PartBundleNode {
protected: protected:
Character(const Character &copy); Character(const Character &copy, bool copy_bundles);
public: public:
Character(const string &name); Character(const string &name);
virtual ~Character(); virtual ~Character();
virtual PandaNode *make_copy() const; virtual PandaNode *make_copy() const;
virtual PandaNode *dupe_for_flatten() const;
virtual PandaNode *combine_with(PandaNode *other); virtual PandaNode *combine_with(PandaNode *other);
virtual bool cull_callback(CullTraverser *trav, CullTraverserData &data); virtual bool cull_callback(CullTraverser *trav, CullTraverserData &data);
@ -76,7 +77,6 @@ PUBLISHED:
private: private:
void do_update(); void do_update();
void copy_joints(PartGroup *copy, PartGroup *orig);
typedef pmap<const PandaNode *, PandaNode *> NodeMap; typedef pmap<const PandaNode *, PandaNode *> NodeMap;
typedef pmap<const PartGroup *, PartGroup *> JointMap; typedef pmap<const PartGroup *, PartGroup *> JointMap;

View File

@ -37,10 +37,10 @@ CharacterJointBundle(const CharacterJointBundle &copy) :
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: CharacterJointBundle::get_node // Function: CharacterJointBundle::get_node
// Access: Public // Access: Public
// Description: Returns the Character node associated with this // Description: Returns the nth Character associated with
// PartBundle. // this PartBundle.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE Character *CharacterJointBundle:: INLINE Character *CharacterJointBundle::
get_node() const { get_node(int n) const {
return DCAST(Character, PartBundle::get_node()); return DCAST(Character, PartBundle::get_node(n));
} }

View File

@ -45,22 +45,42 @@ make_copy() const {
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: CharacterJointBundle::set_node // Function: CharacterJointBundle::add_node
// Access: Protected, Virtual // Access: Protected, Virtual
// Description: Changes the PartBundleNode pointer associated with // Description: Adds the PartBundleNode pointer to the set of nodes
// the PartBundle. Normally called only by the // associated with the PartBundle. Normally called only
// PartBundleNode itself, for instance when the bundle // by the PartBundleNode itself, for instance when the
// is flattened with another node. // bundle is flattened with another node.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void CharacterJointBundle:: void CharacterJointBundle::
set_node(PartBundleNode *node) { add_node(PartBundleNode *node) {
PartBundle::set_node(node); PartBundle::add_node(node);
if (node->is_of_type(Character::get_class_type())) { if (node->is_of_type(Character::get_class_type())) {
Character *character = DCAST(Character, node); Character *character = DCAST(Character, node);
r_set_character(this, character); r_set_character(this, character);
} }
} }
////////////////////////////////////////////////////////////////////
// Function: CharacterJointBundle::remove_node
// Access: Protected, Virtual
// Description: Removes the PartBundleNode pointer from the set of
// nodes associated with the PartBundle. Normally
// called only by the PartBundleNode itself, for
// instance when the bundle is flattened with another
// node.
////////////////////////////////////////////////////////////////////
void CharacterJointBundle::
remove_node(PartBundleNode *node) {
PartBundle::remove_node(node);
// If there is still a Character on the list, assign that one to all
// of the joints.
if (get_num_nodes() > 0) {
r_set_character(this, get_node(get_num_nodes() - 1));
}
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: CharacterJointBundle::r_set_character // Function: CharacterJointBundle::r_set_character
// Access: Private // Access: Private

View File

@ -40,11 +40,12 @@ public:
CharacterJointBundle(const string &name = ""); CharacterJointBundle(const string &name = "");
PUBLISHED: PUBLISHED:
INLINE Character *get_node() const; INLINE Character *get_node(int n) const;
protected: protected:
virtual PartGroup *make_copy() const; virtual PartGroup *make_copy() const;
virtual void set_node(PartBundleNode *node); virtual void add_node(PartBundleNode *node);
virtual void remove_node(PartBundleNode *node);
private: private:
void r_set_character(PartGroup *group, Character *character); void r_set_character(PartGroup *group, Character *character);

View File

@ -315,7 +315,7 @@ add_render_texture(Texture *tex, RenderTextureMode mode,
tex->set_x_size(Texture::up_to_power_2(get_x_size())); tex->set_x_size(Texture::up_to_power_2(get_x_size()));
tex->set_y_size(Texture::up_to_power_2(get_y_size())); tex->set_y_size(Texture::up_to_power_2(get_y_size()));
if ((mode == RTM_bind_or_copy)&&(support_render_texture==0)) { if (mode == RTM_bind_or_copy && !support_render_texture) {
mode = RTM_copy_texture; mode = RTM_copy_texture;
} }
else { else {

View File

@ -1043,7 +1043,7 @@ make_camera() {
PT(Lens) lens = new PerspectiveLens; PT(Lens) lens = new PerspectiveLens;
if (aspect_ratio != 0.0f) { if (aspect_ratio != 0.0) {
// If we're given an explict aspect ratio, use it // If we're given an explict aspect ratio, use it
lens->set_aspect_ratio(aspect_ratio); lens->set_aspect_ratio(aspect_ratio);

View File

@ -69,6 +69,7 @@
lodNode.I lodNode.h \ lodNode.I lodNode.h \
materialAttrib.I materialAttrib.h \ materialAttrib.I materialAttrib.h \
materialCollection.I materialCollection.h \ materialCollection.I materialCollection.h \
modelFlattenRequest.I modelFlattenRequest.h \
modelLoadRequest.I modelLoadRequest.h \ modelLoadRequest.I modelLoadRequest.h \
modelNode.I modelNode.h \ modelNode.I modelNode.h \
modelPool.I modelPool.h \ modelPool.I modelPool.h \
@ -176,6 +177,7 @@
lodNode.cxx \ lodNode.cxx \
materialAttrib.cxx \ materialAttrib.cxx \
materialCollection.cxx \ materialCollection.cxx \
modelFlattenRequest.cxx \
modelLoadRequest.cxx \ modelLoadRequest.cxx \
modelNode.cxx \ modelNode.cxx \
modelPool.cxx \ modelPool.cxx \
@ -278,6 +280,7 @@
lodNode.I lodNode.h \ lodNode.I lodNode.h \
materialAttrib.I materialAttrib.h \ materialAttrib.I materialAttrib.h \
materialCollection.I materialCollection.h \ materialCollection.I materialCollection.h \
modelFlattenRequest.I modelFlattenRequest.h \
modelLoadRequest.I modelLoadRequest.h \ modelLoadRequest.I modelLoadRequest.h \
modelNode.I modelNode.h \ modelNode.I modelNode.h \
modelPool.I modelPool.h \ modelPool.I modelPool.h \

View File

@ -60,6 +60,7 @@
#include "loaderFileTypeRegistry.h" #include "loaderFileTypeRegistry.h"
#include "lodNode.h" #include "lodNode.h"
#include "materialAttrib.h" #include "materialAttrib.h"
#include "modelFlattenRequest.h"
#include "modelLoadRequest.h" #include "modelLoadRequest.h"
#include "modelNode.h" #include "modelNode.h"
#include "modelRoot.h" #include "modelRoot.h"
@ -127,6 +128,12 @@ ConfigVariableBool unambiguous_graph
"assertion failure instead of just a warning (which can then be " "assertion failure instead of just a warning (which can then be "
"trapped with assert-abort).")); "trapped with assert-abort)."));
ConfigVariableBool no_unsupported_copy
("no-unsupported-copy", false,
PRC_DESC("Set this true to make an attempt to copy an unsupported type "
"generate an assertion failure instead of just a warning (which "
"can then be trapped with assert-abort)."));
ConfigVariableBool allow_unrelated_wrt ConfigVariableBool allow_unrelated_wrt
("allow-unrelated-wrt", true, ("allow-unrelated-wrt", true,
PRC_DESC("Set this true to allow unrelated NodePaths (that is, nodes which " PRC_DESC("Set this true to allow unrelated NodePaths (that is, nodes which "
@ -341,6 +348,7 @@ init_libpgraph() {
LoaderFileType::init_type(); LoaderFileType::init_type();
LoaderFileTypeBam::init_type(); LoaderFileTypeBam::init_type();
MaterialAttrib::init_type(); MaterialAttrib::init_type();
ModelFlattenRequest::init_type();
ModelLoadRequest::init_type(); ModelLoadRequest::init_type();
ModelNode::init_type(); ModelNode::init_type();
ModelRoot::init_type(); ModelRoot::init_type();

View File

@ -37,6 +37,7 @@ NotifyCategoryDecl(portal, EXPCL_PANDA, EXPTP_PANDA);
extern ConfigVariableBool fake_view_frustum_cull; extern ConfigVariableBool fake_view_frustum_cull;
extern ConfigVariableBool allow_portal_cull; extern ConfigVariableBool allow_portal_cull;
extern ConfigVariableBool unambiguous_graph; extern ConfigVariableBool unambiguous_graph;
extern ConfigVariableBool no_unsupported_copy;
extern ConfigVariableBool allow_unrelated_wrt; extern ConfigVariableBool allow_unrelated_wrt;
extern ConfigVariableBool paranoid_compose; extern ConfigVariableBool paranoid_compose;
extern ConfigVariableBool compose_componentwise; extern ConfigVariableBool compose_componentwise;

View File

@ -47,6 +47,7 @@ FindApproxLevelEntry(const FindApproxLevelEntry &parent,
_approx_path(parent._approx_path), _approx_path(parent._approx_path),
_next(next) _next(next)
{ {
nassertv(validate_ptr(this) && validate_ptr(&parent));
nassertv(_node_path.is_valid()); nassertv(_node_path.is_valid());
} }

View File

@ -0,0 +1,66 @@
// Filename: modelFlattenRequest.I
// Created by: drose (30Mar07)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: ModelFlattenRequest::Constructor
// Access: Published
// Description: Create a new ModelFlattenRequest, and add it to the loader
// via load_async(), to begin an asynchronous load.
////////////////////////////////////////////////////////////////////
INLINE ModelFlattenRequest::
ModelFlattenRequest(PandaNode *orig) :
AsyncTask(orig->get_name()),
_orig(orig),
_is_ready(false)
{
}
////////////////////////////////////////////////////////////////////
// Function: ModelFlattenRequest::get_orig
// Access: Published
// Description: Returns the original, unflattened node.
////////////////////////////////////////////////////////////////////
INLINE PandaNode *ModelFlattenRequest::
get_orig() const {
return _orig;
}
////////////////////////////////////////////////////////////////////
// Function: ModelFlattenRequest::is_ready
// Access: Published
// Description: Returns true if this request has completed, false if
// it is still pending. When this returns true, you may
// retrieve the model loaded by calling get_result().
////////////////////////////////////////////////////////////////////
INLINE bool ModelFlattenRequest::
is_ready() const {
return _is_ready;
}
////////////////////////////////////////////////////////////////////
// Function: ModelFlattenRequest::get_model
// Access: Published
// Description: Returns the flattened copy of the model. It is an
// error to call this unless is_ready() returns true.
////////////////////////////////////////////////////////////////////
INLINE PandaNode *ModelFlattenRequest::
get_model() const {
nassertr(_is_ready, NULL);
return _model;
}

View File

@ -0,0 +1,42 @@
// Filename: modelFlattenRequest.cxx
// Created by: drose (30Mar07)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#include "modelFlattenRequest.h"
#include "nodePath.h"
TypeHandle ModelFlattenRequest::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: ModelFlattenRequest::do_task
// Access: Protected, Virtual
// Description: Performs the task: that is, copies and flattens the
// model.
////////////////////////////////////////////////////////////////////
bool ModelFlattenRequest::
do_task() {
// We make another instance of the original node, so we can safely
// flatten that without affecting the original copy.
NodePath np("flatten_root");
np.attach_new_node(_orig);
np.flatten_strong();
_model = np.get_child(0).node();
_is_ready = true;
// Don't continue the task; we're done.
return false;
}

View File

@ -0,0 +1,74 @@
// Filename: modelFlattenRequest.h
// Created by: drose (30Mar07)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license. You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////
#ifndef MODELFLATTENREQUEST
#define MODELFLATTENREQUEST
#include "pandabase.h"
#include "asyncTask.h"
#include "pandaNode.h"
#include "pointerTo.h"
////////////////////////////////////////////////////////////////////
// Class : ModelFlattenRequest
// Description : This class object manages a single asynchronous
// request to flatten a model. The model will be
// duplicated and flattened in a sub-thread (if
// threading is available), without affecting the
// original model; and when the result is done it may be
// retrieved from this object.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA ModelFlattenRequest : public AsyncTask {
PUBLISHED:
INLINE ModelFlattenRequest(PandaNode *orig);
INLINE PandaNode *get_orig() const;
INLINE bool is_ready() const;
INLINE PandaNode *get_model() const;
protected:
virtual bool do_task();
private:
PT(PandaNode) _orig;
bool _is_ready;
PT(PandaNode) _model;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
AsyncTask::init_type();
register_type(_type_handle, "ModelFlattenRequest",
AsyncTask::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;
};
#include "modelFlattenRequest.I"
#endif

View File

@ -196,14 +196,30 @@ make_copy() const {
return new PandaNode(*this); return new PandaNode(*this);
} }
////////////////////////////////////////////////////////////////////
// Function: PandaNode::dupe_for_flatten
// Access: Public, Virtual
// Description: This is similar to make_copy(), but it makes a copy
// for the specific purpose of flatten. Typically, this
// will be a new PandaNode with a new pointer, but all
// of the internal data will always be shared with the
// original; whereas the new node returned by
// make_copy() might not share the internal data.
////////////////////////////////////////////////////////////////////
PandaNode *PandaNode::
dupe_for_flatten() const {
return make_copy();
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: PandaNode::safe_to_flatten // Function: PandaNode::safe_to_flatten
// Access: Public, Virtual // Access: Public, Virtual
// Description: Returns true if it is generally safe to flatten out // Description: Returns true if it is generally safe to flatten out
// this particular kind of PandaNode by duplicating // this particular kind of PandaNode by duplicating
// instances, false otherwise (for instance, a Camera // instances (by calling dupe_for_flatten()), false
// cannot be safely flattened, because the Camera // otherwise (for instance, a Camera cannot be safely
// pointer itself is meaningful). // flattened, because the Camera pointer itself is
// meaningful).
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
bool PandaNode:: bool PandaNode::
safe_to_flatten() const { safe_to_flatten() const {
@ -2397,6 +2413,10 @@ r_copy_subgraph(PandaNode::InstanceMap &inst_map, Thread *current_thread) const
if (copy->get_type() != get_type()) { if (copy->get_type() != get_type()) {
pgraph_cat.warning() pgraph_cat.warning()
<< "Don't know how to copy nodes of type " << get_type() << "\n"; << "Don't know how to copy nodes of type " << get_type() << "\n";
if (no_unsupported_copy) {
nassertr(false, NULL);
}
} }
copy->r_copy_children(this, inst_map, current_thread); copy->r_copy_children(this, inst_map, current_thread);

View File

@ -83,6 +83,7 @@ private:
public: public:
virtual PandaNode *make_copy() const; virtual PandaNode *make_copy() const;
virtual PandaNode *dupe_for_flatten() const;
virtual bool safe_to_flatten() const; virtual bool safe_to_flatten() const;
virtual bool safe_to_transform() const; virtual bool safe_to_transform() const;

View File

@ -12,6 +12,7 @@
#include "lodNode.cxx" #include "lodNode.cxx"
#include "materialAttrib.cxx" #include "materialAttrib.cxx"
#include "materialCollection.cxx" #include "materialCollection.cxx"
#include "modelFlattenRequest.cxx"
#include "modelLoadRequest.cxx" #include "modelLoadRequest.cxx"
#include "modelNode.cxx" #include "modelNode.cxx"
#include "modelPool.cxx" #include "modelPool.cxx"

View File

@ -175,15 +175,19 @@ r_apply_attribs(PandaNode *node, const AccumulatedAttribs &attribs,
pgraph_cat.spam() pgraph_cat.spam()
<< "Cannot duplicate nodes of type " << child_node->get_type() << "Cannot duplicate nodes of type " << child_node->get_type()
<< ".\n"; << ".\n";
resist_copy = true;
} }
resist_copy = true;
} else { } else {
PT(PandaNode) new_node = child_node->make_copy(); PT(PandaNode) new_node = child_node->dupe_for_flatten();
if (new_node->get_type() != child_node->get_type()) { if (new_node->get_type() != child_node->get_type()) {
pgraph_cat.error() pgraph_cat.error()
<< "Don't know how to copy nodes of type " << "Don't know how to copy nodes of type "
<< child_node->get_type() << "\n"; << child_node->get_type() << "\n";
if (no_unsupported_copy) {
nassertv(false);
}
resist_copy = true; resist_copy = true;
} else { } else {

View File

@ -74,7 +74,7 @@ private:
const WorkingNodePath *_next; const WorkingNodePath *_next;
PT(NodePathComponent) _start; PT(NodePathComponent) _start;
PandaNode *_node; PT(PandaNode) _node;
}; };
INLINE ostream &operator << (ostream &out, const WorkingNodePath &node_path); INLINE ostream &operator << (ostream &out, const WorkingNodePath &node_path);

View File

@ -32,6 +32,13 @@ ConfigureFn(config_pipeline) {
init_libpipeline(); init_libpipeline();
} }
ConfigVariableBool support_threads
("support-threads", true,
PRC_DESC("Set this false to disallow the creation of threads using Panda's "
"Thread interface, even if threading support is compiled in. This "
"does not affect the operation of mutexes and other synchronization "
"primitives, just the creation of threads."));
ConfigVariableInt thread_stack_size ConfigVariableInt thread_stack_size
("thread-stack-size", 4194304, ("thread-stack-size", 4194304,
PRC_DESC("Specifies the minimum size, in bytes, of the stack that will be " PRC_DESC("Specifies the minimum size, in bytes, of the stack that will be "

View File

@ -29,6 +29,7 @@ ConfigureDecl(config_pipeline, EXPCL_PANDA, EXPTP_PANDA);
NotifyCategoryDecl(pipeline, EXPCL_PANDA, EXPTP_PANDA); NotifyCategoryDecl(pipeline, EXPCL_PANDA, EXPTP_PANDA);
NotifyCategoryDecl(thread, EXPCL_PANDA, EXPTP_PANDA); NotifyCategoryDecl(thread, EXPCL_PANDA, EXPTP_PANDA);
extern ConfigVariableBool support_threads;
extern ConfigVariableInt thread_stack_size; extern ConfigVariableInt thread_stack_size;
extern ConfigVariableBool threads_always_global; extern ConfigVariableBool threads_always_global;
extern ConfigVariableBool threads_never_global; extern ConfigVariableBool threads_never_global;

View File

@ -233,6 +233,9 @@ get_current_pipeline_stage() {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
INLINE bool Thread:: INLINE bool Thread::
is_threading_supported() { is_threading_supported() {
if (!support_threads) {
return false;
}
return ThreadImpl::is_threading_supported(); return ThreadImpl::is_threading_supported();
} }

View File

@ -146,6 +146,12 @@ bool Thread::
start(ThreadPriority priority, bool global, bool joinable) { start(ThreadPriority priority, bool global, bool joinable) {
nassertr(!_started, false); nassertr(!_started, false);
if (!support_threads) {
thread_cat.warning()
<< *this << " could not be started: support-threads is false.\n";
return false;
}
if (threads_always_global) { if (threads_always_global) {
global = true; global = true;
} else if (threads_never_global) { } else if (threads_never_global) {

View File

@ -25,6 +25,7 @@
#include "threadPriority.h" #include "threadPriority.h"
#include "threadImpl.h" #include "threadImpl.h"
#include "pnotify.h" #include "pnotify.h"
#include "config_pipeline.h"
class Mutex; class Mutex;
class ReMutex; class ReMutex;

View File

@ -29,9 +29,6 @@
#include "mutexWin32Impl.h" #include "mutexWin32Impl.h"
#include "conditionVarWin32Impl.h" #include "conditionVarWin32Impl.h"
#define WIN32_LEAN_AND_MEAN 1
#include <windows.h>
class Thread; class Thread;
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////