Support collision solids under LOD nodes

This commit is contained in:
David Rose 2004-09-27 20:29:41 +00:00
parent c0fffac008
commit d850afd71a
23 changed files with 618 additions and 1681 deletions

View File

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

View File

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

View File

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

View File

@ -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 <math.h>
////////////////////////////////////////////////////////////////////
// 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 &copy) :
_in(copy._in),
_out(copy._out)
{
}
////////////////////////////////////////////////////////////////////
// Function: LODSwitch::Copy Assignment Operator
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE void LODSwitch::
operator = (const LODSwitch &copy) {
_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();
}

View File

@ -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 &copy) :
_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 &center) 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;
}

View File

@ -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 &copy);
INLINE void operator = (const LODSwitch &copy);
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<LODSwitch>, 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 &copy);
~LOD();
void xform(const LMatrix4f &mat);
int compute_child(const LPoint3f &cam_pos,
const LPoint3f &center) 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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 &copy) :
_lod(copy._lod) {
_fade_time = copy._fade_time;
}
////////////////////////////////////////////////////////////////////
// Function: FadeLODNode::Constructor
// Access: Published
@ -44,7 +23,9 @@ CData(const FadeLODNode::CData &copy) :
////////////////////////////////////////////////////////////////////
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 &copy) :
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 &center) {
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;
}

View File

@ -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 &params) {
////////////////////////////////////////////////////////////////////
void FadeLODNode::
fillin(DatagramIterator &scan, BamReader *manager) {
PandaNode::fillin(scan, manager);
manager->read_cdata(scan, _cycler);
LODNode::fillin(scan, manager);
}

View File

@ -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 &copy);
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 &center);
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 &params);
void fillin(DatagramIterator &scan, BamReader *manager);
private:
class EXPCL_PANDA CData : public CycleData {
public:
INLINE CData();
INLINE CData(const CData &copy);
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<CData> _cycler;
typedef CycleDataReader<CData> CDReader;
typedef CycleDataWriter<CData> 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;

View File

@ -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 &copy) :
_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 &copy) :
////////////////////////////////////////////////////////////////////
INLINE LODNode::
LODNode(const string &name) :
SelectiveChildNode(name)
PandaNode(name)
{
}
@ -54,7 +156,7 @@ LODNode(const string &name) :
////////////////////////////////////////////////////////////////////
INLINE LODNode::
LODNode(const LODNode &copy) :
SelectiveChildNode(copy),
PandaNode(copy),
_cycler(copy._cycler)
{
}
@ -75,7 +177,8 @@ LODNode(const LODNode &copy) :
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 &center) {
CDWriter cdata(_cycler);
cdata->_lod._center = center;
cdata->_center = center;
}
////////////////////////////////////////////////////////////////////
@ -171,5 +331,5 @@ set_center(const LPoint3f &center) {
INLINE const LPoint3f &LODNode::
get_center() const {
CDReader cdata(_cycler);
return cdata->_lod._center;
return cdata->_center;
}

View File

@ -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 &params) {
////////////////////////////////////////////////////////////////////
void LODNode::
fillin(DatagramIterator &scan, BamReader *manager) {
SelectiveChildNode::fillin(scan, manager);
PandaNode::fillin(scan, manager);
manager->read_cdata(scan, _cycler);
}

View File

@ -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 &center);
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<Switch> SwitchVector;
class EXPCL_PANDA CData : public CycleData {
public:
INLINE CData();
INLINE CData(const CData &copy);
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<CData> _cycler;
typedef CycleDataReader<CData> CDReader;
typedef CycleDataWriter<CData> 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 &params);
void fillin(DatagramIterator &scan, BamReader *manager);
private:
class EXPCL_PANDA CData : public CycleData {
public:
INLINE CData();
INLINE CData(const CData &copy);
virtual CycleData *make_copy() const;
virtual void write_datagram(BamWriter *manager, Datagram &dg) const;
virtual void fillin(DatagramIterator &scan, BamReader *manager);
LOD _lod;
};
PipelineCycler<CData> _cycler;
typedef CycleDataReader<CData> CDReader;
typedef CycleDataWriter<CData> 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();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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