diff --git a/panda/src/collide/collisionTraverser.cxx b/panda/src/collide/collisionTraverser.cxx index 45a57bb9bc..8859646f27 100644 --- a/panda/src/collide/collisionTraverser.cxx +++ b/panda/src/collide/collisionTraverser.cxx @@ -27,6 +27,7 @@ #include "transformState.h" #include "geomNode.h" #include "geom.h" +#include "lodNode.h" #include "nodePath.h" #include "pStatTimer.h" #include "indent.h" @@ -597,6 +598,14 @@ r_traverse(CollisionLevelState &level_state) { r_traverse(next_state); } + } else if (node->is_lod_node()) { + // If it's an LODNode, visit the lowest level of detail. + int index = DCAST(LODNode, node)->get_lowest_switch(); + if (index >= 0 && index < node->get_num_children()) { + CollisionLevelState next_state(level_state, node->get_child(index)); + r_traverse(next_state); + } + } else { // Otherwise, visit all the children. int num_children = node->get_num_children(); diff --git a/panda/src/framework/pandaFramework.cxx b/panda/src/framework/pandaFramework.cxx index e742de7fd0..2fed9d659f 100644 --- a/panda/src/framework/pandaFramework.cxx +++ b/panda/src/framework/pandaFramework.cxx @@ -447,7 +447,7 @@ all_windows_closed() const { // be instanced to each window's render tree as the // window is created. //////////////////////////////////////////////////////////////////// -const NodePath &PandaFramework:: +NodePath &PandaFramework:: get_models() { if (_models.is_empty()) { _models = NodePath("models"); diff --git a/panda/src/framework/pandaFramework.h b/panda/src/framework/pandaFramework.h index f86fd86d0b..c2682e5eb4 100644 --- a/panda/src/framework/pandaFramework.h +++ b/panda/src/framework/pandaFramework.h @@ -77,7 +77,7 @@ public: void close_all_windows(); bool all_windows_closed() const; - const NodePath &get_models(); + NodePath &get_models(); void report_frame_rate(ostream &out) const; void reset_frame_rate(); diff --git a/panda/src/gobj/LOD.I b/panda/src/gobj/LOD.I deleted file mode 100644 index 5649a2f19c..0000000000 --- a/panda/src/gobj/LOD.I +++ /dev/null @@ -1,184 +0,0 @@ -// Filename: LOD.I -// Created by: mike (09Jan97) -// -//////////////////////////////////////////////////////////////////// -// -// 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 - -//////////////////////////////////////////////////////////////////// -// Function: LODSwitch::Default Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE LODSwitch:: -LODSwitch() { -} - -//////////////////////////////////////////////////////////////////// -// Function: LODSwitch::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE LODSwitch:: -LODSwitch(float in, float out) { - set_range(in, out); -} - -//////////////////////////////////////////////////////////////////// -// Function: LODSwitch::Copy Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE LODSwitch:: -LODSwitch(const LODSwitch ©) : - _in(copy._in), - _out(copy._out) -{ -} - -//////////////////////////////////////////////////////////////////// -// Function: LODSwitch::Copy Assignment Operator -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE void LODSwitch:: -operator = (const LODSwitch ©) { - _in = copy._in; - _out = copy._out; -} - -//////////////////////////////////////////////////////////////////// -// Function: LODSwitch::get_range -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE void LODSwitch:: -get_range(float &in, float &out) const { - in = get_in(); - out = get_out(); -} - -//////////////////////////////////////////////////////////////////// -// Function: LODSwitch::get_in -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE float LODSwitch:: -get_in() const { - return sqrtf(_in); -} - -//////////////////////////////////////////////////////////////////// -// Function: LODSwitch::get_out -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE float LODSwitch:: -get_out() const { - return sqrtf(_out); -} - -//////////////////////////////////////////////////////////////////// -// Function: LODSwitch::set_range -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE void LODSwitch:: -set_range(float in, float out) { - // We actually store the square of the switching distances. This - // makes the LOD computation a little simpler. - _in = in * in; - _out = out * out; -} - -//////////////////////////////////////////////////////////////////// -// Function: LODSwitch::in_range -// Access: Public -// Description: Computes the distance between two points and returns -// true if the result is within the range for the LOD. -//////////////////////////////////////////////////////////////////// -INLINE bool LODSwitch:: -in_range(float dist_squared) const { - return (dist_squared >= _out && dist_squared < _in); -} - -//////////////////////////////////////////////////////////////////// -// Function: LODSwitch::rescale -// Access: Public -// Description: Scales the switching distances by the square root of -// the indicated factor. -//////////////////////////////////////////////////////////////////// -INLINE void LODSwitch:: -rescale(float factor_squared) { - _in *= factor_squared; - _out *= factor_squared; -} - -//////////////////////////////////////////////////////////////////// -// Function: LODSwitch::operator == -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE bool LODSwitch:: -operator == (const LODSwitch &) const { - return true; -} - -//////////////////////////////////////////////////////////////////// -// Function: LODSwitch::operator != -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE bool LODSwitch:: -operator != (const LODSwitch &) const { - return false; -} - -//////////////////////////////////////////////////////////////////// -// Function: LODSwitch::operator < -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE bool LODSwitch:: -operator < (const LODSwitch &) const { - return false; -} - -//////////////////////////////////////////////////////////////////// -// Function: LODSwitch::write_datagram -// Access: Public -// Description: Writes the contents of the LODSwitch out to the -// datagram, presumably in preparation to writing to a -// Bam file. -//////////////////////////////////////////////////////////////////// -INLINE void LODSwitch:: -write_datagram(Datagram &destination) const { - destination.add_float32(_in); - destination.add_float32(_out); -} - -//////////////////////////////////////////////////////////////////// -// Function: LODSwitch::read_datagram -// Access: Public -// Description: Reads the contents of the LODSwitch from the -// datagram, presumably in response to reading a Bam -// file. -//////////////////////////////////////////////////////////////////// -INLINE void LODSwitch:: -read_datagram(DatagramIterator &source) { - _in = source.get_float32(); - _out = source.get_float32(); -} diff --git a/panda/src/gobj/LOD.cxx b/panda/src/gobj/LOD.cxx deleted file mode 100644 index bd857ef276..0000000000 --- a/panda/src/gobj/LOD.cxx +++ /dev/null @@ -1,228 +0,0 @@ -// Filename: LOD.cxx -// Created by: mike (09Jan97) -// -//////////////////////////////////////////////////////////////////// -// -// 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 "LOD.h" - -#include "datagram.h" -#include "datagramIterator.h" -#include "indent.h" -#include "config_gobj.h" - -#define EXPCL EXPCL_PANDA -#define EXPTP EXPTP_PANDA -#define TYPE LODSwitch -#define NAME LODSwitchVector - -#include "vector_src.cxx" - -float LOD::_stress_factor = lod_stress_factor; - -//////////////////////////////////////////////////////////////////// -// Function: LOD::constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -LOD:: -LOD(void) { - _center.set(0.0f, 0.0f, 0.0f); -} - -//////////////////////////////////////////////////////////////////// -// Function: LOD::Copy Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -LOD:: -LOD(const LOD ©) : - _center(copy._center), - _switch_vector(copy._switch_vector) -{ -} - -//////////////////////////////////////////////////////////////////// -// Function: LOD::destructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -LOD:: -~LOD(void) { -} - -//////////////////////////////////////////////////////////////////// -// Function: LOD::xform -// Access: Public -// Description: Transforms the LOD specification by the indicated -// matrix. -//////////////////////////////////////////////////////////////////// -void LOD:: -xform(const LMatrix4f &mat) { - _center = _center * mat; - - // We'll take just the length of the y axis as the matrix's scale. - LVector3f y; - mat.get_row3(y,1); - float factor_squared = y.length_squared(); - - LODSwitchVector::iterator si; - for (si = _switch_vector.begin(); si != _switch_vector.end(); ++si) { - (*si).rescale(factor_squared); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: LOD::compute_child -// Access: Public -// Description: Computes the distance between two points and returns -// the index for the child of the LOD by testing against -// the corresponding list of switching distances. -//////////////////////////////////////////////////////////////////// -int LOD:: -compute_child(const LPoint3f &cam_pos, const LPoint3f ¢er) const { - - LVector3f v = cam_pos - center; - float dist = dot(v, v) * _stress_factor; - LODSwitchVector::const_iterator i; - int child = 0; - for (i = _switch_vector.begin(), child = 0; - i != _switch_vector.end(); ++i, ++child) { - if ((*i).in_range(dist)) - break; - } - - if(debug_LOD_mode) { - //not ifndef NDEBUG'ing this out since need it at Opt4 for perf measurements - if(select_LOD_number>=0) { - return select_LOD_number; - } - - // since lowest level LOD is lev 0, must invert the meaning of - // so minimum_LOD_number 0 will screen out no LODs, and increasing it - // will screen out successively higher levels - int max_allowed_LOD_number = _switch_vector.size() - minimum_LOD_number; - if(child > max_allowed_LOD_number) { - child = max_allowed_LOD_number; - } - } - - return child; -} - -//////////////////////////////////////////////////////////////////// -// Function: LOD::write_datagram -// Access: Public -// Description: Writes the contents of the LOD out to the datagram, -// presumably in preparation to writing to a Bam file. -//////////////////////////////////////////////////////////////////// -void LOD:: -write_datagram(Datagram &destination) const { - _center.write_datagram(destination); - - destination.add_uint16(_switch_vector.size()); - - LODSwitchVector::const_iterator si; - for (si = _switch_vector.begin(); - si != _switch_vector.end(); - ++si) { - (*si).write_datagram(destination); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: LOD::read_datagram -// Access: Public -// Description: Reads the contents of the LOD from the datagram, -// presumably in response to reading a Bam file. -//////////////////////////////////////////////////////////////////// -void LOD:: -read_datagram(DatagramIterator &source) { - _center.read_datagram(source); - - _switch_vector.clear(); - - int num_switches = source.get_uint16(); - _switch_vector.reserve(num_switches); - for (int i = 0; i < num_switches; i++) { - _switch_vector.push_back(LODSwitch(0, 0)); - _switch_vector.back().read_datagram(source); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: LOD::output -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -void LOD:: -output(ostream &out) const { - if (_switch_vector.empty()) { - out << "no switches."; - } else { - LODSwitchVector::const_iterator si; - si = _switch_vector.begin(); - out << "(" << (*si).get_in() << "/" << (*si).get_out() << ")"; - ++si; - while (si != _switch_vector.end()) { - out << " (" << (*si).get_in() << "/" << (*si).get_out() << ")"; - ++si; - } - } -} - -//////////////////////////////////////////////////////////////////// -// Function: LOD::write -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -void LOD:: -write(ostream &out, int indent_level) const { - indent(out, indent_level) - << "LOD, " << _switch_vector.size() << " switches:\n"; - LODSwitchVector::const_iterator si; - int i = 0; - for (si = _switch_vector.begin(); - si != _switch_vector.end(); - ++si) { - indent(out, indent_level + 2) - << i << ". in at " << (*si).get_in() - << ", out at " << (*si).get_out() << "\n"; - i++; - } -} - -//////////////////////////////////////////////////////////////////// -// Function: LOD::set_stress_factor -// Access: Published, Static -// Description: Sets the factor that globally scales all LOD's. This -// factor is applied to the square of the LOD distance, -// so the larger the number, the lower the detail that -// is presented. The normal value is 1.0. -//////////////////////////////////////////////////////////////////// -void LOD:: -set_stress_factor(float stress_factor) { - _stress_factor = stress_factor; -} - -//////////////////////////////////////////////////////////////////// -// Function: LOD::get_stress_factor -// Access: Published, Static -// Description: Returns the factor that globally scales all LOD's. -// See get_stress_factor(). -//////////////////////////////////////////////////////////////////// -float LOD:: -get_stress_factor() { - return _stress_factor; -} diff --git a/panda/src/gobj/LOD.h b/panda/src/gobj/LOD.h deleted file mode 100644 index 9c87d3b753..0000000000 --- a/panda/src/gobj/LOD.h +++ /dev/null @@ -1,119 +0,0 @@ -// Filename: LOD.h -// Created by: mike (09Jan97) -// -//////////////////////////////////////////////////////////////////// -// -// 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 LOD_H -#define LOD_H - -#include "pandabase.h" - -#include "luse.h" -#include "typedReferenceCount.h" - -class Datagram; -class DatagramIterator; - -//////////////////////////////////////////////////////////////////// -// Class : LODSwitch -// Description : Defines a switching region for an LOD. An object -// will be visible when it is closer than "in" units, -// but further than "out" units from the camera. -// -// The sense of in vs. out distances is as if the object -// were coming towards you from far away: it switches -// "in" at the far distance, and switches "out" at the -// close distance. Thus, "in" should be larger than -// "out". -//////////////////////////////////////////////////////////////////// -class EXPCL_PANDA LODSwitch { -public: - INLINE LODSwitch(); - INLINE LODSwitch(float in, float out); - INLINE LODSwitch(const LODSwitch ©); - INLINE void operator = (const LODSwitch ©); - - INLINE void get_range(float &in, float &out) const; - INLINE float get_in() const; - INLINE float get_out() const; - INLINE void set_range(float in, float out); - INLINE bool in_range(float dist_squared) const; - - INLINE void rescale(float factor_squared); - - // We must declare these operators to allow VC++ to explicitly - // export pvector, below. They don't do anything useful. - INLINE bool operator == (const LODSwitch &other) const; - INLINE bool operator != (const LODSwitch &other) const; - INLINE bool operator < (const LODSwitch &other) const; - - INLINE void write_datagram(Datagram &destination) const; - INLINE void read_datagram(DatagramIterator &source); - -protected: - float _in; - float _out; -}; - -#define EXPCL EXPCL_PANDA -#define EXPTP EXPTP_PANDA -#define TYPE LODSwitch -#define NAME LODSwitchVector - -#include "vector_src.h" - -//////////////////////////////////////////////////////////////////// -// Class : LOD -// Description : Computes whether a level-of-detail should be rendered -// or not based on distance from the rendering camera. -//////////////////////////////////////////////////////////////////// -class EXPCL_PANDA LOD { -public: - LOD(); - LOD(const LOD ©); - ~LOD(); - - void xform(const LMatrix4f &mat); - - int compute_child(const LPoint3f &cam_pos, - const LPoint3f ¢er) const; - - void write_datagram(Datagram &destination) const; - void read_datagram(DatagramIterator &source); - - void output(ostream &out) const; - void write(ostream &out, int indent_level = 0) const; - -PUBLISHED: - static void set_stress_factor(float stress_factor); - static float get_stress_factor(); - -public: - LPoint3f _center; - LODSwitchVector _switch_vector; - -private: - static float _stress_factor; -}; - -INLINE ostream &operator << (ostream &out, const LOD &lod) { - lod.output(out); - return out; -} - -#include "LOD.I" - -#endif diff --git a/panda/src/gobj/Sources.pp b/panda/src/gobj/Sources.pp index 8b39d73ffa..b3a1666bc6 100644 --- a/panda/src/gobj/Sources.pp +++ b/panda/src/gobj/Sources.pp @@ -10,7 +10,6 @@ #define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx #define SOURCES \ - LOD.I LOD.h \ boundedObject.I boundedObject.h \ config_gobj.h drawable.h \ geom.I geom.h \ @@ -33,7 +32,6 @@ textureStage.I textureStage.h #define INCLUDED_SOURCES \ - LOD.cxx \ boundedObject.cxx \ config_gobj.cxx drawable.cxx geom.cxx \ geomContext.cxx \ @@ -48,7 +46,6 @@ texCoordName.cxx textureStage.cxx #define INSTALL_HEADERS \ - LOD.I LOD.h \ boundedObject.I boundedObject.h \ config_gobj.h \ drawable.h geom.I geom.h \ diff --git a/panda/src/gobj/config_gobj.cxx b/panda/src/gobj/config_gobj.cxx index 396e97dbc5..f850482f3d 100644 --- a/panda/src/gobj/config_gobj.cxx +++ b/panda/src/gobj/config_gobj.cxx @@ -107,20 +107,6 @@ BamTextureMode bam_texture_mode; // texture file, which will presumably only be loaded once. const string fake_texture_image = config_gobj.GetString("fake-texture-image", ""); -// must be set to true for LOD_number debugging items to work -const bool debug_LOD_mode = config_gobj.GetBool("debug-LOD-mode", false); - -// if this is >=0, select_child always returns this LOD number -const int select_LOD_number = config_gobj.GetInt("select-LOD-number", -1); - -// this controls the LOD child number returned by compute_child -// use it to force the LOD alg to not select the highest level(s) of LOD -// minimum_LOD_number=0 will screen out no LODs, and increasing it -// will screen out successively higher levels -const int minimum_LOD_number = config_gobj.GetInt("minimum-LOD-number", 0); - -const float lod_stress_factor = config_gobj.GetFloat("lod-stress-factor", 1.0f); - // The default near and far plane distances. const float default_near = config_gobj.GetFloat("default-near", 1.0f); const float default_far = config_gobj.GetFloat("default-far", 1000.0f); diff --git a/panda/src/gobj/config_gobj.h b/panda/src/gobj/config_gobj.h index 93472df396..dd05d9da98 100644 --- a/panda/src/gobj/config_gobj.h +++ b/panda/src/gobj/config_gobj.h @@ -44,11 +44,6 @@ enum BamTextureMode { extern EXPCL_PANDA BamTextureMode bam_texture_mode; extern EXPCL_PANDA const string fake_texture_image; -extern EXPCL_PANDA const bool debug_number_mode; -extern EXPCL_PANDA const int select_LOD_number; -extern EXPCL_PANDA const int minimum_LOD_number; -extern EXPCL_PANDA const bool debug_LOD_mode; - extern const float default_near; extern const float default_far; extern const float default_fov; diff --git a/panda/src/gobj/gobj_composite2.cxx b/panda/src/gobj/gobj_composite2.cxx index 9424521fd9..884462eae5 100644 --- a/panda/src/gobj/gobj_composite2.cxx +++ b/panda/src/gobj/gobj_composite2.cxx @@ -3,7 +3,6 @@ #include "drawable.cxx" #include "geomContext.cxx" #include "imageBuffer.cxx" -#include "LOD.cxx" #include "material.cxx" #include "materialPool.cxx" #include "orthographicLens.cxx" diff --git a/panda/src/pgraph/fadeLodNode.I b/panda/src/pgraph/fadeLodNode.I index 8a646c4137..5ad7642900 100755 --- a/panda/src/pgraph/fadeLodNode.I +++ b/panda/src/pgraph/fadeLodNode.I @@ -16,27 +16,6 @@ // //////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////// -// Function: FadeLODNode::CData::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE FadeLODNode::CData:: -CData() { - _fade_time = 1.0; -} - -//////////////////////////////////////////////////////////////////// -// Function: FadeLODNode::CData::Copy Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -INLINE FadeLODNode::CData:: -CData(const FadeLODNode::CData ©) : - _lod(copy._lod) { - _fade_time = copy._fade_time; -} - //////////////////////////////////////////////////////////////////// // Function: FadeLODNode::Constructor // Access: Published @@ -44,7 +23,9 @@ CData(const FadeLODNode::CData ©) : //////////////////////////////////////////////////////////////////// INLINE FadeLODNode:: FadeLODNode(const string &name) : - PandaNode(name) { + LODNode(name) +{ + _fade_time = 1.0; _fade_mode = false; _previous_child = 0; } @@ -56,128 +37,13 @@ FadeLODNode(const string &name) : //////////////////////////////////////////////////////////////////// INLINE FadeLODNode:: FadeLODNode(const FadeLODNode ©) : - PandaNode(copy), - _cycler(copy._cycler) { + LODNode(copy) +{ + _fade_time = copy._fade_time; _fade_mode = copy._fade_mode; _previous_child = copy._previous_child; } -//////////////////////////////////////////////////////////////////// -// Function: FadeLODNode::add_switch -// Access: Published -// Description: Adds a switch range to the FadeLODNode. This implies -// that the corresponding child node has been parented -// to the node. -// -// The sense of in vs. out distances is as if the object -// were coming towards you from far away: it switches -// "in" at the far distance, and switches "out" at the -// close distance. Thus, "in" should be larger than -// "out". -//////////////////////////////////////////////////////////////////// -INLINE void FadeLODNode:: -add_switch(float in, float out) { - CDWriter cdata(_cycler); - cdata->_lod._switch_vector.push_back(LODSwitch(in, out)); -} - -//////////////////////////////////////////////////////////////////// -// Function: FadeLODNode::set_switch -// Access: Published -// Description: Changes the switching range of a particular child of -// the LODNode. See add_switch(). -//////////////////////////////////////////////////////////////////// -INLINE bool FadeLODNode:: -set_switch(int index, float in, float out) { - CDWriter cdata(_cycler); - nassertr(index >= 0 && index < (int)cdata->_lod._switch_vector.size(), false); - cdata->_lod._switch_vector[index].set_range(in, out); - return true; -} - -//////////////////////////////////////////////////////////////////// -// Function: FadeLODNode::clear_switches -// Access: Published -// Description: Removes the set of switching ranges for the LODNode, -// presumably in conjunction with removing all of its -// children. See add_switch(). -//////////////////////////////////////////////////////////////////// -INLINE void FadeLODNode:: -clear_switches(void) { - CDWriter cdata(_cycler); - cdata->_lod._switch_vector.erase(cdata->_lod._switch_vector.begin(), - cdata->_lod._switch_vector.end()); -} - -//////////////////////////////////////////////////////////////////// -// Function: FadeLODNode::get_num_switches -// Access: Published -// Description: Returns the number of switch ranges added to the -// LODNode. This should correspond to the number of -// children of the node in order for the FadeLODNode to -// function correctly. -//////////////////////////////////////////////////////////////////// -INLINE int FadeLODNode:: -get_num_switches() const { - CDReader cdata(_cycler); - return cdata->_lod._switch_vector.size(); -} - -//////////////////////////////////////////////////////////////////// -// Function: FadeLODNode::get_in -// Access: Published -// Description: Returns the "in" distance of the indicated switch -// range. This should be larger than the "out" distance -// of the same range. -//////////////////////////////////////////////////////////////////// -INLINE float FadeLODNode:: -get_in(int index) const { - CDReader cdata(_cycler); - nassertr(index >= 0 && index < (int)cdata->_lod._switch_vector.size(), 0.0); - return cdata->_lod._switch_vector[index].get_in(); -} - -//////////////////////////////////////////////////////////////////// -// Function: FadeLODNode::get_out -// Access: Published -// Description: Returns the "out" distance of the indicated switch -// range. This should be smaller than the "in" distance -// of the same range. -//////////////////////////////////////////////////////////////////// -INLINE float FadeLODNode:: -get_out(int index) const { - CDReader cdata(_cycler); - nassertr(index >= 0 && index < (int)cdata->_lod._switch_vector.size(), 0.0); - return cdata->_lod._switch_vector[index].get_out(); -} - -//////////////////////////////////////////////////////////////////// -// Function: FadeLODNode::set_center -// Access: Published -// Description: Specifies the center of the LOD. This is the point -// that is compared to the camera (in camera space) to -// determine the particular LOD that should be chosen. -//////////////////////////////////////////////////////////////////// -INLINE void FadeLODNode:: -set_center(const LPoint3f ¢er) { - CDWriter cdata(_cycler); - cdata->_lod._center = center; -} - -//////////////////////////////////////////////////////////////////// -// Function: FadeLODNode::get_center -// Access: Published -// Description: Returns the center of the LOD. This is the point -// that is compared to the camera (in camera space) to -// determine the particular LOD that should be chosen. -//////////////////////////////////////////////////////////////////// -INLINE const LPoint3f &FadeLODNode:: -get_center() const { - CDReader cdata(_cycler); - return cdata->_lod._center; -} - - //////////////////////////////////////////////////////////////////// // Function: FadeLODNode::set_fade_time // Access: Published @@ -185,8 +51,7 @@ get_center() const { //////////////////////////////////////////////////////////////////// INLINE void FadeLODNode:: set_fade_time(float t) { - CDWriter cdata(_cycler); - cdata->_fade_time = t; + _fade_time = t; } //////////////////////////////////////////////////////////////////// @@ -196,7 +61,6 @@ set_fade_time(float t) { //////////////////////////////////////////////////////////////////// INLINE float FadeLODNode:: get_fade_time() const { - CDReader cdata(_cycler); - return cdata->_fade_time; + return _fade_time; } diff --git a/panda/src/pgraph/fadeLodNode.cxx b/panda/src/pgraph/fadeLodNode.cxx index 386c93009e..1ef53fd21b 100755 --- a/panda/src/pgraph/fadeLodNode.cxx +++ b/panda/src/pgraph/fadeLodNode.cxx @@ -26,39 +26,6 @@ TypeHandle FadeLODNode::_type_handle; -//////////////////////////////////////////////////////////////////// -// Function: FadeLODNode::CData::make_copy -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -CycleData *FadeLODNode::CData:: -make_copy() const { - return new CData(*this); -} - -//////////////////////////////////////////////////////////////////// -// Function: FadeLODNode::CData::write_datagram -// Access: Public, Virtual -// Description: Writes the contents of this object to the datagram -// for shipping out to a Bam file. -//////////////////////////////////////////////////////////////////// -void FadeLODNode::CData:: -write_datagram(BamWriter *manager, Datagram &dg) const { - _lod.write_datagram(dg); -} - -//////////////////////////////////////////////////////////////////// -// Function: FadeLODNode::CData::fillin -// Access: Public, Virtual -// Description: This internal function is called by make_from_bam to -// read in all of the relevant data from the BamFile for -// the new LODNode. -//////////////////////////////////////////////////////////////////// -void FadeLODNode::CData:: -fillin(DatagramIterator &scan, BamReader *manager) { - _lod.read_datagram(scan); -} - //////////////////////////////////////////////////////////////////// // Function: FadeLODNode::make_copy // Access: Public, Virtual @@ -72,48 +39,6 @@ make_copy() const { return new FadeLODNode(*this); } -//////////////////////////////////////////////////////////////////// -// Function: FadeLODNode::safe_to_combine -// Access: Public, Virtual -// Description: Returns true if it is generally safe to combine this -// particular kind of PandaNode with other kinds of -// PandaNodes, adding children or whatever. For -// instance, an LODNode should not be combined with any -// other PandaNode, because its set of children is -// meaningful. -//////////////////////////////////////////////////////////////////// -bool FadeLODNode:: -safe_to_combine() const { - return false; -} - -//////////////////////////////////////////////////////////////////// -// Function: FadeLODNode::xform -// Access: Public, Virtual -// Description: Transforms the contents of this PandaNode by the -// indicated matrix, if it means anything to do so. For -// most kinds of PandaNodes, this does nothing. -//////////////////////////////////////////////////////////////////// -void FadeLODNode:: -xform(const LMatrix4f &mat) { - CDWriter cdata(_cycler); - cdata->_lod.xform(mat); -} - -//////////////////////////////////////////////////////////////////// -// Function: FadeLODNode::has_cull_callback -// Access: Public, Virtual -// Description: Should be overridden by derived classes to return -// true if cull_callback() has been defined. Otherwise, -// returns false to indicate cull_callback() does not -// need to be called for this node during the cull -// traversal. -//////////////////////////////////////////////////////////////////// -bool FadeLODNode:: -has_cull_callback() const { - return true; -} - //////////////////////////////////////////////////////////////////// // Function: FadeLODNode::cull_callback // Access: Public, Virtual @@ -135,94 +60,90 @@ has_cull_callback() const { //////////////////////////////////////////////////////////////////// bool FadeLODNode:: cull_callback(CullTraverser *trav, CullTraverserData &data) { - PandaNode *node = data.node(); - CDReader cdata(_cycler); if (_fade_mode) { - float in_alpha; - float out_alpha; - _fade_timer -= ClockObject::get_global_clock()->get_dt(); - if (_fade_timer <= (cdata->_fade_time / 2.0)) { - //SECOND HALF OF FADE: - //Fade out the old LOD with z write off and - //draw the opaque new LOD with z write on - out_alpha = (_fade_timer*2.0) / cdata->_fade_time; - if (out_alpha < 0.0) { - out_alpha = 0.0; - } - - CullTraverserData next_data_in(data, node->get_child(_fade_in)); - CullTraverserData next_data_out(data, node->get_child(_fade_out)); - - // Disable Transparency on new LOD - next_data_in._state = next_data_in._state->add_attrib(TransparencyAttrib::make(TransparencyAttrib::M_none), 0); - // Enable Transparency on old LOD - next_data_out._state = next_data_out._state->add_attrib(TransparencyAttrib::make(TransparencyAttrib::M_alpha), 0); - // Start Fading the old LOD out - next_data_out._state = next_data_out._state->add_attrib(ColorScaleAttrib::make(LVecBase4f(1.0,1.0,1.0,out_alpha))); - // The new LOD is now opaque and has depth writing - next_data_in._state = next_data_in._state->add_attrib(DepthWriteAttrib::make(DepthWriteAttrib::M_on), 0); - // The old LOD is fading so it doesnt depth write - next_data_out._state = next_data_out._state->add_attrib(DepthWriteAttrib::make(DepthWriteAttrib::M_off), 0); - - - trav->traverse(next_data_in); - trav->traverse(next_data_out); - } else { - // FIRST HALF OF FADE - // Fade the new LOD in with z writing off - // Keep drawing the old LOD opaque with z writing on - in_alpha = (1.0 - (_fade_timer / cdata->_fade_time))*2.0; - if (in_alpha > 1.0) { - in_alpha = 1.0; - } - - CullTraverserData next_data_out(data, node->get_child(_fade_out)); - CullTraverserData next_data_in(data, node->get_child(_fade_in)); + float now = ClockObject::get_global_clock()->get_frame_time(); + float elapsed = now - _fade_start; - // Disable transparency on old LOD - next_data_out._state = next_data_out._state->add_attrib(TransparencyAttrib::make(TransparencyAttrib::M_none), 0); - // Enable transparency on new LOD - next_data_in._state = next_data_in._state->add_attrib(TransparencyAttrib::make(TransparencyAttrib::M_alpha), 0); - // Start Fading in the new LOD - next_data_in._state = next_data_in._state->add_attrib(ColorScaleAttrib::make(LVecBase4f(1.0,1.0,1.0,in_alpha))); - // Enable depth write for the old LOD - next_data_out._state = next_data_out._state->add_attrib(DepthWriteAttrib::make(DepthWriteAttrib::M_on), 0); - // Disable depth write for the new LOD - next_data_in._state = next_data_in._state->add_attrib(DepthWriteAttrib::make(DepthWriteAttrib::M_off), 0); - + float half_fade_time = _fade_time / 2.0f; + + if (elapsed < half_fade_time) { + // FIRST HALF OF FADE + // Fade the new LOD in with z writing off + // Keep drawing the old LOD opaque with z writing on + if (_fade_out >= 0 && _fade_out < get_num_children()) { + CullTraverserData next_data_out(data, get_child(_fade_out)); trav->traverse(next_data_out); + } + + if (_fade_in >= 0 && _fade_in < get_num_children()) { + CullTraverserData next_data_in(data, get_child(_fade_in)); + + float in_alpha = elapsed / half_fade_time; + if (in_alpha > 1.0f) { + in_alpha = 1.0f; + } + LVecBase4f alpha_scale(1.0f, 1.0f, 1.0f, in_alpha); + + next_data_in._state = + next_data_in._state->compose(get_fade_out_state())->compose + (RenderState::make(ColorScaleAttrib::make(alpha_scale))); + trav->traverse(next_data_in); } - if (_fade_timer < 0) { // Fading Complete + + } else if (elapsed < _fade_time) { + //SECOND HALF OF FADE: + //Fade out the old LOD with z write off and + //draw the opaque new LOD with z write on + if (_fade_in >= 0 && _fade_in < get_num_children()) { + CullTraverserData next_data_in(data, get_child(_fade_in)); + trav->traverse(next_data_in); + } + + if (_fade_out >= 0 && _fade_out < get_num_children()) { + CullTraverserData next_data_out(data, get_child(_fade_out)); + + float out_alpha = 1.0f - elapsed / half_fade_time; + if (out_alpha < 0.0f) { + out_alpha = 0.0f; + } + LVecBase4f alpha_scale(1.0f, 1.0f, 1.0f, out_alpha); + + next_data_out._state = + next_data_out._state->compose(get_fade_out_state())->compose + (RenderState::make(ColorScaleAttrib::make(alpha_scale))); + + trav->traverse(next_data_out); + } + + } else { + // Fading complete _fade_mode = false; + + if (_fade_in >= 0 && _fade_in < get_num_children()) { + CullTraverserData next_data_in(data, get_child(_fade_in)); + trav->traverse(next_data_in); + } } + } else { - if (data._net_transform->is_singular()) { - // If we're under a singular transform, we can't compute the LOD; - // select none of them instead. - //select_child(get_num_children()); - return false; - } else { - LPoint3f camera_pos(0, 0, 0); - // Get the LOD center in camera space - CPT(TransformState) rel_transform = - trav->get_camera_transform()->invert_compose(data._net_transform); - LPoint3f center = cdata->_lod._center * rel_transform->get_mat(); - // Determine which child to traverse - int index = cdata->_lod.compute_child(camera_pos, center); - //printf("CHILD: %d PREVIOUS %d \n",index,_previous_child); - if (index != _previous_child) { // Transition occurred - _fade_mode = true; - _fade_timer = cdata->_fade_time; - _fade_out = _previous_child; - _fade_in = index; - _previous_child = index; - CullTraverserData next_data_transition(data, node->get_child(_fade_out)); + int index = compute_child(trav, data); + if (index != _previous_child) { // Transition occurred + _fade_mode = true; + _fade_start = ClockObject::get_global_clock()->get_frame_time(); + _fade_out = _previous_child; + _fade_in = index; + _previous_child = index; + if (_fade_out >= 0 && _fade_out < get_num_children()) { + CullTraverserData next_data_transition(data, get_child(_fade_out)); trav->traverse(next_data_transition); - } else { + } + + } else { + if (index >= 0 && index < get_num_children()) { // No transition... handle things as usual // Traverse only one valid child - CullTraverserData next_data_normal(data, node->get_child(index)); + CullTraverserData next_data_normal(data, get_child(index)); trav->traverse(next_data_normal); } } @@ -238,11 +159,28 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) { //////////////////////////////////////////////////////////////////// void FadeLODNode:: output(ostream &out) const { - PandaNode::output(out); - CDReader cdata(_cycler); - out << " "; - cdata->_lod.output(out); - out<< "Fade Time : " << cdata->_fade_time << endl; + LODNode::output(out); + out << " fade time: " << _fade_time; +} + +//////////////////////////////////////////////////////////////////// +// Function: FadeLODNode::get_fade_out_state +// Access: Protected, Static +// Description: Returns a RenderState for rendering the element that +// is switching out of visibility. +//////////////////////////////////////////////////////////////////// +CPT(RenderState) FadeLODNode:: +get_fade_out_state() { + // Once someone asks for this pointer, we hold its reference count + // and never free it. + static CPT(RenderState) state = (const RenderState *)NULL; + if (state == (const RenderState *)NULL) { + state = RenderState::make + (TransparencyAttrib::make(TransparencyAttrib::M_alpha), + DepthWriteAttrib::make(DepthWriteAttrib::M_off)); + } + + return state; } //////////////////////////////////////////////////////////////////// @@ -264,8 +202,7 @@ register_with_read_factory() { //////////////////////////////////////////////////////////////////// void FadeLODNode:: write_datagram(BamWriter *manager, Datagram &dg) { - PandaNode::write_datagram(manager, dg); - manager->write_cdata(dg, _cycler); + LODNode::write_datagram(manager, dg); } //////////////////////////////////////////////////////////////////// @@ -297,6 +234,5 @@ make_from_bam(const FactoryParams ¶ms) { //////////////////////////////////////////////////////////////////// void FadeLODNode:: fillin(DatagramIterator &scan, BamReader *manager) { - PandaNode::fillin(scan, manager); - manager->read_cdata(scan, _cycler); + LODNode::fillin(scan, manager); } diff --git a/panda/src/pgraph/fadeLodNode.h b/panda/src/pgraph/fadeLodNode.h index c571872c4b..77b9aede98 100755 --- a/panda/src/pgraph/fadeLodNode.h +++ b/panda/src/pgraph/fadeLodNode.h @@ -21,49 +21,43 @@ #include "pandabase.h" -#include "pandaNode.h" - -#include "LOD.h" +#include "lodNode.h" //////////////////////////////////////////////////////////////////// // Class : FadeLODNode // Description : A Level-of-Detail node with alpha based switching. //////////////////////////////////////////////////////////////////// -class EXPCL_PANDA FadeLODNode : public PandaNode { +class EXPCL_PANDA FadeLODNode : public LODNode { PUBLISHED: INLINE FadeLODNode(const string &name); - protected: INLINE FadeLODNode(const FadeLODNode ©); public: virtual PandaNode *make_copy() const; - virtual bool safe_to_combine() const; - virtual void xform(const LMatrix4f &mat); - virtual bool has_cull_callback() const; virtual bool cull_callback(CullTraverser *trav, CullTraverserData &data); virtual void output(ostream &out) const; PUBLISHED: - // The sense of in vs. out distances is as if the object were coming - // towards you from far away: it switches "in" at the far distance, - // and switches "out" at the close distance. Thus, "in" should be - // larger than "out". - - INLINE void add_switch(float in, float out); - INLINE bool set_switch(int index, float in, float out); - INLINE void clear_switches(void); - - INLINE int get_num_switches() const; - INLINE float get_in(int index) const; - INLINE float get_out(int index) const; - - INLINE void set_center(const LPoint3f ¢er); - INLINE const LPoint3f &get_center() const; - INLINE void set_fade_time(float t); INLINE float get_fade_time() const; +private: + static CPT(RenderState) get_fade_out_state(); + +private: + float _fade_time; + + // These values are used to implement the fade-in-transition, and + // really shouldn't be stored here (because it is incompatible with + // multiple cameras on the scene, or multiple instances of the + // LODNode). + bool _fade_mode; + float _fade_start; + int _fade_out; + int _fade_in; + int _previous_child; + public: static void register_with_read_factory(); virtual void write_datagram(BamWriter *manager, Datagram &dg); @@ -72,30 +66,6 @@ protected: static TypedWritable *make_from_bam(const FactoryParams ¶ms); void fillin(DatagramIterator &scan, BamReader *manager); -private: - class EXPCL_PANDA CData : public CycleData { - public: - INLINE CData(); - INLINE CData(const CData ©); - virtual CycleData *make_copy() const; - virtual void write_datagram(BamWriter *manager, Datagram &dg) const; - virtual void fillin(DatagramIterator &scan, BamReader *manager); - - LOD _lod; - float _fade_time; - }; - - PipelineCycler _cycler; - typedef CycleDataReader CDReader; - typedef CycleDataWriter CDWriter; - bool _fade_mode; - float _fade_timer; - int _fade_out; - int _fade_in; - int _previous_child; - - - public: static TypeHandle get_class_type() { return _type_handle; diff --git a/panda/src/pgraph/lodNode.I b/panda/src/pgraph/lodNode.I index c947dd0aff..56f8e7e3f5 100644 --- a/panda/src/pgraph/lodNode.I +++ b/panda/src/pgraph/lodNode.I @@ -16,13 +16,20 @@ // //////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////// // Function: LODNode::CData::Constructor // Access: Public // Description: //////////////////////////////////////////////////////////////////// INLINE LODNode::CData:: -CData() { +CData() : + _center(0.0f, 0.0f, 0.0f), + _lowest(0), + _highest(0), + _got_force_switch(false), + _force_switch(0) +{ } //////////////////////////////////////////////////////////////////// @@ -32,10 +39,105 @@ CData() { //////////////////////////////////////////////////////////////////// INLINE LODNode::CData:: CData(const LODNode::CData ©) : - _lod(copy._lod) + _center(copy._center), + _switch_vector(copy._switch_vector), + _lowest(copy._lowest), + _highest(copy._highest), + _got_force_switch(copy._got_force_switch), + _force_switch(copy._force_switch) { } +//////////////////////////////////////////////////////////////////// +// Function: LODNode::Switch::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE LODNode::Switch:: +Switch(float in, float out) { + set_range(in, out); +} + +//////////////////////////////////////////////////////////////////// +// Function: LODNode::Switch::get_in +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE float LODNode::Switch:: +get_in() const { + return _in; +} + +//////////////////////////////////////////////////////////////////// +// Function: LODNode::Switch::get_out +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE float LODNode::Switch:: +get_out() const { + return _out; +} + +//////////////////////////////////////////////////////////////////// +// Function: LODNode::Switch::set_range +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE void LODNode::Switch:: +set_range(float in, float out) { + _in = in; + _out = out; +} + +//////////////////////////////////////////////////////////////////// +// Function: LODNode::Switch::in_range +// Access: Public +// Description: Computes the distance between two points and returns +// true if the result is within the range for the LOD. +//////////////////////////////////////////////////////////////////// +INLINE bool LODNode::Switch:: +in_range(float dist) const { + return (dist >= _out && dist < _in); +} + +//////////////////////////////////////////////////////////////////// +// Function: LODNode::Switch::rescale +// Access: Public +// Description: Scales the switching distances by the indicated factor. +//////////////////////////////////////////////////////////////////// +INLINE void LODNode::Switch:: +rescale(float factor) { + _in *= factor; + _out *= factor; +} + +//////////////////////////////////////////////////////////////////// +// Function: LODNode::Switch::write_datagram +// Access: Public +// Description: Writes the contents of the Switch out to the +// datagram, presumably in preparation to writing to a +// Bam file. +//////////////////////////////////////////////////////////////////// +INLINE void LODNode::Switch:: +write_datagram(Datagram &destination) const { + destination.add_float32(_in); + destination.add_float32(_out); +} + +//////////////////////////////////////////////////////////////////// +// Function: LODNode::Switch::read_datagram +// Access: Public +// Description: Reads the contents of the Switch from the datagram, +// presumably in response to reading a Bam file. +//////////////////////////////////////////////////////////////////// +INLINE void LODNode::Switch:: +read_datagram(DatagramIterator &source) { + _in = source.get_float32(); + _out = source.get_float32(); +} + + + //////////////////////////////////////////////////////////////////// // Function: LODNode::Constructor // Access: Published @@ -43,7 +145,7 @@ CData(const LODNode::CData ©) : //////////////////////////////////////////////////////////////////// INLINE LODNode:: LODNode(const string &name) : - SelectiveChildNode(name) + PandaNode(name) { } @@ -54,7 +156,7 @@ LODNode(const string &name) : //////////////////////////////////////////////////////////////////// INLINE LODNode:: LODNode(const LODNode ©) : - SelectiveChildNode(copy), + PandaNode(copy), _cycler(copy._cycler) { } @@ -75,7 +177,8 @@ LODNode(const LODNode ©) : INLINE void LODNode:: add_switch(float in, float out) { CDWriter cdata(_cycler); - cdata->_lod._switch_vector.push_back(LODSwitch(in, out)); + cdata->_switch_vector.push_back(Switch(in, out)); + cdata->check_limits(); } //////////////////////////////////////////////////////////////////// @@ -87,8 +190,9 @@ add_switch(float in, float out) { INLINE bool LODNode:: set_switch(int index, float in, float out) { CDWriter cdata(_cycler); - nassertr(index >= 0 && index < (int)cdata->_lod._switch_vector.size(), false); - cdata->_lod._switch_vector[index].set_range(in, out); + nassertr(index >= 0 && index < (int)cdata->_switch_vector.size(), false); + cdata->_switch_vector[index].set_range(in, out); + cdata->check_limits(); return true; } @@ -102,8 +206,9 @@ set_switch(int index, float in, float out) { INLINE void LODNode:: clear_switches(void) { CDWriter cdata(_cycler); - cdata->_lod._switch_vector.erase(cdata->_lod._switch_vector.begin(), - cdata->_lod._switch_vector.end()); + cdata->_switch_vector.clear(); + cdata->_lowest = 0; + cdata->_highest = 0; } //////////////////////////////////////////////////////////////////// @@ -117,7 +222,7 @@ clear_switches(void) { INLINE int LODNode:: get_num_switches() const { CDReader cdata(_cycler); - return cdata->_lod._switch_vector.size(); + return cdata->_switch_vector.size(); } //////////////////////////////////////////////////////////////////// @@ -130,8 +235,8 @@ get_num_switches() const { INLINE float LODNode:: get_in(int index) const { CDReader cdata(_cycler); - nassertr(index >= 0 && index < (int)cdata->_lod._switch_vector.size(), 0.0); - return cdata->_lod._switch_vector[index].get_in(); + nassertr(index >= 0 && index < (int)cdata->_switch_vector.size(), 0.0); + return cdata->_switch_vector[index].get_in(); } //////////////////////////////////////////////////////////////////// @@ -144,8 +249,63 @@ get_in(int index) const { INLINE float LODNode:: get_out(int index) const { CDReader cdata(_cycler); - nassertr(index >= 0 && index < (int)cdata->_lod._switch_vector.size(), 0.0); - return cdata->_lod._switch_vector[index].get_out(); + nassertr(index >= 0 && index < (int)cdata->_switch_vector.size(), 0.0); + return cdata->_switch_vector[index].get_out(); +} + +//////////////////////////////////////////////////////////////////// +// Function: LODNode::get_lowest_switch +// Access: Published +// Description: Returns the index number of the child with the lowest +// level of detail; that is, the one that is designed to +// be seen from the farthest away. This is usually the +// first child, but it is not necessarily so. +//////////////////////////////////////////////////////////////////// +INLINE int LODNode:: +get_lowest_switch() const { + CDReader cdata(_cycler); + return cdata->_lowest; +} + +//////////////////////////////////////////////////////////////////// +// Function: LODNode::get_highest_switch +// Access: Published +// Description: Returns the index number of the child with the highest +// level of detail; that is, the one that is designed to +// be seen from the closest to the camera. This is +// usually the last child, but it is not necessarily so. +//////////////////////////////////////////////////////////////////// +INLINE int LODNode:: +get_highest_switch() const { + CDReader cdata(_cycler); + return cdata->_highest; +} + +//////////////////////////////////////////////////////////////////// +// Function: LODNode::force_switch +// Access: Published +// Description: Forces the LODNode to show the indicated level +// instead of the level that would normally be shown +// based on the distance from the camera. +//////////////////////////////////////////////////////////////////// +INLINE void LODNode:: +force_switch(int index) { + CDWriter cdata(_cycler); + cdata->_force_switch = index; + cdata->_got_force_switch = true; +} + +//////////////////////////////////////////////////////////////////// +// Function: LODNode::clear_force_switch +// Access: Published +// Description: Undoes the effect of a previous call to +// force_switch() and releases the LODNode to once again +// display the normal level. +//////////////////////////////////////////////////////////////////// +INLINE void LODNode:: +clear_force_switch() { + CDWriter cdata(_cycler); + cdata->_got_force_switch = false; } //////////////////////////////////////////////////////////////////// @@ -158,7 +318,7 @@ get_out(int index) const { INLINE void LODNode:: set_center(const LPoint3f ¢er) { CDWriter cdata(_cycler); - cdata->_lod._center = center; + cdata->_center = center; } //////////////////////////////////////////////////////////////////// @@ -171,5 +331,5 @@ set_center(const LPoint3f ¢er) { INLINE const LPoint3f &LODNode:: get_center() const { CDReader cdata(_cycler); - return cdata->_lod._center; + return cdata->_center; } diff --git a/panda/src/pgraph/lodNode.cxx b/panda/src/pgraph/lodNode.cxx index 6a2c578824..5ed22973a7 100644 --- a/panda/src/pgraph/lodNode.cxx +++ b/panda/src/pgraph/lodNode.cxx @@ -32,6 +32,26 @@ make_copy() const { return new CData(*this); } +//////////////////////////////////////////////////////////////////// +// Function: LODNode::CData::check_limits +// Access: Public +// Description: Ensures that the _lowest and _highest members are set +// appropriately after a change to the set of switches. +//////////////////////////////////////////////////////////////////// +void LODNode::CData:: +check_limits() { + _lowest = 0; + _highest = 0; + for (size_t i = 1; i < _switch_vector.size(); ++i) { + if (_switch_vector[i].get_out() > _switch_vector[_lowest].get_out()) { + _lowest = i; + } + if (_switch_vector[i].get_in() < _switch_vector[_highest].get_in()) { + _highest = i; + } + } +} + //////////////////////////////////////////////////////////////////// // Function: LODNode::CData::write_datagram // Access: Public, Virtual @@ -40,7 +60,16 @@ make_copy() const { //////////////////////////////////////////////////////////////////// void LODNode::CData:: write_datagram(BamWriter *manager, Datagram &dg) const { - _lod.write_datagram(dg); + _center.write_datagram(dg); + + dg.add_uint16(_switch_vector.size()); + + SwitchVector::const_iterator si; + for (si = _switch_vector.begin(); + si != _switch_vector.end(); + ++si) { + (*si).write_datagram(dg); + } } //////////////////////////////////////////////////////////////////// @@ -52,7 +81,24 @@ write_datagram(BamWriter *manager, Datagram &dg) const { //////////////////////////////////////////////////////////////////// void LODNode::CData:: fillin(DatagramIterator &scan, BamReader *manager) { - _lod.read_datagram(scan); + _center.read_datagram(scan); + + _switch_vector.clear(); + + int num_switches = scan.get_uint16(); + _switch_vector.reserve(num_switches); + for (int i = 0; i < num_switches; i++) { + Switch sw(0, 0); + sw.read_datagram(scan); + + if (manager->get_file_minor_ver() < 13) { + // Before bam version 4.13, we stored the square of the + // switching distance in the bam files. + sw.set_range(sqrtf(sw.get_in()), sqrtf(sw.get_out())); + } + + _switch_vector.push_back(sw); + } } //////////////////////////////////////////////////////////////////// @@ -93,7 +139,20 @@ safe_to_combine() const { void LODNode:: xform(const LMatrix4f &mat) { CDWriter cdata(_cycler); - cdata->_lod.xform(mat); + + cdata->_center = cdata->_center * mat; + + // We'll take just the length of the y axis as the matrix's scale. + LVector3f y; + mat.get_row3(y, 1); + float factor = y.length(); + + SwitchVector::iterator si; + for (si = cdata->_switch_vector.begin(); + si != cdata->_switch_vector.end(); + ++si) { + (*si).rescale(factor); + } } //////////////////////////////////////////////////////////////////// @@ -131,26 +190,15 @@ has_cull_callback() const { //////////////////////////////////////////////////////////////////// bool LODNode:: cull_callback(CullTraverser *trav, CullTraverserData &data) { - if (data._net_transform->is_singular()) { - // If we're under a singular transform, we can't compute the LOD; - // select none of them instead. - select_child(get_num_children()); - - } else { - CDReader cdata(_cycler); - LPoint3f camera_pos(0, 0, 0); - - // Get the LOD center in camera space - CPT(TransformState) rel_transform = - trav->get_camera_transform()->invert_compose(data._net_transform); - LPoint3f center = cdata->_lod._center * rel_transform->get_mat(); - - // Determine which child to traverse - int index = cdata->_lod.compute_child(camera_pos, center); - select_child(index); + int index = compute_child(trav, data); + if (index >= 0 && index < get_num_children()) { + CullTraverserData next_data(data, get_child(index)); + trav->traverse(next_data); } - return true; + // Now return false indicating that we have already taken care of + // the traversal from here. + return false; } //////////////////////////////////////////////////////////////////// @@ -160,10 +208,90 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) { //////////////////////////////////////////////////////////////////// void LODNode:: output(ostream &out) const { - SelectiveChildNode::output(out); + PandaNode::output(out); CDReader cdata(_cycler); out << " "; - cdata->_lod.output(out); + if (cdata->_switch_vector.empty()) { + out << "no switches."; + } else { + SwitchVector::const_iterator si; + si = cdata->_switch_vector.begin(); + out << "(" << (*si).get_in() << "/" << (*si).get_out() << ")"; + ++si; + while (si != cdata->_switch_vector.end()) { + out << " (" << (*si).get_in() << "/" << (*si).get_out() << ")"; + ++si; + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: LODNode::is_lod_node +// Access: Published, Virtual +// Description: A simple downcast check. Returns true if this kind +// of node happens to inherit from LODNode, false +// otherwise. +// +// This is provided as a a faster alternative to calling +// is_of_type(LODNode::get_class_type()). +//////////////////////////////////////////////////////////////////// +bool LODNode:: +is_lod_node() const { + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: LODNode::compute_child +// Access: Protected +// Description: Determines which child should be visible according to +// the current camera position. If a child is visible, +// returns its index number; otherwise, returns -1. +//////////////////////////////////////////////////////////////////// +int LODNode:: +compute_child(CullTraverser *trav, CullTraverserData &data) { + if (data._net_transform->is_singular()) { + // If we're under a singular transform, we can't compute the LOD; + // select none of them instead. + return -1; + } + + CDReader cdata(_cycler); + + if (cdata->_got_force_switch) { + return cdata->_force_switch; + } + + // Get the LOD center in camera space + // CPT(TransformState) rel_transform = + // trav->get_camera_transform()->invert_compose(data._net_transform); + + CPT(TransformState) rel_transform = + trav->get_scene()->get_cull_center().get_net_transform()-> + invert_compose(data._net_transform); + + LPoint3f center = cdata->_center * rel_transform->get_mat(); + + // Determine which child to traverse + float dist = dot(center, LVector3f::forward()); + + for (int index = 0; index < (int)cdata->_switch_vector.size(); index++) { + if (cdata->_switch_vector[index].in_range(dist)) { + if (pgraph_cat.is_debug()) { + pgraph_cat.debug() + << data._node_path << " at distance " << dist << ", selected child " + << index << "\n"; + } + + return index; + } + } + + if (pgraph_cat.is_debug()) { + pgraph_cat.debug() + << data._node_path << " at distance " << dist << ", no children in range.\n"; + } + + return -1; } //////////////////////////////////////////////////////////////////// @@ -185,7 +313,7 @@ register_with_read_factory() { //////////////////////////////////////////////////////////////////// void LODNode:: write_datagram(BamWriter *manager, Datagram &dg) { - SelectiveChildNode::write_datagram(manager, dg); + PandaNode::write_datagram(manager, dg); manager->write_cdata(dg, _cycler); } @@ -218,6 +346,6 @@ make_from_bam(const FactoryParams ¶ms) { //////////////////////////////////////////////////////////////////// void LODNode:: fillin(DatagramIterator &scan, BamReader *manager) { - SelectiveChildNode::fillin(scan, manager); + PandaNode::fillin(scan, manager); manager->read_cdata(scan, _cycler); } diff --git a/panda/src/pgraph/lodNode.h b/panda/src/pgraph/lodNode.h index 9103435de7..c10bb96076 100644 --- a/panda/src/pgraph/lodNode.h +++ b/panda/src/pgraph/lodNode.h @@ -21,9 +21,7 @@ #include "pandabase.h" -#include "selectiveChildNode.h" - -#include "LOD.h" +#include "pandaNode.h" //////////////////////////////////////////////////////////////////// // Class : LODNode @@ -32,7 +30,7 @@ // from the camera and the table indicated in the // associated LOD object. //////////////////////////////////////////////////////////////////// -class EXPCL_PANDA LODNode : public SelectiveChildNode { +class EXPCL_PANDA LODNode : public PandaNode { PUBLISHED: INLINE LODNode(const string &name); @@ -47,6 +45,8 @@ public: virtual void output(ostream &out) const; + virtual bool is_lod_node() const; + PUBLISHED: // The sense of in vs. out distances is as if the object were coming // towards you from far away: it switches "in" at the far distance, @@ -61,9 +61,62 @@ PUBLISHED: INLINE float get_in(int index) const; INLINE float get_out(int index) const; + INLINE int get_lowest_switch() const; + INLINE int get_highest_switch() const; + + INLINE void force_switch(int index); + INLINE void clear_force_switch(); + INLINE void set_center(const LPoint3f ¢er); INLINE const LPoint3f &get_center() const; +protected: + int compute_child(CullTraverser *trav, CullTraverserData &data); + +protected: + class Switch { + public: + INLINE Switch(float in, float out); + INLINE float get_in() const; + INLINE float get_out() const; + + INLINE void set_range(float in, float out); + INLINE bool in_range(float dist) const; + + INLINE void rescale(float factor); + + INLINE void write_datagram(Datagram &destination) const; + INLINE void read_datagram(DatagramIterator &source); + + private: + float _in; + float _out; + }; + typedef pvector SwitchVector; + + class EXPCL_PANDA CData : public CycleData { + public: + INLINE CData(); + INLINE CData(const CData ©); + virtual CycleData *make_copy() const; + + void check_limits(); + + virtual void write_datagram(BamWriter *manager, Datagram &dg) const; + virtual void fillin(DatagramIterator &scan, BamReader *manager); + + LPoint3f _center; + SwitchVector _switch_vector; + size_t _lowest, _highest; + + bool _got_force_switch; + int _force_switch; + }; + + PipelineCycler _cycler; + typedef CycleDataReader CDReader; + typedef CycleDataWriter CDWriter; + public: static void register_with_read_factory(); virtual void write_datagram(BamWriter *manager, Datagram &dg); @@ -72,30 +125,14 @@ protected: static TypedWritable *make_from_bam(const FactoryParams ¶ms); void fillin(DatagramIterator &scan, BamReader *manager); -private: - class EXPCL_PANDA CData : public CycleData { - public: - INLINE CData(); - INLINE CData(const CData ©); - virtual CycleData *make_copy() const; - virtual void write_datagram(BamWriter *manager, Datagram &dg) const; - virtual void fillin(DatagramIterator &scan, BamReader *manager); - - LOD _lod; - }; - - PipelineCycler _cycler; - typedef CycleDataReader CDReader; - typedef CycleDataWriter CDWriter; - public: static TypeHandle get_class_type() { return _type_handle; } static void init_type() { - SelectiveChildNode::init_type(); + PandaNode::init_type(); register_type(_type_handle, "LODNode", - SelectiveChildNode::get_class_type()); + PandaNode::get_class_type()); } virtual TypeHandle get_type() const { return get_class_type(); diff --git a/panda/src/pgraph/pandaNode.cxx b/panda/src/pgraph/pandaNode.cxx index 3168e93199..5c8e9e7747 100644 --- a/panda/src/pgraph/pandaNode.cxx +++ b/panda/src/pgraph/pandaNode.cxx @@ -1348,6 +1348,21 @@ is_geom_node() const { return false; } +//////////////////////////////////////////////////////////////////// +// Function: PandaNode::is_lod_node +// Access: Published, Virtual +// Description: A simple downcast check. Returns true if this kind +// of node happens to inherit from LODNode, false +// otherwise. +// +// This is provided as a a faster alternative to calling +// is_of_type(LODNode::get_class_type()). +//////////////////////////////////////////////////////////////////// +bool PandaNode:: +is_lod_node() const { + return false; +} + //////////////////////////////////////////////////////////////////// // Function: PandaNode::as_light // Access: Published, Virtual diff --git a/panda/src/pgraph/pandaNode.h b/panda/src/pgraph/pandaNode.h index fe792a8792..4c7fd36f2d 100644 --- a/panda/src/pgraph/pandaNode.h +++ b/panda/src/pgraph/pandaNode.h @@ -193,6 +193,7 @@ PUBLISHED: INLINE const BoundingVolume &get_internal_bound() const; virtual bool is_geom_node() const; + virtual bool is_lod_node() const; virtual Light *as_light(); protected: diff --git a/panda/src/putil/bam.h b/panda/src/putil/bam.h index e710abb721..6abfbceecc 100644 --- a/panda/src/putil/bam.h +++ b/panda/src/putil/bam.h @@ -34,7 +34,7 @@ static const unsigned short _bam_major_ver = 4; // Bumped to major version 3 on 12/8/00 to change float64's to float32's. // Bumped to major version 4 on 4/10/02 to store new scene graph. -static const unsigned short _bam_minor_ver = 12; +static const unsigned short _bam_minor_ver = 13; // Bumped to minor version 1 on 4/10/03 to add CullFaceAttrib::reverse. // Bumped to minor version 1 on 4/10/03 to add CullFaceAttrib::reverse. // Bumped to minor version 2 on 4/12/03 to add num_components to texture. @@ -48,6 +48,7 @@ static const unsigned short _bam_minor_ver = 12; // Bumped to minor version 10 on 04/23/04 to make ComputedVertices use uint32's. // Bumped to minor version 11 on 07/26/04 to add multitexture pointers. // Bumped to minor version 12 on 09/22/04 to add PandaNode::into_collide_mask. +// Bumped to minor version 13 on 09/24/04 to store actual LODNode switch distances instead of squares. #endif diff --git a/panda/src/testbed/Sources.pp b/panda/src/testbed/Sources.pp index a1cafa6bc0..ab5e3b37f1 100644 --- a/panda/src/testbed/Sources.pp +++ b/panda/src/testbed/Sources.pp @@ -33,12 +33,11 @@ #end test_bin_target #begin test_bin_target - #define TARGET test_texmem - #define SOURCES test_texmem.cxx + #define TARGET test_lod + #define SOURCES test_lod.cxx #end test_bin_target #begin test_bin_target - #define TARGET test_particles - - #define SOURCES test_particles.cxx + #define TARGET test_texmem + #define SOURCES test_texmem.cxx #end test_bin_target diff --git a/panda/src/testbed/lod_test.cxx b/panda/src/testbed/lod_test.cxx deleted file mode 100644 index 8d0c711ca5..0000000000 --- a/panda/src/testbed/lod_test.cxx +++ /dev/null @@ -1,54 +0,0 @@ -// Filename: lod_test.cxx -// Created by: -// -//////////////////////////////////////////////////////////////////// -// -// 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 "pandabase.h" -#include "namedNode.h" - -#include "eventHandler.h" -#include "chancfg.h" -#include "textNode.h" -#include "eggLoader.h" -#include "LOD.h" -#include "LODNode.h" -#include "pt_NamedNode.h" - -extern PT_NamedNode render; -extern PT_NamedNode egg_root; -extern EventHandler event_handler; - -extern int framework_main(int argc, char *argv[]); -extern void (*define_keys)(EventHandler&); - -void lod_keys(EventHandler& eh) { - - PT(LODNode) lodnode = new LODNode("lodnode"); - new RenderRelation(egg_root, lodnode); - - PT_NamedNode lodnode0 = loader.load_sync("smiley.egg"); - new RenderRelation(lodnode, lodnode0); - lodnode->add_switch(10, 0); - - PT_NamedNode lodnode1 = loader.load_sync("frowney.egg"); - new RenderRelation(lodnode, lodnode1); - lodnode->add_switch(1000, 10); -} - -int main(int argc, char *argv[]) { - define_keys = &lod_keys; - return framework_main(argc, argv); -} diff --git a/panda/src/testbed/test_lod.cxx b/panda/src/testbed/test_lod.cxx new file mode 100644 index 0000000000..a43a883fb2 --- /dev/null +++ b/panda/src/testbed/test_lod.cxx @@ -0,0 +1,74 @@ +// Filename: test_lod.cxx +// Created by: drose (24Sep04) +// +//////////////////////////////////////////////////////////////////// +// +// 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 "pandaFramework.h" +#include "lodNode.h" +#include "fadeLodNode.h" +#include "loader.h" + +PandaFramework framework; + +char *filename_a = "smiley"; +char *filename_b = "frowney"; + +void +create_lod_node(NodePath &models, const char *a, const char *b) { + Loader loader; + PT(PandaNode) smiley = loader.load_sync(a); + PT(PandaNode) frowney = loader.load_sync(b); + + PT(LODNode) lod = new FadeLODNode("lod"); + //PT(LODNode) lod = new LODNode("lod"); + if (!smiley.is_null()) { + lod->add_child(smiley); + lod->add_switch(10, 0); + } + if (!frowney.is_null()) { + lod->add_child(frowney); + lod->add_switch(1000, 10); + } + + models.attach_new_node(lod); +} + + +int +main(int argc, char *argv[]) { + framework.open_framework(argc, argv); + framework.set_window_title("LOD Test"); + + WindowFramework *window = framework.open_window(); + if (window != (WindowFramework *)NULL) { + // We've successfully opened a window. + + window->enable_keyboard(); + window->setup_trackball(); + framework.get_models().instance_to(window->get_render()); + + create_lod_node(framework.get_models(), + argc > 1 ? argv[1] : filename_a, + argc > 2 ? argv[2] : filename_b); + + window->center_trackball(framework.get_models()); + + framework.enable_default_keys(); + framework.main_loop(); + } + + return (0); +} diff --git a/panda/src/testbed/test_particles.cxx b/panda/src/testbed/test_particles.cxx deleted file mode 100644 index ffd8994c45..0000000000 --- a/panda/src/testbed/test_particles.cxx +++ /dev/null @@ -1,649 +0,0 @@ -// Filename: test_particles.cxx -// Created by: -// -//////////////////////////////////////////////////////////////////// -// -// 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 "framework.h" - -#include "eventHandler.h" -#include "chancfg.h" -#include -#include "renderModeTransition.h" -#include "colorTransition.h" -#include "cullFaceTransition.h" -#include "depthTestTransition.h" -#include "depthWriteTransition.h" -#include "textureTransition.h" -#include "lightTransition.h" -#include "materialTransition.h" -#include "transformTransition.h" -#include "get_rel_pos.h" -#include "boundingSphere.h" -#include "geomSphere.h" -#include "geomNode.h" -#include "notify.h" -#include "directionalLight.h" -#include "renderRelation.h" -#include "camera.h" -#include "frustum.h" -#include "orthoProjection.h" -#include "perspectiveProjection.h" -#include "textNode.h" -#include "physicsManager.h" -#include "particleSystem.h" -#include "emitters.h" -#include "particlefactories.h" -#include "forces.h" -#include "sparkleParticleRenderer.h" -#include "pointParticleRenderer.h" -#include "lineParticleRenderer.h" -#include "geomParticleRenderer.h" -#include "spriteParticleRenderer.h" -#include "colorTransition.h" -#include "particleSystemManager.h" -#include "clockObject.h" -#include "nodePath.h" -#include "pointShapeTransition.h" -#include "texture.h" -#include "texturePool.h" -#include "physicalNode.h" -#include "forceNode.h" -#include "linearEulerIntegrator.h" - -// physics. particle systems. - -///////////////////////////////////////////////// - -// particle system manager params -#define PARTICLE_SYSTEM_MANAGER_FRAME_STEPPING 1 - -// particle system params -#define PARTICLE_SYSTEM_POOL_SIZE 1000 -#define PARTICLE_SYSTEM_BIRTH_RATE 0.01f -//#define PARTICLE_SYSTEM_BIRTH_RATE 0.5f -#define PARTICLE_SYSTEM_LITTER_SIZE 10 -#define PARTICLE_SYSTEM_LITTER_SPREAD 0 - - -//#define WIND_FORCE 0.5, 0, 0 -//#define NOISE_FORCE 0.02f - -///////////////////////////////////////////////// - -// particle factory selection -#define POINT_PARTICLES -//#define ZSPIN_PARTICLES -//#define ORIENTED_PARTICLES - -// particle renderer selection -//#define POINT_PARTICLE_RENDERER -#define LINE_PARTICLE_RENDERER -//#define SPARKLE_PARTICLE_RENDERER -//#define SPRITE_PARTICLE_RENDERER -//#define GEOM_PARTICLE_RENDERER - -// particle emitter selection -//#define BOX_EMITTER -//#define DISC_EMITTER -//#define LINE_EMITTER -//#define POINT_EMITTER -//#define RECTANGLE_EMITTER -//#define RING_EMITTER -//#define SPHERE_SURFACE_EMITTER -#define SPHERE_VOLUME_EMITTER -//#define TANGENT_RING_EMITTER - -///////////////////////////////////////////////// - -// particle factory params -#define PARTICLE_FACTORY_LIFESPAN_BASE 5.0f -//#define PARTICLE_FACTORY_LIFESPAN_BASE 3.0f -//#define PARTICLE_FACTORY_LIFESPAN_SPREAD 1.0f -//#define PARTICLE_FACTORY_MASS_BASE 1.0f -//#define PARTICLE_FACTORY_MASS_SPREAD 0.2f -//#define PARTICLE_FACTORY_TERMINAL_VELOCITY_BASE PhysicsObject::_default_terminal_velocity -//#define PARTICLE_FACTORY_TERMINAL_VELOCITY_SPREAD 0.0f - -#ifdef ZSPIN_PARTICLES - #define ZSPIN_PARTICLES_INITIAL_ANGLE 0.0f - #define ZSPIN_PARTICLES_FINAL_ANGLE 0.0f - #define ZSPIN_PARTICLES_INITIAL_ANGLE_SPREAD 90.0f - #define ZSPIN_PARTICLES_FINAL_ANGLE_SPREAD 90.0f -#endif - -// particle renderer params -#define SPRITE_PARTICLE_RENDERER_ALPHA_DISABLE false -#define PARTICLE_RENDERER_ALPHA_MODE BaseParticleRenderer::PR_ALPHA_NONE -//#define PARTICLE_RENDERER_ALPHA_MODE BaseParticleRenderer::PR_ALPHA_IN -//#define PARTICLE_RENDERER_ALPHA_MODE BaseParticleRenderer::PR_ALPHA_OUT -//#define PARTICLE_RENDERER_ALPHA_MODE BaseParticleRenderer::PR_ALPHA_USER -//#define PARTICLE_RENDERER_USER_ALPHA 1.0 - -#ifdef GEOM_PARTICLE_RENDERER -#elif defined POINT_PARTICLE_RENDERER - #define POINT_PARTICLE_RENDERER_POINT_SIZE 1.0f -// #define POINT_PARTICLE_RENDERER_STARTCOLOR Colorf(1.0f, 0.0f, 0.0f, 1.0f) -// #define POINT_PARTICLE_RENDERER_ENDCOLOR Colorf(1.0f, 1.0f, 0.0f, 1.0f) -// #define POINT_PARTICLE_RENDERER_BLEND_TYPE BaseParticleRenderer::PP_BLEND_LIFE -// #define POINT_PARTICLE_RENDERER_BLEND_METHOD BaseParticleRenderer::PP_BLEND_LINEAR -// #define POINT_PARTICLE_RENDERER_BLEND_METHOD BaseParticleRenderer::PP_BLEND_CUBIC - -#elif defined LINE_PARTICLE_RENDERER - #define LINE_PARTICLE_RENDERER_HEAD_COLOR Colorf(1.0f, 1.0f, 1.0f, 1.0f) - #define LINE_PARTICLE_RENDERER_TAIL_COLOR Colorf(1.0f, 1.0f, 1.0f, 1.0f) -#elif defined SPARKLE_PARTICLE_RENDERER -// #define SPARKLE_PARTICLE_RENDERER_CENTER_COLOR Colorf(1.0f, 0.0f, 0.0f, 1.0f) -// #define SPARKLE_PARTICLE_RENDERER_EDGE_COLOR Colorf(0.0f, 0.0f, 1.0f, 1.0f) -// #define SPARKLE_PARTICLE_RENDERER_BIRTH_RADIUS 0.004f -// #define SPARKLE_PARTICLE_RENDERER_DEATH_RADIUS 1.0f -// #define SPARKLE_PARTICLE_RENDERER_LIFE_SCALE SP_SCALE -#elif defined SPRITE_PARTICLE_RENDERER -// #define SPRITE_PARTICLE_RENDERER_TEXTURE_FILE "smoke.rgba" -// #define SPRITE_PARTICLE_RENDERER_TEXTURE_FILE "lilsmiley.rgba" - #define SPRITE_PARTICLE_RENDERER_TEXTURE_FILE "rock-floor.rgb" - #define SPRITE_PARTICLE_RENDERER_COLOR Colorf(1.0f, 1.0f, 1.0f, 1.0f) -// #define SPRITE_PARTICLE_RENDERER_X_SCALE_FLAG true -// #define SPRITE_PARTICLE_RENDERER_Y_SCALE_FLAG true - #define SPRITE_PARTICLE_RENDERER_ANIM_ANGLE_FLAG true -// #define SPRITE_PARTICLE_RENDERER_INITIAL_X_SCALE 0.1 -// #define SPRITE_PARTICLE_RENDERER_FINAL_X_SCALE 0.0 -// #define SPRITE_PARTICLE_RENDERER_INITIAL_Y_SCALE 0.0 -// #define SPRITE_PARTICLE_RENDERER_FINAL_Y_SCALE 0.5 - #define SPRITE_PARTICLE_RENDERER_NONANIMATED_THETA 45.0f - #define SPRITE_PARTICLE_RENDERER_BLEND_METHOD BaseParticleRenderer::PP_BLEND_LINEAR -// #define SPRITE_PARTICLE_RENDERER_BLEND_METHOD BaseParticleRenderer::PP_BLEND_CUBIC -// #define SPRITE_PARTICLE_RENDERER_ALPHA_DISABLE false -#endif - -// particle emitter params - -#define EMISSION_TYPE_EXPLICIT -//#define EMISSION_TYPE_RADIATE -//#define EMISSION_TYPE_CUSTOM - -//#define EMITTER_AMPLITUDE 10.0 -#define EMITTER_AMPLITUDE 1.0 -//#define EMITTER_AMPLITUDE 0.5 -//#define EMITTER_AMPLITUDE_SPREAD 2.0 -//#define EMITTER_OFFSET_FORCE LVector3f(1.0, 1.0, 1.0) - -#if defined EMISSION_TYPE_EXPLICIT - #define EXPLICIT_LAUNCH_VEC LVector3f(-1.0f, -1.0f, 1.0f) -// #define EXPLICIT_LAUNCH_VEC LVector3f(0.0f, 0.0f, 0.0f) -#elif defined EMISSION_TYPE_RADIATE -// #define RADIATE_ORIGIN LPoint3f(0.0f, 0.0f, 0.5f) - #define RADIATE_ORIGIN LPoint3f(0.0f, 0.0f, 0.0f) -#endif - -#ifdef BOX_EMITTER - #define BOX_EMITTER_MINBOUND LPoint3f(-1.0f, -1.0f, -1.0f) - #define BOX_EMITTER_MAXBOUND LPoint3f(1.0f, 1.0f, 1.0f) -#elif defined DISC_EMITTER - #define DISC_EMITTER_RADIUS 1.0f - #ifdef EMISSION_TYPE_CUSTOM - #define DISC_EMITTER_OUTER_ANGLE 45.0f - #define DISC_EMITTER_INNER_ANGLE 90.0f - #define DISC_EMITTER_OUTER_MAGNITUDE 1.5f - #define DISC_EMITTER_INNER_MAGNITUDE 1.5f - #define DISC_EMITTER_CUBIC_LERPING false - #endif -#elif defined LINE_EMITTER - #define LINE_EMITTER_ENDPOINT1 LPoint3f(-2.0f, 0.0f, 2.0f) - #define LINE_EMITTER_ENDPOINT2 LPoint3f(2.0f, 0.0f, 2.0f) -#elif defined POINT_EMITTER - #define POINT_EMITTER_LOCATION LPoint3f(1.0f, 1.0f, 1.0f) -#elif defined RECTANGLE_EMITTER - #define RECTANGLE_EMITTER_MINBOUND LPoint2f(-1.0f, -1.0f) - #define RECTANGLE_EMITTER_MAXBOUND LPoint2f(1.0f, 1.0f) -#elif defined RING_EMITTER - #define RING_EMITTER_RADIUS 0.5f - #ifdef EMISSION_TYPE_CUSTOM - #define RING_EMITTER_ANGLE 90.0f - #endif -#elif defined SPHERE_SURFACE_EMITTER - #define SPHERE_SURFACE_EMITTER_RADIUS 1.0f -#elif defined SPHERE_VOLUME_EMITTER - #define SPHERE_VOLUME_EMITTER_RADIUS 1.0f -#elif defined TANGENT_RING_EMITTER - #define TANGENT_RING_EMITTER_RADIUS 1.0f -#endif - -///////////////////////////////////////////////// - - -PhysicsManager physics_manager; -ParticleSystemManager ps_manager; - -PT(ParticleSystem) particle_system = new ParticleSystem(PARTICLE_SYSTEM_POOL_SIZE); - -static int particles_added = 0; - -/* -#if defined POINT_PARTICLES - PT(PointParticleFactory) pf = new PointParticleFactory; -#elif defined ZSPIN_PARTICLES - PT(ZSpinParticleFactory) pf = new ZSpinParticleFactory; -#elif defined ORIENTED_PARTICLES - PT(OrientedParticleFactory) pf = new OrientedParticleFactory; -#endif -*/ -#if defined POINT_PARTICLES - PT(BaseParticleFactory) pf = new PointParticleFactory; -#elif defined ZSPIN_PARTICLES - PT(BaseParticleFactory) pf = new ZSpinParticleFactory; -#elif defined ORIENTED_PARTICLES - PT(BaseParticleFactory) pf = new OrientedParticleFactory; -#endif - -#if defined GEOM_PARTICLE_RENDERER - PT(GeomParticleRenderer) pr = new GeomParticleRenderer; -#elif defined POINT_PARTICLE_RENDERER - PT(PointParticleRenderer) pr = new PointParticleRenderer; -#elif defined LINE_PARTICLE_RENDERER - PT(LineParticleRenderer) pr = new LineParticleRenderer; -#elif defined SPARKLE_PARTICLE_RENDERER - PT(SparkleParticleRenderer) pr = new SparkleParticleRenderer; -#elif defined SPRITE_PARTICLE_RENDERER - PT(SpriteParticleRenderer) pr = new SpriteParticleRenderer; -#endif - -#if defined BOX_EMITTER - PT(BoxEmitter) pe = new BoxEmitter; -#elif defined DISC_EMITTER - PT(DiscEmitter) pe = new DiscEmitter; -#elif defined LINE_EMITTER - PT(LineEmitter) pe = new LineEmitter; -#elif defined POINT_EMITTER - PT(PointEmitter) pe = new PointEmitter; -#elif defined RECTANGLE_EMITTER - PT(RectangleEmitter) pe = new RectangleEmitter; -#elif defined RING_EMITTER - PT(RingEmitter) pe = new RingEmitter; -#elif defined SPHERE_SURFACE_EMITTER - PT(SphereSurfaceEmitter) pe = new SphereSurfaceEmitter; -#elif defined TANGENT_RING_EMITTER - PT(TangentRingEmitter) pe = new TangentRingEmitter; -#elif defined SPHERE_VOLUME_EMITTER - PT(SphereVolumeEmitter) pe = new SphereVolumeEmitter; -#endif - -PT(Texture) texture; - -#ifdef WIND_FORCE -PT(LinearVectorForce) wind_force = new LinearVectorForce(WIND_FORCE); -#endif -#ifdef NOISE_FORCE -PT(LinearNoiseForce) noise_force = new LinearNoiseForce(NOISE_FORCE); -#endif - -PT(PhysicalNode) pn = new PhysicalNode; -PT(ForceNode) fn = new ForceNode; - -static void -event_csn_update(CPT_Event) { - float dt = ClockObject::get_global_clock()->get_dt(); - - physics_manager.do_physics(dt); - ps_manager.do_particles(dt); -} - -static void -event_add_particles(CPT_Event) { - - // guard against additional "P" presses (bad things happen) - if(particles_added) return; - particles_added = 1; - - // renderer setup - #ifdef PARTICLE_RENDERER_ALPHA_MODE - pr->set_alpha_mode(PARTICLE_RENDERER_ALPHA_MODE); - #endif - #ifdef PARTICLE_RENDERER_USER_ALPHA - pr->set_user_alpha(PARTICLE_RENDERER_USER_ALPHA); - #endif - - #ifdef GEOM_PARTICLE_RENDERER - #elif defined POINT_PARTICLE_RENDERER - #ifdef POINT_PARTICLE_RENDERER_POINT_SIZE - pr->set_point_size(POINT_PARTICLE_RENDERER_POINT_SIZE); - #endif - #ifdef POINT_PARTICLE_RENDERER_STARTCOLOR - pr->set_color1(POINT_PARTICLE_RENDERER_STARTCOLOR); - #endif - #ifdef POINT_PARTICLE_RENDERER_ENDCOLOR - pr->set_color2(POINT_PARTICLE_RENDERER_ENDCOLOR); - #endif - #ifdef POINT_PARTICLE_RENDERER_BLEND_TYPE - pr->set_blend_type(POINT_PARTICLE_RENDERER_BLEND_TYPE); - #endif - #ifdef POINT_PARTICLE_RENDERER_BLEND_METHOD - pr->set_blend_method(POINT_PARTICLE_RENDERER_BLEND_METHOD); - #endif - #elif defined LINE_PARTICLE_RENDERER - #ifdef LINE_PARTICLE_RENDERER_HEAD_COLOR - pr->set_head_color(LINE_PARTICLE_RENDERER_HEAD_COLOR); - #endif - #ifdef LINE_PARTICLE_RENDERER_TAIL_COLOR - pr->set_tail_color(LINE_PARTICLE_RENDERER_TAIL_COLOR); - #endif - #elif defined SPARKLE_PARTICLE_RENDERER - #ifdef SPARKLE_PARTICLE_RENDERER_CENTER_COLOR - pr->set_center_color(SPARKLE_PARTICLE_RENDERER_CENTER_COLOR); - #endif - #ifdef SPARKLE_PARTICLE_RENDERER_EDGE_COLOR - pr->set_edge_color(SPARKLE_PARTICLE_RENDERER_EDGE_COLOR); - #endif - #ifdef SPARKLE_PARTICLE_RENDERER_LIFE_SCALE - pr->set_life_scale(SPARKLE_PARTICLE_RENDERER_LIFE_SCALE); - #endif - #ifdef SPARKLE_PARTICLE_RENDERER_BIRTH_RADIUS - pr->set_birth_mag(SPARKLE_PARTICLE_RENDERER_BIRTH_RADIUS); - #endif - #ifdef SPARKLE_PARTICLE_RENDERER_DEATH_RADIUS - pr->set_death_mag(SPARKLE_PARTICLE_RENDERER_DEATH_RADIUS); - #endif - #elif defined SPRITE_PARTICLE_RENDERER - pr->set_texture(texture); - #ifdef SPRITE_PARTICLE_RENDERER_COLOR - pr->set_color(SPRITE_PARTICLE_RENDERER_COLOR); - #endif - #ifdef SPRITE_PARTICLE_RENDERER_X_SCALE_FLAG - pr->set_x_scale_flag(SPRITE_PARTICLE_RENDERER_X_SCALE_FLAG); - #endif - #ifdef SPRITE_PARTICLE_RENDERER_Y_SCALE_FLAG - pr->set_y_scale_flag(SPRITE_PARTICLE_RENDERER_Y_SCALE_FLAG); - #endif - #ifdef SPRITE_PARTICLE_RENDERER_ANIM_ANGLE_FLAG - pr->set_anim_angle_flag(SPRITE_PARTICLE_RENDERER_ANIM_ANGLE_FLAG); - #endif - #ifdef SPRITE_PARTICLE_RENDERER_INITIAL_X_SCALE - pr->set_initial_x_scale(SPRITE_PARTICLE_RENDERER_INITIAL_X_SCALE); - #endif - #ifdef SPRITE_PARTICLE_RENDERER_FINAL_X_SCALE - pr->set_final_x_scale(SPRITE_PARTICLE_RENDERER_FINAL_X_SCALE); - #endif - #ifdef SPRITE_PARTICLE_RENDERER_INITIAL_Y_SCALE - pr->set_initial_y_scale(SPRITE_PARTICLE_RENDERER_INITIAL_Y_SCALE); - #endif - #ifdef SPRITE_PARTICLE_RENDERER_FINAL_Y_SCALE - pr->set_final_y_scale(SPRITE_PARTICLE_RENDERER_FINAL_Y_SCALE); - #endif - #ifdef SPRITE_PARTICLE_RENDERER_NONANIMATED_THETA - pr->set_nonanimated_theta(SPRITE_PARTICLE_RENDERER_NONANIMATED_THETA); - #endif - #ifdef SPRITE_PARTICLE_RENDERER_BLEND_METHOD - pr->set_alpha_blend_method(SPRITE_PARTICLE_RENDERER_BLEND_METHOD); - #endif - #ifdef SPRITE_PARTICLE_RENDERER_ALPHA_DISABLE - pr->set_alpha_disable(SPRITE_PARTICLE_RENDERER_ALPHA_DISABLE); - #endif - #endif - - // factory setup - - #ifdef PARTICLE_FACTORY_LIFESPAN_BASE - pf->set_lifespan_base(PARTICLE_FACTORY_LIFESPAN_BASE); - #endif - #ifdef PARTICLE_FACTORY_LIFESPAN_SPREAD - pf->set_lifespan_spread(PARTICLE_FACTORY_LIFESPAN_SPREAD); - #endif - #ifdef PARTICLE_FACTORY_MASS_BASE - pf->set_mass_base(PARTICLE_FACTORY_MASS_BASE); - #endif - #ifdef PARTICLE_FACTORY_MASS_SPREAD - pf->set_mass_spread(PARTICLE_FACTORY_MASS_SPREAD); - #endif - #ifdef PARTICLE_FACTORY_TERMINAL_VELOCITY_BASE - pf->set_terminal_velocity_base(PARTICLE_FACTORY_TERMINAL_VELOCITY_BASE); - #endif - #ifdef PARTICLE_FACTORY_TERMINAL_VELOCITY_SPREAD - pf->set_terminal_velocity_spread(PARTICLE_FACTORY_TERMINAL_VELOCITY_SPREAD); - #endif - - #if defined ZSPIN_PARTICLES - #ifdef ZSPIN_PARTICLES_INITIAL_ANGLE - pf->set_initial_angle(ZSPIN_PARTICLES_INITIAL_ANGLE); - #endif - #ifdef ZSPIN_PARTICLES_FINAL_ANGLE - pf->set_final_angle(ZSPIN_PARTICLES_FINAL_ANGLE); - #endif - #ifdef ZSPIN_PARTICLES_INITIAL_ANGLE_SPREAD - pf->set_initial_angle_spread(ZSPIN_PARTICLES_INITIAL_ANGLE_SPREAD); - #endif - #ifdef ZSPIN_PARTICLES_FINAL_ANGLE_SPREAD - pf->set_final_angle_spread(ZSPIN_PARTICLES_FINAL_ANGLE_SPREAD); - #endif - #elif defined ORIENTED_PARTICLES - #endif - - // emitter setup - #ifdef EMITTER_AMPLITUDE - pe->set_amplitude(EMITTER_AMPLITUDE); - #endif - #ifdef EMITTER_AMPLITUDE_SPREAD - pe->set_amplitude_spread(EMITTER_AMPLITUDE_SPREAD); - #endif - #ifdef EMITTER_OFFSET_FORCE - pe->set_offset_force(EMITTER_OFFSET_FORCE); - #endif - - #if defined EMISSION_TYPE_EXPLICIT - pe->set_emission_type(BaseParticleEmitter::ET_EXPLICIT); - #ifdef EXPLICIT_LAUNCH_VEC - pe->set_explicit_launch_vector(EXPLICIT_LAUNCH_VEC); - #endif - #elif defined EMISSION_TYPE_RADIATE - pe->set_emission_type(BaseParticleEmitter::ET_RADIATE); - #ifdef RADIATE_ORIGIN - pe->set_radiate_origin(RADIATE_ORIGIN); - #endif - #elif defined EMISSION_TYPE_CUSTOM - pe->set_emission_type(BaseParticleEmitter::ET_CUSTOM); - #endif - - #ifdef BOX_EMITTER - #ifdef BOX_EMITTER_MINBOUND - pe->set_min_bound(BOX_EMITTER_MINBOUND); - #endif - #ifdef BOX_EMITTER_MAXBOUND - pe->set_max_bound(BOX_EMITTER_MAXBOUND); - #endif - #elif defined DISC_EMITTER - #ifdef DISC_EMITTER_RADIUS - pe->set_radius(DISC_EMITTER_RADIUS); - #endif - #ifdef EMISSION_TYPE_CUSTOM - #ifdef DISC_EMITTER_OUTER_ANGLE - pe->set_outer_angle(DISC_EMITTER_OUTER_ANGLE); - #endif - #ifdef DISC_EMITTER_INNER_ANGLE - pe->set_inner_angle(DISC_EMITTER_INNER_ANGLE); - #endif - #ifdef DISC_EMITTER_OUTER_MAGNITUDE - pe->set_outer_magnitude(DISC_EMITTER_OUTER_MAGNITUDE); - #endif - #ifdef DISC_EMITTER_INNER_MAGNITUDE - pe->set_inner_magnitude(DISC_EMITTER_INNER_MAGNITUDE); - #endif - #ifdef DISC_EMITTER_CUBIC_LERPING - pe->set_cubic_lerping(DISC_EMITTER_CUBIC_LERPING); - #endif - #endif - #elif defined LINE_EMITTER - #ifdef LINE_EMITTER_ENDPOINT1 - pe->set_endpoint1(LINE_EMITTER_ENDPOINT1); - #endif - #ifdef LINE_EMITTER_ENDPOINT2 - pe->set_endpoint2(LINE_EMITTER_ENDPOINT2); - #endif - #elif defined POINT_EMITTER - #ifdef POINT_EMITTER_LOCATION - pe->set_location(POINT_EMITTER_LOCATION); - #endif - #elif defined RECTANGLE_EMITTER - #ifdef RECTANGLE_EMITTER_MINBOUND - pe->set_min_bound(RECTANGLE_EMITTER_MINBOUND); - #endif - #ifdef RECTANGLE_EMITTER_MAXBOUND - pe->set_max_bound(RECTANGLE_EMITTER_MAXBOUND); - #endif - #elif defined RING_EMITTER - #ifdef RING_EMITTER_RADIUS - pe->set_radius(RING_EMITTER_RADIUS); - #endif - #ifdef EMISSION_TYPE_CUSTOM - #ifdef RING_EMITTER_ANGLE - pe->set_aoe(RING_EMITTER_ANGLE); - #endif - #endif - #elif defined SPHERE_SURFACE_EMITTER - #ifdef SPHERE_SURFACE_EMITTER_RADIUS - pe->set_radius(SPHERE_SURFACE_EMITTER_RADIUS); - #endif - #elif defined TANGENT_RING_EMITTER - #ifdef TANGENT_RING_EMITTER_RADIUS - pe->set_radius(TANGENT_RING_EMITTER_RADIUS); - #endif - #elif defined SPHERE_VOLUME_EMITTER - #ifdef SPHERE_VOLUME_EMITTER_RADIUS - pe->set_radius(SPHERE_VOLUME_EMITTER_RADIUS); - #endif - #endif // emitter type - - // system setup - particle_system->set_birth_rate(PARTICLE_SYSTEM_BIRTH_RATE); - particle_system->set_litter_size(PARTICLE_SYSTEM_LITTER_SIZE); - particle_system->set_litter_spread(PARTICLE_SYSTEM_LITTER_SPREAD); - particle_system->set_emitter(pe); - particle_system->set_renderer(pr); - particle_system->set_factory(pf); - - particle_system->set_render_parent(render); - - pn->add_physical(particle_system); - new RenderRelation(render, pn); - -#ifdef WIND_FORCE - fn->add_force(wind_force); -#endif -#ifdef NOISE_FORCE - fn->add_force(noise_force); -#endif - new RenderRelation(render, fn); - - physics_manager.attach_linear_integrator(new LinearEulerIntegrator); - physics_manager.attach_physical(particle_system); -#ifdef WIND_FORCE - physics_manager.add_linear_force(wind_force); -#endif - -#ifdef PARTICLE_SYSTEM_MANAGER_FRAME_STEPPING - ps_manager.set_frame_stepping(PARTICLE_SYSTEM_MANAGER_FRAME_STEPPING); -#endif - ps_manager.attach_particlesystem(particle_system); - -#ifdef NOISE_FORCE - particle_system->add_linear_force(noise_force); -#endif - - nout << "Added particles." << endl; - event_handler.add_hook("NewFrame", event_csn_update); -} - -static void set_pool_size(int size) { - nout << "setting pool size to " << size << endl; - particle_system->set_pool_size(size); -} - -static void -event_more_particles(CPT_Event) { - static int index = 0; - static int sizes[] = { - 10, - 999, - 998, - 999, - 1000, - 1001, - 1002, - 1003, - 1004, - 1000, - 16*1000, - 4*1000, - 3*1000, - 2*1000, - 1000, - 0, - }; - - if(!particles_added) return; - - if (0 == sizes[index]) index = 0; - set_pool_size(sizes[index]); - index++; -} - -static void -event_switch_particle_factory_type(CPT_Event) { - static int index = 0; - - if(!particles_added) return; - - cout << "Switching to a"; - - switch (index) { - case 0: - cout << " point"; - pf = new PointParticleFactory; - particle_system->set_factory(pf); - break; - case 1: - cout << " z-spin"; - pf = new ZSpinParticleFactory; - particle_system->set_factory(pf); - break; - case 2: - cout << "n oriented"; - pf = new OrientedParticleFactory; - particle_system->set_factory(pf); - break; - } - - cout << " particle factory" << endl; - - index++; - if (index > 2) index = 0; -} - -void demo_keys(EventHandler&) { - new RenderRelation( lights, dlight ); - have_dlight = true; - - event_handler.add_hook("p", event_add_particles); - event_handler.add_hook("m", event_more_particles); - event_handler.add_hook(",", event_switch_particle_factory_type); -} - -int main(int argc, char *argv[]) { - define_keys = &demo_keys; - -#ifdef SPRITE_PARTICLE_RENDERER - texture = TexturePool::load_texture(SPRITE_PARTICLE_RENDERER_TEXTURE_FILE); -#endif - - return framework_main(argc, argv); -}