Checked in osgParticle, writtten by Marco Jez.
This commit is contained in:
16
src/Demos/osgparticle/Makefile
Normal file
16
src/Demos/osgparticle/Makefile
Normal file
@@ -0,0 +1,16 @@
|
||||
TOPDIR = ../../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgparticle.cpp\
|
||||
|
||||
LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS) -losgParticle
|
||||
|
||||
INSTFILES = \
|
||||
$(CXXFILES)\
|
||||
Makefile.inst=Makefile
|
||||
|
||||
EXEC = osgparticle
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
|
||||
13
src/Demos/osgparticle/Makefile.inst
Normal file
13
src/Demos/osgparticle/Makefile.inst
Normal file
@@ -0,0 +1,13 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
osgparticle.cpp\
|
||||
|
||||
LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS) -losgParticle
|
||||
|
||||
EXEC = osgparticle
|
||||
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
|
||||
120
src/Demos/osgparticle/osgparticle.cpp
Normal file
120
src/Demos/osgparticle/osgparticle.cpp
Normal file
@@ -0,0 +1,120 @@
|
||||
#include <osg/GL>
|
||||
#include <osgGLUT/glut>
|
||||
#include <osgGLUT/Viewer>
|
||||
|
||||
#include <osg/Transform>
|
||||
#include <osg/Billboard>
|
||||
#include <osg/Geode>
|
||||
#include <osg/Group>
|
||||
#include <osg/Notify>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
#include <osgUtil/TrackballManipulator>
|
||||
#include <osgUtil/FlightManipulator>
|
||||
#include <osgUtil/DriveManipulator>
|
||||
#include <osgUtil/Optimizer>
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// These lines are necessary under Windows because if we don't instantiate at least
|
||||
// one object of osgParticle, the library will not be linked to the exe even if we
|
||||
// add it to the dependancies list, leading to failure when importing .osg files.
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#include <osgParticle/Particle>
|
||||
osgParticle::Particle dummy_Particle__;
|
||||
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
void write_usage(std::ostream& out,const std::string& name)
|
||||
{
|
||||
out << std::endl;
|
||||
out <<"usage:"<< std::endl;
|
||||
out <<" "<<name<<" [options] infile1 [infile2 ...]"<< std::endl;
|
||||
out << std::endl;
|
||||
out <<"options:"<< std::endl;
|
||||
out <<" -l libraryName - load plugin of name libraryName"<< std::endl;
|
||||
out <<" i.e. -l osgdb_pfb"<< std::endl;
|
||||
out <<" Useful for loading reader/writers which can load"<< std::endl;
|
||||
out <<" other file formats in addition to its extension."<< std::endl;
|
||||
out <<" -e extensionName - load reader/wrter plugin for file extension"<< std::endl;
|
||||
out <<" i.e. -e pfb"<< std::endl;
|
||||
out <<" Useful short hand for specifying full library name as"<< std::endl;
|
||||
out <<" done with -l above, as it automatically expands to"<< std::endl;
|
||||
out <<" the full library name appropriate for each platform."<< std::endl;
|
||||
out <<std::endl;
|
||||
out <<" -stereo - switch on stereo rendering, using the default of,"<< std::endl;
|
||||
out <<" ANAGLYPHIC or the value set in the OSG_STEREO_MODE "<< std::endl;
|
||||
out <<" environmental variable. See doc/stereo.html for "<< std::endl;
|
||||
out <<" further details on setting up accurate stereo "<< std::endl;
|
||||
out <<" for your system. "<< std::endl;
|
||||
out <<" -stereo ANAGLYPHIC - switch on anaglyphic(red/cyan) stereo rendering."<< std::endl;
|
||||
out <<" -stereo QUAD_BUFFER - switch on quad buffered stereo rendering."<< std::endl;
|
||||
out <<std::endl;
|
||||
out <<" -stencil - use a visual with stencil buffer enabled, this "<< std::endl;
|
||||
out <<" also allows the depth complexity statistics mode"<< std::endl;
|
||||
out <<" to be used (press 'p' three times to cycle to it)."<< std::endl;
|
||||
out << std::endl;
|
||||
}
|
||||
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
// initialize the GLUT
|
||||
glutInit( &argc, argv );
|
||||
|
||||
if (argc<2)
|
||||
{
|
||||
write_usage(std::cout,argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// create the commandline args.
|
||||
std::vector<std::string> commandLine;
|
||||
for(int i=1;i<argc;++i) commandLine.push_back(argv[i]);
|
||||
|
||||
|
||||
// initialize the viewer.
|
||||
osgGLUT::Viewer viewer;
|
||||
viewer.setWindowTitle(argv[0]);
|
||||
|
||||
// configure the viewer from the commandline arguments, and eat any
|
||||
// parameters that have been matched.
|
||||
viewer.readCommandLine(commandLine);
|
||||
|
||||
// configure the plugin registry from the commandline arguments, and
|
||||
// eat any parameters that have been matched.
|
||||
osgDB::readCommandLine(commandLine);
|
||||
|
||||
// load the nodes from the commandline arguments.
|
||||
osg::Node* rootnode = osgDB::readNodeFiles(commandLine);
|
||||
if (!rootnode)
|
||||
{
|
||||
// write_usage(osg::notify(osg::NOTICE),argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// run optimization over the scene graph
|
||||
osgUtil::Optimizer optimzer;
|
||||
optimzer.optimize(rootnode);
|
||||
|
||||
// add a viewport to the viewer and attach the scene graph.
|
||||
viewer.addViewport( rootnode );
|
||||
|
||||
// register trackball, flight and drive.
|
||||
viewer.registerCameraManipulator(new osgUtil::TrackballManipulator);
|
||||
viewer.registerCameraManipulator(new osgUtil::FlightManipulator);
|
||||
viewer.registerCameraManipulator(new osgUtil::DriveManipulator);
|
||||
|
||||
// open the viewer window.
|
||||
viewer.open();
|
||||
|
||||
// fire up the event loop.
|
||||
viewer.run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
17
src/osgParticle/Emitter.cpp
Normal file
17
src/osgParticle/Emitter.cpp
Normal file
@@ -0,0 +1,17 @@
|
||||
#include <osgParticle/Emitter>
|
||||
#include <osgParticle/ParticleProcessor>
|
||||
|
||||
#include <osg/CopyOp>
|
||||
|
||||
osgParticle::Emitter::Emitter()
|
||||
: ParticleProcessor(),
|
||||
usedeftemp_(true)
|
||||
{
|
||||
}
|
||||
|
||||
osgParticle::Emitter::Emitter(const Emitter ©, const osg::CopyOp ©op)
|
||||
: ParticleProcessor(copy, copyop),
|
||||
usedeftemp_(copy.usedeftemp_),
|
||||
ptemp_(copy.ptemp_)
|
||||
{
|
||||
}
|
||||
38
src/osgParticle/FluidFrictionOperator.cpp
Normal file
38
src/osgParticle/FluidFrictionOperator.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
#include <osgParticle/FluidFrictionOperator>
|
||||
#include <osgParticle/ModularProgram>
|
||||
#include <osgParticle/Operator>
|
||||
#include <osgParticle/Particle>
|
||||
#include <osg/Notify>
|
||||
|
||||
osgParticle::FluidFrictionOperator::FluidFrictionOperator()
|
||||
: Operator(), ovr_rad_(0)
|
||||
{
|
||||
setFluidToAir();
|
||||
}
|
||||
|
||||
osgParticle::FluidFrictionOperator::FluidFrictionOperator(const FluidFrictionOperator ©, const osg::CopyOp ©op)
|
||||
: Operator(copy, copyop),
|
||||
A_(copy.A_),
|
||||
B_(copy.B_),
|
||||
density_(copy.density_),
|
||||
viscosity_(copy.viscosity_),
|
||||
ovr_rad_(copy.ovr_rad_)
|
||||
{
|
||||
}
|
||||
|
||||
void osgParticle::FluidFrictionOperator::operate(Particle *P, double dt)
|
||||
{
|
||||
float r = (ovr_rad_ > 0)? ovr_rad_ : P->getRadius();
|
||||
osg::Vec3 v = P->getVelocity();
|
||||
|
||||
float vm = v.normalize();
|
||||
float R = A_ * r * vm + B_ * r * r * vm * vm;
|
||||
|
||||
osg::Vec3 Fr(-R * v.x(), -R * v.y(), -R * v.z());
|
||||
|
||||
if (current_program_->getReferenceFrame() == ModularProgram::RELATIVE_TO_PARENTS) {
|
||||
Fr = current_program_->rotateLocalToWorld(Fr);
|
||||
}
|
||||
|
||||
P->addVelocity(Fr * (P->getMassInv() * dt));
|
||||
}
|
||||
48
src/osgParticle/IO_AccelOperator.cpp
Normal file
48
src/osgParticle/IO_AccelOperator.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
|
||||
#include <osgParticle/AccelOperator>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/Input>
|
||||
#include <osgDB/Output>
|
||||
|
||||
#include <osg/Vec3>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
bool AccelOperator_readLocalData(osg::Object &obj, osgDB::Input &fr);
|
||||
bool AccelOperator_writeLocalData(const osg::Object &obj, osgDB::Output &fw);
|
||||
|
||||
osgDB::RegisterDotOsgWrapperProxy AccelOperator_Proxy
|
||||
(
|
||||
osgNew osgParticle::AccelOperator,
|
||||
"AccelOperator",
|
||||
"Object Operator AccelOperator",
|
||||
AccelOperator_readLocalData,
|
||||
AccelOperator_writeLocalData
|
||||
);
|
||||
|
||||
bool AccelOperator_readLocalData(osg::Object &obj, osgDB::Input &fr)
|
||||
{
|
||||
osgParticle::AccelOperator &aop = static_cast<osgParticle::AccelOperator &>(obj);
|
||||
bool itAdvanced = false;
|
||||
|
||||
osg::Vec3 a;
|
||||
|
||||
if (fr[0].matchWord("acceleration")) {
|
||||
if (fr[1].getFloat(a.x()) && fr[2].getFloat(a.y()) && fr[3].getFloat(a.z())) {
|
||||
aop.setAcceleration(a);
|
||||
fr += 4;
|
||||
itAdvanced = true;
|
||||
}
|
||||
}
|
||||
|
||||
return itAdvanced;
|
||||
}
|
||||
|
||||
bool AccelOperator_writeLocalData(const osg::Object &obj, osgDB::Output &fw)
|
||||
{
|
||||
const osgParticle::AccelOperator &aop = static_cast<const osgParticle::AccelOperator &>(obj);
|
||||
osg::Vec3 a = aop.getAcceleration();
|
||||
fw.indent() << "acceleration " << a.x() << " " << a.y() << " " << a.z() << std::endl;
|
||||
return true;
|
||||
}
|
||||
49
src/osgParticle/IO_CenteredPlacer.cpp
Normal file
49
src/osgParticle/IO_CenteredPlacer.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
|
||||
#include <osgParticle/CenteredPlacer>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/Input>
|
||||
#include <osgDB/Output>
|
||||
|
||||
#include <osg/Vec3>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
bool CenteredPlacer_readLocalData(osg::Object &obj, osgDB::Input &fr);
|
||||
bool CenteredPlacer_writeLocalData(const osg::Object &obj, osgDB::Output &fw);
|
||||
|
||||
osgDB::RegisterDotOsgWrapperProxy CenteredPlacer_Proxy
|
||||
(
|
||||
0,
|
||||
"CenteredPlacer",
|
||||
"Object Placer CenteredPlacer",
|
||||
CenteredPlacer_readLocalData,
|
||||
CenteredPlacer_writeLocalData
|
||||
);
|
||||
|
||||
bool CenteredPlacer_readLocalData(osg::Object &obj, osgDB::Input &fr)
|
||||
{
|
||||
osgParticle::CenteredPlacer &myobj = static_cast<osgParticle::CenteredPlacer &>(obj);
|
||||
bool itAdvanced = false;
|
||||
|
||||
osg::Vec3 v;
|
||||
if (fr[0].matchWord("center")) {
|
||||
if (fr[1].getFloat(v.x()) && fr[2].getFloat(v.y()) && fr[3].getFloat(v.z())) {
|
||||
myobj.setCenter(v);
|
||||
fr += 4;
|
||||
itAdvanced = true;
|
||||
}
|
||||
}
|
||||
|
||||
return itAdvanced;
|
||||
}
|
||||
|
||||
bool CenteredPlacer_writeLocalData(const osg::Object &obj, osgDB::Output &fw)
|
||||
{
|
||||
const osgParticle::CenteredPlacer &myobj = static_cast<const osgParticle::CenteredPlacer &>(obj);
|
||||
|
||||
osg::Vec3 v = myobj.getCenter();
|
||||
fw.indent() << "center " << v.x() << " " << v.y() << " " << v.z() << std::endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
70
src/osgParticle/IO_Emitter.cpp
Normal file
70
src/osgParticle/IO_Emitter.cpp
Normal file
@@ -0,0 +1,70 @@
|
||||
|
||||
#include <osgParticle/Emitter>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/Input>
|
||||
#include <osgDB/Output>
|
||||
|
||||
extern bool read_particle(osgDB::Input &fr, osgParticle::Particle &P);
|
||||
extern void write_particle(const osgParticle::Particle &P, osgDB::Output &fw);
|
||||
|
||||
bool Emitter_readLocalData(osg::Object &obj, osgDB::Input &fr);
|
||||
bool Emitter_writeLocalData(const osg::Object &obj, osgDB::Output &fw);
|
||||
|
||||
osgDB::RegisterDotOsgWrapperProxy Emitter_Proxy
|
||||
(
|
||||
0,
|
||||
"Emitter",
|
||||
"Object Node ParticleProcessor Emitter",
|
||||
Emitter_readLocalData,
|
||||
Emitter_writeLocalData
|
||||
);
|
||||
|
||||
bool Emitter_readLocalData(osg::Object &obj, osgDB::Input &fr)
|
||||
{
|
||||
osgParticle::Emitter &myobj = static_cast<osgParticle::Emitter &>(obj);
|
||||
bool itAdvanced = false;
|
||||
|
||||
if (fr[0].matchWord("useDefaultTemplate")) {
|
||||
if (fr[1].matchWord("TRUE")) {
|
||||
myobj.setUseDefaultTemplate(true);
|
||||
fr += 2;
|
||||
itAdvanced = true;
|
||||
}
|
||||
if (fr[1].matchWord("FALSE")) {
|
||||
myobj.setUseDefaultTemplate(false);
|
||||
fr += 2;
|
||||
itAdvanced = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (fr[0].matchWord("particleTemplate")) {
|
||||
++fr;
|
||||
itAdvanced = true;
|
||||
osgParticle::Particle P;
|
||||
if (read_particle(fr, P)) {
|
||||
myobj.setParticleTemplate(P);
|
||||
}
|
||||
}
|
||||
|
||||
return itAdvanced;
|
||||
}
|
||||
|
||||
bool Emitter_writeLocalData(const osg::Object &obj, osgDB::Output &fw)
|
||||
{
|
||||
const osgParticle::Emitter &myobj = static_cast<const osgParticle::Emitter &>(obj);
|
||||
|
||||
fw.indent() << "useDefaultTemplate ";
|
||||
if (!myobj.getUseDefaultTemplate()) {
|
||||
fw << "FALSE" << std::endl;
|
||||
fw.indent() << "particleTemplate ";
|
||||
write_particle(myobj.getParticleTemplate(), fw);
|
||||
fw << std::endl;
|
||||
} else {
|
||||
fw << "TRUE" << std::endl;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
63
src/osgParticle/IO_FluidFrictionOperator.cpp
Normal file
63
src/osgParticle/IO_FluidFrictionOperator.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
|
||||
#include <osgParticle/FluidFrictionOperator>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/Input>
|
||||
#include <osgDB/Output>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
bool FluidFrictionOperator_readLocalData(osg::Object &obj, osgDB::Input &fr);
|
||||
bool FluidFrictionOperator_writeLocalData(const osg::Object &obj, osgDB::Output &fw);
|
||||
|
||||
osgDB::RegisterDotOsgWrapperProxy FluidFrictionOperator_Proxy
|
||||
(
|
||||
osgNew osgParticle::FluidFrictionOperator,
|
||||
"FluidFrictionOperator",
|
||||
"Object Operator FluidFrictionOperator",
|
||||
FluidFrictionOperator_readLocalData,
|
||||
FluidFrictionOperator_writeLocalData
|
||||
);
|
||||
|
||||
bool FluidFrictionOperator_readLocalData(osg::Object &obj, osgDB::Input &fr)
|
||||
{
|
||||
osgParticle::FluidFrictionOperator &aop = static_cast<osgParticle::FluidFrictionOperator &>(obj);
|
||||
bool itAdvanced = false;
|
||||
|
||||
float f;
|
||||
|
||||
if (fr[0].matchWord("fluidDensity")) {
|
||||
if (fr[1].getFloat(f)) {
|
||||
aop.setFluidDensity(f);
|
||||
fr += 2;
|
||||
itAdvanced = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (fr[0].matchWord("fluidViscosity")) {
|
||||
if (fr[1].getFloat(f)) {
|
||||
aop.setFluidViscosity(f);
|
||||
fr += 2;
|
||||
itAdvanced = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (fr[0].matchWord("overrideRadius")) {
|
||||
if (fr[1].getFloat(f)) {
|
||||
aop.setOverrideRadius(f);
|
||||
fr += 2;
|
||||
itAdvanced = true;
|
||||
}
|
||||
}
|
||||
|
||||
return itAdvanced;
|
||||
}
|
||||
|
||||
bool FluidFrictionOperator_writeLocalData(const osg::Object &obj, osgDB::Output &fw)
|
||||
{
|
||||
const osgParticle::FluidFrictionOperator &aop = static_cast<const osgParticle::FluidFrictionOperator &>(obj);
|
||||
fw.indent() << "fluidDensity " << aop.getFluidDensity() << std::endl;
|
||||
fw.indent() << "fluidViscosity " << aop.getFluidViscosity() << std::endl;
|
||||
fw.indent() << "overrideRadius " << aop.getOverrideRadius();
|
||||
return true;
|
||||
}
|
||||
48
src/osgParticle/IO_ForceOperator.cpp
Normal file
48
src/osgParticle/IO_ForceOperator.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
|
||||
#include <osgParticle/ForceOperator>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/Input>
|
||||
#include <osgDB/Output>
|
||||
|
||||
#include <osg/Vec3>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
bool ForceOperator_readLocalData(osg::Object &obj, osgDB::Input &fr);
|
||||
bool ForceOperator_writeLocalData(const osg::Object &obj, osgDB::Output &fw);
|
||||
|
||||
osgDB::RegisterDotOsgWrapperProxy ForceOperator_Proxy
|
||||
(
|
||||
osgNew osgParticle::ForceOperator,
|
||||
"ForceOperator",
|
||||
"Object Operator ForceOperator",
|
||||
ForceOperator_readLocalData,
|
||||
ForceOperator_writeLocalData
|
||||
);
|
||||
|
||||
bool ForceOperator_readLocalData(osg::Object &obj, osgDB::Input &fr)
|
||||
{
|
||||
osgParticle::ForceOperator &fop = static_cast<osgParticle::ForceOperator &>(obj);
|
||||
bool itAdvanced = false;
|
||||
|
||||
osg::Vec3 f;
|
||||
|
||||
if (fr[0].matchWord("force")) {
|
||||
if (fr[1].getFloat(f.x()) && fr[2].getFloat(f.y()) && fr[3].getFloat(f.z())) {
|
||||
fop.setForce(f);
|
||||
fr += 4;
|
||||
itAdvanced = true;
|
||||
}
|
||||
}
|
||||
|
||||
return itAdvanced;
|
||||
}
|
||||
|
||||
bool ForceOperator_writeLocalData(const osg::Object &obj, osgDB::Output &fw)
|
||||
{
|
||||
const osgParticle::ForceOperator &fop = static_cast<const osgParticle::ForceOperator &>(obj);
|
||||
osg::Vec3 f = fop.getForce();
|
||||
fw.indent() << "force " << f.x() << " " << f.y() << " " << f.z() << std::endl;
|
||||
return true;
|
||||
}
|
||||
28
src/osgParticle/IO_LinearInterpolator.cpp
Normal file
28
src/osgParticle/IO_LinearInterpolator.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
|
||||
#include <osgParticle/LinearInterpolator>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/Input>
|
||||
#include <osgDB/Output>
|
||||
|
||||
bool LinearInterpolator_readLocalData(osg::Object &obj, osgDB::Input &fr);
|
||||
bool LinearInterpolator_writeLocalData(const osg::Object &obj, osgDB::Output &fw);
|
||||
|
||||
osgDB::RegisterDotOsgWrapperProxy LinearInterpolator_Proxy
|
||||
(
|
||||
osgNew osgParticle::LinearInterpolator,
|
||||
"LinearInterpolator",
|
||||
"Object Interpolator LinearInterpolator",
|
||||
LinearInterpolator_readLocalData,
|
||||
LinearInterpolator_writeLocalData
|
||||
);
|
||||
|
||||
bool LinearInterpolator_readLocalData(osg::Object &, osgDB::Input &)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LinearInterpolator_writeLocalData(const osg::Object &, osgDB::Output &)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
62
src/osgParticle/IO_ModularEmitter.cpp
Normal file
62
src/osgParticle/IO_ModularEmitter.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
|
||||
#include <osgParticle/ModularEmitter>
|
||||
#include <osgParticle/Counter>
|
||||
#include <osgParticle/Placer>
|
||||
#include <osgParticle/Shooter>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/Input>
|
||||
#include <osgDB/Output>
|
||||
|
||||
bool ModularEmitter_readLocalData(osg::Object &obj, osgDB::Input &fr);
|
||||
bool ModularEmitter_writeLocalData(const osg::Object &obj, osgDB::Output &fw);
|
||||
|
||||
osgDB::RegisterDotOsgWrapperProxy ModularEmitter_Proxy
|
||||
(
|
||||
osgNew osgParticle::ModularEmitter,
|
||||
"ModularEmitter",
|
||||
"Object Node ParticleProcessor Emitter ModularEmitter",
|
||||
ModularEmitter_readLocalData,
|
||||
ModularEmitter_writeLocalData
|
||||
);
|
||||
|
||||
bool ModularEmitter_readLocalData(osg::Object &obj, osgDB::Input &fr)
|
||||
{
|
||||
osgParticle::ModularEmitter &myobj = static_cast<osgParticle::ModularEmitter &>(obj);
|
||||
bool itAdvanced = false;
|
||||
|
||||
// we cannot use readObjectOfType() because the Coutner, Placer and Shooter classes are
|
||||
// abstract and we can't create instances to use as prototypes.
|
||||
// So, we call readObject() and then dynamic cast to the desired class.
|
||||
|
||||
osgParticle::Counter *counter = dynamic_cast<osgParticle::Counter *>(fr.readObject());
|
||||
if (counter) {
|
||||
myobj.setCounter(counter);
|
||||
itAdvanced = true;
|
||||
}
|
||||
|
||||
osgParticle::Placer *placer = dynamic_cast<osgParticle::Placer *>(fr.readObject());
|
||||
if (placer) {
|
||||
myobj.setPlacer(placer);
|
||||
itAdvanced = true;
|
||||
}
|
||||
|
||||
osgParticle::Shooter *shooter = dynamic_cast<osgParticle::Shooter *>(fr.readObject());
|
||||
if (shooter) {
|
||||
myobj.setShooter(shooter);
|
||||
itAdvanced = true;
|
||||
}
|
||||
|
||||
return itAdvanced;
|
||||
}
|
||||
|
||||
bool ModularEmitter_writeLocalData(const osg::Object &obj, osgDB::Output &fw)
|
||||
{
|
||||
const osgParticle::ModularEmitter &myobj = static_cast<const osgParticle::ModularEmitter &>(obj);
|
||||
|
||||
fw.writeObject(*myobj.getCounter());
|
||||
fw.writeObject(*myobj.getPlacer());
|
||||
fw.writeObject(*myobj.getShooter());
|
||||
|
||||
return true;
|
||||
}
|
||||
46
src/osgParticle/IO_ModularProgram.cpp
Normal file
46
src/osgParticle/IO_ModularProgram.cpp
Normal file
@@ -0,0 +1,46 @@
|
||||
|
||||
#include <osgParticle/ModularProgram>
|
||||
#include <osgParticle/Operator>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/Input>
|
||||
#include <osgDB/Output>
|
||||
|
||||
bool ModularProgram_readLocalData(osg::Object &obj, osgDB::Input &fr);
|
||||
bool ModularProgram_writeLocalData(const osg::Object &obj, osgDB::Output &fw);
|
||||
|
||||
osgDB::RegisterDotOsgWrapperProxy ModularProgram_Proxy
|
||||
(
|
||||
osgNew osgParticle::ModularProgram,
|
||||
"ModularProgram",
|
||||
"Object Node ParticleProcessor Program ModularProgram",
|
||||
ModularProgram_readLocalData,
|
||||
ModularProgram_writeLocalData
|
||||
);
|
||||
|
||||
bool ModularProgram_readLocalData(osg::Object &obj, osgDB::Input &fr)
|
||||
{
|
||||
osgParticle::ModularProgram &myobj = static_cast<osgParticle::ModularProgram &>(obj);
|
||||
bool itAdvanced = false;
|
||||
|
||||
osgParticle::Operator *op = dynamic_cast<osgParticle::Operator *>(fr.readObject());
|
||||
if (op) {
|
||||
myobj.addOperator(op);
|
||||
itAdvanced = true;
|
||||
}
|
||||
|
||||
return itAdvanced;
|
||||
}
|
||||
|
||||
bool ModularProgram_writeLocalData(const osg::Object &obj, osgDB::Output &fw)
|
||||
{
|
||||
const osgParticle::ModularProgram &myobj = static_cast<const osgParticle::ModularProgram &>(obj);
|
||||
|
||||
for (int i=0; i<myobj.numOperators(); ++i) {
|
||||
fw.writeObject(*myobj.getOperator(i));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
54
src/osgParticle/IO_MultiSegmentPlacer.cpp
Normal file
54
src/osgParticle/IO_MultiSegmentPlacer.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
|
||||
#include <osgParticle/MultiSegmentPlacer>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/Input>
|
||||
#include <osgDB/Output>
|
||||
|
||||
#include <osg/Vec3>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
bool MultiSegmentPlacer_readLocalData(osg::Object &obj, osgDB::Input &fr);
|
||||
bool MultiSegmentPlacer_writeLocalData(const osg::Object &obj, osgDB::Output &fw);
|
||||
|
||||
osgDB::RegisterDotOsgWrapperProxy MultiSegmentPlacer_Proxy
|
||||
(
|
||||
osgNew osgParticle::MultiSegmentPlacer,
|
||||
"MultiSegmentPlacer",
|
||||
"Object Placer MultiSegmentPlacer",
|
||||
MultiSegmentPlacer_readLocalData,
|
||||
MultiSegmentPlacer_writeLocalData
|
||||
);
|
||||
|
||||
bool MultiSegmentPlacer_readLocalData(osg::Object &obj, osgDB::Input &fr)
|
||||
{
|
||||
osgParticle::MultiSegmentPlacer &myobj = static_cast<osgParticle::MultiSegmentPlacer &>(obj);
|
||||
bool itAdvanced = false;
|
||||
|
||||
osg::Vec3 v;
|
||||
|
||||
if (fr[0].matchWord("vertex")) {
|
||||
if (fr[1].getFloat(v.x()) && fr[2].getFloat(v.y()) && fr[3].getFloat(v.z())) {
|
||||
myobj.addVertex(v);
|
||||
fr += 4;
|
||||
itAdvanced = true;
|
||||
}
|
||||
}
|
||||
|
||||
return itAdvanced;
|
||||
}
|
||||
|
||||
bool MultiSegmentPlacer_writeLocalData(const osg::Object &obj, osgDB::Output &fw)
|
||||
{
|
||||
const osgParticle::MultiSegmentPlacer &myobj = static_cast<const osgParticle::MultiSegmentPlacer &>(obj);
|
||||
|
||||
int n = myobj.numVertices();
|
||||
|
||||
for (int i=0; i<n; ++i) {
|
||||
const osg::Vec3 &v = myobj.getVertex(i);
|
||||
fw.indent() << "vertex " << v.x() << " " << v.y() << " " << v.z() << std::endl;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
205
src/osgParticle/IO_Particle.cpp
Normal file
205
src/osgParticle/IO_Particle.cpp
Normal file
@@ -0,0 +1,205 @@
|
||||
|
||||
#include <osgParticle/Particle>
|
||||
#include <osgParticle/Interpolator>
|
||||
#include <osgParticle/range>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include <osg/Vec3>
|
||||
#include <osg/Vec4>
|
||||
#include <osg/Notify>
|
||||
|
||||
#include <osgDB/Input>
|
||||
#include <osgDB/Output>
|
||||
|
||||
bool read_particle(osgDB::Input &fr, osgParticle::Particle &P)
|
||||
{
|
||||
if (fr[0].matchString("{")) {
|
||||
++fr;
|
||||
int entry = fr[0].getNoNestedBrackets();
|
||||
bool itAdvanced = true;
|
||||
while (!fr.eof() && fr[0].getNoNestedBrackets() >= entry && itAdvanced) {
|
||||
itAdvanced = false;
|
||||
if (fr[0].matchWord("shape")) {
|
||||
const char *ptstr = fr[1].getStr();
|
||||
if (ptstr) {
|
||||
if (std::string(ptstr) == "QUAD") {
|
||||
P.setShape(osgParticle::Particle::QUAD);
|
||||
} else if (std::string(ptstr) == "HEXAGON") {
|
||||
P.setShape(osgParticle::Particle::HEXAGON);
|
||||
} else if (std::string(ptstr) == "POINT") {
|
||||
P.setShape(osgParticle::Particle::POINT);
|
||||
} else if (std::string(ptstr) == "QUAD_TRIANGLESTRIP") {
|
||||
P.setShape(osgParticle::Particle::QUAD_TRIANGLESTRIP);
|
||||
} else {
|
||||
osg::notify(osg::WARN) << "Particle reader warning: invalid shape: " << ptstr << std::endl;
|
||||
}
|
||||
fr += 2;
|
||||
itAdvanced = true;
|
||||
}
|
||||
}
|
||||
if (fr[0].matchWord("lifeTime")) {
|
||||
float lt;
|
||||
if (fr[1].getFloat(lt)) {
|
||||
P.setLifeTime(lt);
|
||||
fr += 2;
|
||||
itAdvanced = true;
|
||||
}
|
||||
}
|
||||
if (fr[0].matchWord("sizeRange")) {
|
||||
osgParticle::rangef r;
|
||||
if (fr[1].getFloat(r.min) && fr[2].getFloat(r.max)) {
|
||||
P.setSizeRange(r);
|
||||
fr += 3;
|
||||
itAdvanced = true;
|
||||
}
|
||||
}
|
||||
if (fr[0].matchWord("alphaRange")) {
|
||||
osgParticle::rangef r;
|
||||
if (fr[1].getFloat(r.min) && fr[2].getFloat(r.max)) {
|
||||
P.setAlphaRange(r);
|
||||
fr += 3;
|
||||
itAdvanced = true;
|
||||
}
|
||||
}
|
||||
if (fr[0].matchWord("colorRange")) {
|
||||
osgParticle::rangev4 r;
|
||||
if (fr[1].getFloat(r.min.x()) && fr[2].getFloat(r.min.y()) && fr[3].getFloat(r.min.z()) && fr[4].getFloat(r.min.w()) &&
|
||||
fr[5].getFloat(r.max.x()) && fr[6].getFloat(r.max.y()) && fr[7].getFloat(r.max.z()) && fr[8].getFloat(r.max.w())) {
|
||||
P.setColorRange(r);
|
||||
fr += 9;
|
||||
itAdvanced = true;
|
||||
}
|
||||
}
|
||||
if (fr[0].matchWord("position")) {
|
||||
osg::Vec3 v;
|
||||
if (fr[1].getFloat(v.x()) && fr[2].getFloat(v.y()) && fr[3].getFloat(v.z())) {
|
||||
P.setPosition(v);
|
||||
fr += 4;
|
||||
itAdvanced = true;
|
||||
}
|
||||
}
|
||||
if (fr[0].matchWord("velocity")) {
|
||||
osg::Vec3 v;
|
||||
if (fr[1].getFloat(v.x()) && fr[2].getFloat(v.y()) && fr[3].getFloat(v.z())) {
|
||||
P.setVelocity(v);
|
||||
fr += 4;
|
||||
itAdvanced = true;
|
||||
}
|
||||
}
|
||||
if (fr[0].matchWord("radius")) {
|
||||
float f;
|
||||
if (fr[1].getFloat(f)) {
|
||||
P.setRadius(f);
|
||||
fr += 2;
|
||||
itAdvanced = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (fr[0].matchWord("mass")) {
|
||||
float f;
|
||||
if (fr[1].getFloat(f)) {
|
||||
P.setMass(f);
|
||||
fr += 2;
|
||||
itAdvanced = true;
|
||||
}
|
||||
}
|
||||
|
||||
// interpolators
|
||||
|
||||
if (fr[0].matchWord("sizeInterpolator") && fr[1].matchString("{")) {
|
||||
fr += 2;
|
||||
itAdvanced = true;
|
||||
osgParticle::Interpolator *ip = dynamic_cast<osgParticle::Interpolator *>(fr.readObject());
|
||||
if (ip) {
|
||||
P.setSizeInterpolator(ip);
|
||||
}
|
||||
++fr;
|
||||
}
|
||||
if (fr[0].matchWord("alphaInterpolator") && fr[1].matchString("{")) {
|
||||
fr += 2;
|
||||
itAdvanced = true;
|
||||
osgParticle::Interpolator *ip = dynamic_cast<osgParticle::Interpolator *>(fr.readObject());
|
||||
if (ip) {
|
||||
P.setAlphaInterpolator(ip);
|
||||
}
|
||||
++fr;
|
||||
}
|
||||
if (fr[0].matchWord("colorInterpolator") && fr[1].matchString("{")) {
|
||||
fr += 2;
|
||||
itAdvanced = true;
|
||||
osgParticle::Interpolator *ip = dynamic_cast<osgParticle::Interpolator *>(fr.readObject());
|
||||
if (ip) {
|
||||
P.setColorInterpolator(ip);
|
||||
}
|
||||
++fr;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void write_particle(const osgParticle::Particle &P, osgDB::Output &fw)
|
||||
{
|
||||
fw << "{" << std::endl;
|
||||
fw.moveIn();
|
||||
|
||||
fw.indent() << "shape ";
|
||||
switch (P.getShape())
|
||||
{
|
||||
case osgParticle::Particle::POINT: fw << "POINT" << std::endl; break;
|
||||
case osgParticle::Particle::HEXAGON: fw << "HEXAGON" << std::endl; break;
|
||||
case osgParticle::Particle::QUAD_TRIANGLESTRIP: fw << "QUAD_TRIANGLESTRIP" << std::endl; break;
|
||||
case osgParticle::Particle::QUAD:
|
||||
default: fw << "QUAD" << std::endl; break;
|
||||
}
|
||||
|
||||
fw.indent() << "lifeTime " << P.getLifeTime() << std::endl;
|
||||
|
||||
osgParticle::rangef rf = P.getSizeRange();
|
||||
fw.indent() << "sizeRange " << rf.min << " " << rf.max << std::endl;
|
||||
|
||||
rf = P.getAlphaRange();
|
||||
fw.indent() << "alphaRange " << rf.min << " " << rf.max << std::endl;
|
||||
|
||||
osgParticle::rangev4 rv4 = P.getColorRange();
|
||||
fw.indent() << "colorRange ";
|
||||
fw << rv4.min.x() << " " << rv4.min.y() << " " << rv4.min.z() << " " << rv4.min.w() << " ";
|
||||
fw << rv4.max.x() << " " << rv4.max.y() << " " << rv4.max.z() << " " << rv4.max.w() << std::endl;
|
||||
|
||||
osg::Vec3 v = P.getPosition();
|
||||
fw.indent() << "position ";
|
||||
fw << v.x() << " " << v.y() << " " << v.z() << std::endl;
|
||||
|
||||
v = P.getVelocity();
|
||||
fw.indent() << "velocity ";
|
||||
fw << v.x() << " " << v.y() << " " << v.z() << std::endl;
|
||||
|
||||
fw.indent() << "mass " << P.getMass() << std::endl;
|
||||
fw.indent() << "radius " << P.getRadius() << std::endl;
|
||||
|
||||
// interpolators
|
||||
|
||||
fw.indent() << "sizeInterpolator {" << std::endl;
|
||||
fw.moveIn();
|
||||
fw.writeObject(*P.getSizeInterpolator());
|
||||
fw.moveOut();
|
||||
fw.indent() << "}" << std::endl;
|
||||
|
||||
fw.indent() << "alphaInterpolator {" << std::endl;
|
||||
fw.moveIn();
|
||||
fw.writeObject(*P.getAlphaInterpolator());
|
||||
fw.moveOut();
|
||||
fw.indent() << "}" << std::endl;
|
||||
|
||||
fw.indent() << "colorInterpolator {" << std::endl;
|
||||
fw.moveIn();
|
||||
fw.writeObject(*P.getColorInterpolator());
|
||||
fw.moveOut();
|
||||
fw.indent() << "}" << std::endl;
|
||||
|
||||
fw.moveOut();
|
||||
fw.indent() << "}" << std::endl;
|
||||
}
|
||||
93
src/osgParticle/IO_ParticleProcessor.cpp
Normal file
93
src/osgParticle/IO_ParticleProcessor.cpp
Normal file
@@ -0,0 +1,93 @@
|
||||
|
||||
#include <osgParticle/ParticleProcessor>
|
||||
#include <osgParticle/ParticleSystem>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <osg/ref_ptr>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/Input>
|
||||
#include <osgDB/Output>
|
||||
|
||||
extern bool read_particle(osgDB::Input &fr, osgParticle::Particle &P);
|
||||
extern void write_particle(const osgParticle::Particle &P, osgDB::Output &fw);
|
||||
|
||||
bool ParticleProcessor_readLocalData(osg::Object &obj, osgDB::Input &fr);
|
||||
bool ParticleProcessor_writeLocalData(const osg::Object &obj, osgDB::Output &fw);
|
||||
|
||||
osgDB::RegisterDotOsgWrapperProxy ParticleProcessor_Proxy
|
||||
(
|
||||
0,
|
||||
"ParticleProcessor",
|
||||
"Object Node ParticleProcessor",
|
||||
ParticleProcessor_readLocalData,
|
||||
ParticleProcessor_writeLocalData
|
||||
);
|
||||
|
||||
bool ParticleProcessor_readLocalData(osg::Object &obj, osgDB::Input &fr)
|
||||
{
|
||||
osgParticle::ParticleProcessor &myobj = static_cast<osgParticle::ParticleProcessor &>(obj);
|
||||
bool itAdvanced = false;
|
||||
|
||||
osg::ref_ptr<osgParticle::ParticleSystem> ps_proto = osgNew osgParticle::ParticleSystem;
|
||||
|
||||
osgParticle::ParticleSystem *ps = static_cast<osgParticle::ParticleSystem *>(fr.readObjectOfType(*ps_proto));
|
||||
if (ps) {
|
||||
myobj.setParticleSystem(ps);
|
||||
itAdvanced = true;
|
||||
}
|
||||
|
||||
if (fr[0].matchWord("enabled")) {
|
||||
if (fr[1].matchWord("TRUE")) {
|
||||
myobj.setEnabled(true);
|
||||
fr += 2;
|
||||
itAdvanced = true;
|
||||
} else if (fr[1].matchWord("FALSE")) {
|
||||
myobj.setEnabled(false);
|
||||
fr += 2;
|
||||
itAdvanced = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (fr[0].matchWord("referenceFrame")) {
|
||||
if (fr[1].matchWord("RELATIVE_TO_ABSOLUTE")) {
|
||||
myobj.setReferenceFrame(osgParticle::ParticleProcessor::RELATIVE_TO_ABSOLUTE);
|
||||
fr += 2;
|
||||
itAdvanced = true;
|
||||
}
|
||||
if (fr[1].matchWord("RELATIVE_TO_PARENTS")) {
|
||||
myobj.setReferenceFrame(osgParticle::ParticleProcessor::RELATIVE_TO_PARENTS);
|
||||
fr += 2;
|
||||
itAdvanced = true;
|
||||
}
|
||||
}
|
||||
|
||||
return itAdvanced;
|
||||
}
|
||||
|
||||
bool ParticleProcessor_writeLocalData(const osg::Object &obj, osgDB::Output &fw)
|
||||
{
|
||||
const osgParticle::ParticleProcessor &myobj = static_cast<const osgParticle::ParticleProcessor &>(obj);
|
||||
|
||||
fw.writeObject(*myobj.getParticleSystem());
|
||||
|
||||
fw.indent() << "enabled ";
|
||||
if (myobj.isEnabled())
|
||||
fw << "TRUE" << std::endl;
|
||||
else
|
||||
fw << "FALSE" << std::endl;
|
||||
|
||||
fw.indent() << "referenceFrame ";
|
||||
switch (myobj.getReferenceFrame())
|
||||
{
|
||||
case osgParticle::ParticleProcessor::RELATIVE_TO_ABSOLUTE:
|
||||
fw << "RELATIVE_TO_ABSOLUTE" << std::endl;
|
||||
break;
|
||||
case osgParticle::ParticleProcessor::RELATIVE_TO_PARENTS:
|
||||
default:
|
||||
fw << "RELATIVE_TO_PARENTS" << std::endl;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
126
src/osgParticle/IO_ParticleSystem.cpp
Normal file
126
src/osgParticle/IO_ParticleSystem.cpp
Normal file
@@ -0,0 +1,126 @@
|
||||
|
||||
#include <osgParticle/ParticleSystem>
|
||||
|
||||
#include <osg/BoundingBox>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/Input>
|
||||
#include <osgDB/Output>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
extern bool read_particle(osgDB::Input &fr, osgParticle::Particle &P);
|
||||
extern void write_particle(const osgParticle::Particle &P, osgDB::Output &fw);
|
||||
|
||||
bool ParticleSystem_readLocalData(osg::Object &obj, osgDB::Input &fr);
|
||||
bool ParticleSystem_writeLocalData(const osg::Object &obj, osgDB::Output &fw);
|
||||
|
||||
osgDB::RegisterDotOsgWrapperProxy ParticleSystem_Proxy
|
||||
(
|
||||
osgNew osgParticle::ParticleSystem,
|
||||
"ParticleSystem",
|
||||
"Object Drawable ParticleSystem",
|
||||
ParticleSystem_readLocalData,
|
||||
ParticleSystem_writeLocalData
|
||||
);
|
||||
|
||||
bool ParticleSystem_readLocalData(osg::Object &obj, osgDB::Input &fr)
|
||||
{
|
||||
osgParticle::ParticleSystem &myobj = static_cast<osgParticle::ParticleSystem &>(obj);
|
||||
bool itAdvanced = false;
|
||||
|
||||
if (fr[0].matchWord("DoublePassRendering")) {
|
||||
if (fr[1].matchWord("TRUE")) {
|
||||
myobj.setDoublePassRendering(true);
|
||||
fr += 2;
|
||||
itAdvanced = true;
|
||||
} else if (fr[1].matchWord("FALSE")) {
|
||||
myobj.setDoublePassRendering(false);
|
||||
fr += 2;
|
||||
itAdvanced = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (fr[0].matchWord("frozen")) {
|
||||
if (fr[1].matchWord("TRUE")) {
|
||||
myobj.setFrozen(true);
|
||||
fr += 2;
|
||||
itAdvanced = true;
|
||||
} else if (fr[1].matchWord("FALSE")) {
|
||||
myobj.setFrozen(false); // this might not be necessary
|
||||
fr += 2;
|
||||
itAdvanced = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (fr[0].matchWord("freezeOnCull")) {
|
||||
if (fr[1].matchWord("TRUE")) {
|
||||
myobj.setFreezeOnCull(true);
|
||||
fr += 2;
|
||||
itAdvanced = true;
|
||||
} else if (fr[1].matchWord("FALSE")) {
|
||||
myobj.setFreezeOnCull(false);
|
||||
fr += 2;
|
||||
itAdvanced = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (fr[0].matchWord("defaultBoundingBox")) {
|
||||
osg::BoundingBox bbox;
|
||||
if ( fr[1].getFloat(bbox.xMin()) &&
|
||||
fr[2].getFloat(bbox.yMin()) &&
|
||||
fr[3].getFloat(bbox.zMin()) &&
|
||||
fr[4].getFloat(bbox.xMax()) &&
|
||||
fr[5].getFloat(bbox.yMax()) &&
|
||||
fr[6].getFloat(bbox.zMax()) ) {
|
||||
myobj.setDefaultBoundingBox(bbox);
|
||||
fr += 7;
|
||||
itAdvanced = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (fr[0].matchWord("particleTemplate")) {
|
||||
++fr;
|
||||
itAdvanced = true;
|
||||
osgParticle::Particle P;
|
||||
if (read_particle(fr, P)) {
|
||||
myobj.setDefaultParticleTemplate(P);
|
||||
}
|
||||
}
|
||||
|
||||
return itAdvanced;
|
||||
}
|
||||
|
||||
bool ParticleSystem_writeLocalData(const osg::Object &obj, osgDB::Output &fw)
|
||||
{
|
||||
const osgParticle::ParticleSystem &myobj = static_cast<const osgParticle::ParticleSystem &>(obj);
|
||||
|
||||
fw.indent() << "DoublePassRendering ";
|
||||
if (myobj.getDoublePassRendering())
|
||||
fw << "TRUE" << std::endl;
|
||||
else
|
||||
fw << "FALSE" << std::endl;
|
||||
|
||||
fw.indent() << "frozen ";
|
||||
if (myobj.isFrozen())
|
||||
fw << "TRUE" << std::endl;
|
||||
else
|
||||
fw << "FALSE" << std::endl;
|
||||
|
||||
fw.indent() << "freezeOnCull ";
|
||||
if (myobj.getFreezeOnCull())
|
||||
fw << "TRUE" << std::endl;
|
||||
else
|
||||
fw << "FALSE" << std::endl;
|
||||
|
||||
osg::BoundingBox bbox = myobj.getDefaultBoundingBox();
|
||||
fw.indent() << "defaultBoundingBox ";
|
||||
fw << bbox.xMin() << " " << bbox.yMin() << " " << bbox.zMin() << " ";
|
||||
fw << bbox.xMax() << " " << bbox.yMax() << " " << bbox.zMax() << std::endl;
|
||||
|
||||
fw.indent() << "particleTemplate ";
|
||||
write_particle(myobj.getDefaultParticleTemplate(), fw);
|
||||
|
||||
return true;
|
||||
}
|
||||
45
src/osgParticle/IO_ParticleSystemUpdater.cpp
Normal file
45
src/osgParticle/IO_ParticleSystemUpdater.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
|
||||
#include <osgParticle/ParticleSystemUpdater>
|
||||
|
||||
#include <osg/ref_ptr>
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/Input>
|
||||
#include <osgDB/Output>
|
||||
|
||||
bool PSU_readLocalData(osg::Object &obj, osgDB::Input &fr);
|
||||
bool PSU_writeLocalData(const osg::Object &obj, osgDB::Output &fr);
|
||||
|
||||
osgDB::RegisterDotOsgWrapperProxy PSU_Proxy
|
||||
(
|
||||
osgNew osgParticle::ParticleSystemUpdater,
|
||||
"ParticleSystemUpdater",
|
||||
"Object Node ParticleSystemUpdater",
|
||||
PSU_readLocalData,
|
||||
PSU_writeLocalData
|
||||
);
|
||||
|
||||
bool PSU_readLocalData(osg::Object &obj, osgDB::Input &fr)
|
||||
{
|
||||
osgParticle::ParticleSystemUpdater &myobj = static_cast<osgParticle::ParticleSystemUpdater &>(obj);
|
||||
bool itAdvanced = false;
|
||||
|
||||
osg::ref_ptr<osgParticle::ParticleSystem> proto = osgNew osgParticle::ParticleSystem;
|
||||
osgParticle::ParticleSystem *ps = static_cast<osgParticle::ParticleSystem *>(fr.readObjectOfType(*proto));
|
||||
if (ps) {
|
||||
myobj.addParticleSystem(ps);
|
||||
itAdvanced = true;
|
||||
}
|
||||
|
||||
return itAdvanced;
|
||||
}
|
||||
|
||||
bool PSU_writeLocalData(const osg::Object &obj, osgDB::Output &fw)
|
||||
{
|
||||
const osgParticle::ParticleSystemUpdater &myobj = static_cast<const osgParticle::ParticleSystemUpdater &>(obj);
|
||||
|
||||
for (int i=0; i<myobj.numParticleSystems(); ++i) {
|
||||
fw.writeObject(*myobj.getParticleSystem(i));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
28
src/osgParticle/IO_PointPlacer.cpp
Normal file
28
src/osgParticle/IO_PointPlacer.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
|
||||
#include <osgParticle/PointPlacer>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/Input>
|
||||
#include <osgDB/Output>
|
||||
|
||||
bool PointPlacer_readLocalData(osg::Object &obj, osgDB::Input &fr);
|
||||
bool PointPlacer_writeLocalData(const osg::Object &obj, osgDB::Output &fw);
|
||||
|
||||
osgDB::RegisterDotOsgWrapperProxy PointPlacer_Proxy
|
||||
(
|
||||
osgNew osgParticle::PointPlacer,
|
||||
"PointPlacer",
|
||||
"Object Placer CenteredPlacer PointPlacer",
|
||||
PointPlacer_readLocalData,
|
||||
PointPlacer_writeLocalData
|
||||
);
|
||||
|
||||
bool PointPlacer_readLocalData(osg::Object &, osgDB::Input &)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PointPlacer_writeLocalData(const osg::Object &, osgDB::Output &)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
28
src/osgParticle/IO_Program.cpp
Normal file
28
src/osgParticle/IO_Program.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
|
||||
#include <osgParticle/Program>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/Input>
|
||||
#include <osgDB/Output>
|
||||
|
||||
bool Program_readLocalData(osg::Object &obj, osgDB::Input &fr);
|
||||
bool Program_writeLocalData(const osg::Object &obj, osgDB::Output &fw);
|
||||
|
||||
osgDB::RegisterDotOsgWrapperProxy Program_Proxy
|
||||
(
|
||||
0,
|
||||
"Program",
|
||||
"Object Node ParticleProcessor Program",
|
||||
Program_readLocalData,
|
||||
Program_writeLocalData
|
||||
);
|
||||
|
||||
bool Program_readLocalData(osg::Object &, osgDB::Input &)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Program_writeLocalData(const osg::Object &, osgDB::Output &)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
68
src/osgParticle/IO_RadialShooter.cpp
Normal file
68
src/osgParticle/IO_RadialShooter.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
|
||||
#include <osgParticle/RadialShooter>
|
||||
#include <osgParticle/range>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/Input>
|
||||
#include <osgDB/Output>
|
||||
|
||||
bool RadialShooter_readLocalData(osg::Object &obj, osgDB::Input &fr);
|
||||
bool RadialShooter_writeLocalData(const osg::Object &obj, osgDB::Output &fw);
|
||||
|
||||
osgDB::RegisterDotOsgWrapperProxy RadialShooter_Proxy
|
||||
(
|
||||
osgNew osgParticle::RadialShooter,
|
||||
"RadialShooter",
|
||||
"Object Shooter RadialShooter",
|
||||
RadialShooter_readLocalData,
|
||||
RadialShooter_writeLocalData
|
||||
);
|
||||
|
||||
bool RadialShooter_readLocalData(osg::Object &obj, osgDB::Input &fr)
|
||||
{
|
||||
osgParticle::RadialShooter &myobj = static_cast<osgParticle::RadialShooter &>(obj);
|
||||
bool itAdvanced = false;
|
||||
|
||||
osgParticle::rangef r;
|
||||
|
||||
if (fr[0].matchWord("thetaRange")) {
|
||||
if (fr[1].getFloat(r.min) && fr[2].getFloat(r.max)) {
|
||||
myobj.setThetaRange(r);
|
||||
fr += 3;
|
||||
itAdvanced = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (fr[0].matchWord("phiRange")) {
|
||||
if (fr[1].getFloat(r.min) && fr[2].getFloat(r.max)) {
|
||||
myobj.setPhiRange(r);
|
||||
fr += 3;
|
||||
itAdvanced = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (fr[0].matchWord("initialSpeedRange")) {
|
||||
if (fr[1].getFloat(r.min) && fr[2].getFloat(r.max)) {
|
||||
myobj.setInitialSpeedRange(r);
|
||||
fr += 3;
|
||||
itAdvanced = true;
|
||||
}
|
||||
}
|
||||
|
||||
return itAdvanced;
|
||||
}
|
||||
|
||||
bool RadialShooter_writeLocalData(const osg::Object &obj, osgDB::Output &fw)
|
||||
{
|
||||
const osgParticle::RadialShooter &myobj = static_cast<const osgParticle::RadialShooter &>(obj);
|
||||
osgParticle::rangef r;
|
||||
|
||||
r = myobj.getThetaRange();
|
||||
fw.indent() << "thetaRange " << r.min << " " << r.max << std::endl;
|
||||
r = myobj.getPhiRange();
|
||||
fw.indent() << "phiRange " << r.min << " " << r.max << std::endl;
|
||||
r = myobj.getInitialSpeedRange();
|
||||
fw.indent() << "initialSpeedRange " << r.min << " " << r.max << std::endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
30
src/osgParticle/IO_RandomRateCounter.cpp
Normal file
30
src/osgParticle/IO_RandomRateCounter.cpp
Normal file
@@ -0,0 +1,30 @@
|
||||
|
||||
#include <osgParticle/RandomRateCounter>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/Input>
|
||||
#include <osgDB/Output>
|
||||
|
||||
bool RandomRateCounter_readLocalData(osg::Object &obj, osgDB::Input &fr);
|
||||
bool RandomRateCounter_writeLocalData(const osg::Object &obj, osgDB::Output &fw);
|
||||
|
||||
osgDB::RegisterDotOsgWrapperProxy RandomRateCounter_Proxy
|
||||
(
|
||||
osgNew osgParticle::RandomRateCounter,
|
||||
"RandomRateCounter",
|
||||
"Object Counter VariableRateCounter RandomRateCounter",
|
||||
RandomRateCounter_readLocalData,
|
||||
RandomRateCounter_writeLocalData
|
||||
);
|
||||
|
||||
bool RandomRateCounter_readLocalData(osg::Object &, osgDB::Input &)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RandomRateCounter_writeLocalData(const osg::Object &, osgDB::Output &)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
59
src/osgParticle/IO_SectorPlacer.cpp
Normal file
59
src/osgParticle/IO_SectorPlacer.cpp
Normal file
@@ -0,0 +1,59 @@
|
||||
|
||||
#include <osgParticle/SectorPlacer>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/Input>
|
||||
#include <osgDB/Output>
|
||||
|
||||
bool SectorPlacer_readLocalData(osg::Object &obj, osgDB::Input &fr);
|
||||
bool SectorPlacer_writeLocalData(const osg::Object &obj, osgDB::Output &fw);
|
||||
|
||||
osgDB::RegisterDotOsgWrapperProxy SectorPlacer_Proxy
|
||||
(
|
||||
osgNew osgParticle::SectorPlacer,
|
||||
"SectorPlacer",
|
||||
"Object Placer CenteredPlacer SectorPlacer",
|
||||
SectorPlacer_readLocalData,
|
||||
SectorPlacer_writeLocalData
|
||||
);
|
||||
|
||||
bool SectorPlacer_readLocalData(osg::Object &obj, osgDB::Input &fr)
|
||||
{
|
||||
osgParticle::SectorPlacer &myobj = static_cast<osgParticle::SectorPlacer &>(obj);
|
||||
bool itAdvanced = false;
|
||||
|
||||
osgParticle::rangef r;
|
||||
if (fr[0].matchWord("radiusRange")) {
|
||||
if (fr[1].getFloat(r.min) && fr[2].getFloat(r.max)) {
|
||||
myobj.setRadiusRange(r);
|
||||
fr += 3;
|
||||
itAdvanced = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (fr[0].matchWord("phiRange")) {
|
||||
if (fr[1].getFloat(r.min) && fr[2].getFloat(r.max)) {
|
||||
myobj.setPhiRange(r);
|
||||
fr += 3;
|
||||
itAdvanced = true;
|
||||
}
|
||||
}
|
||||
|
||||
return itAdvanced;
|
||||
}
|
||||
|
||||
bool SectorPlacer_writeLocalData(const osg::Object &obj, osgDB::Output &fw)
|
||||
{
|
||||
const osgParticle::SectorPlacer &myobj = static_cast<const osgParticle::SectorPlacer &>(obj);
|
||||
|
||||
osgParticle::rangef r;
|
||||
|
||||
r = myobj.getRadiusRange();
|
||||
fw.indent() << "radiusRange " << r.min << " " << r.max << std::endl;
|
||||
r = myobj.getPhiRange();
|
||||
fw.indent() << "phiRange " << r.min << " " << r.max << std::endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
60
src/osgParticle/IO_SegmentPlacer.cpp
Normal file
60
src/osgParticle/IO_SegmentPlacer.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
|
||||
#include <osgParticle/SegmentPlacer>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/Input>
|
||||
#include <osgDB/Output>
|
||||
|
||||
#include <osg/Vec3>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
bool SegmentPlacer_readLocalData(osg::Object &obj, osgDB::Input &fr);
|
||||
bool SegmentPlacer_writeLocalData(const osg::Object &obj, osgDB::Output &fw);
|
||||
|
||||
osgDB::RegisterDotOsgWrapperProxy SegmentPlacer_Proxy
|
||||
(
|
||||
osgNew osgParticle::SegmentPlacer,
|
||||
"SegmentPlacer",
|
||||
"Object Placer SegmentPlacer",
|
||||
SegmentPlacer_readLocalData,
|
||||
SegmentPlacer_writeLocalData
|
||||
);
|
||||
|
||||
bool SegmentPlacer_readLocalData(osg::Object &obj, osgDB::Input &fr)
|
||||
{
|
||||
osgParticle::SegmentPlacer &myobj = static_cast<osgParticle::SegmentPlacer &>(obj);
|
||||
bool itAdvanced = false;
|
||||
|
||||
osg::Vec3 v;
|
||||
|
||||
if (fr[0].matchWord("vertex_A")) {
|
||||
if (fr[1].getFloat(v.x()) && fr[2].getFloat(v.y()) && fr[3].getFloat(v.z())) {
|
||||
myobj.setVertexA(v);
|
||||
fr += 4;
|
||||
itAdvanced = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (fr[0].matchWord("vertex_B")) {
|
||||
if (fr[1].getFloat(v.x()) && fr[2].getFloat(v.y()) && fr[3].getFloat(v.z())) {
|
||||
myobj.setVertexB(v);
|
||||
fr += 4;
|
||||
itAdvanced = true;
|
||||
}
|
||||
}
|
||||
|
||||
return itAdvanced;
|
||||
}
|
||||
|
||||
bool SegmentPlacer_writeLocalData(const osg::Object &obj, osgDB::Output &fw)
|
||||
{
|
||||
const osgParticle::SegmentPlacer &myobj = static_cast<const osgParticle::SegmentPlacer &>(obj);
|
||||
|
||||
osg::Vec3 v = myobj.getVertexA();
|
||||
fw.indent() << "vertex_A " << v.x() << " " << v.y() << " " << v.z() << std::endl;
|
||||
v = myobj.getVertexB();
|
||||
fw.indent() << "vertex_B " << v.x() << " " << v.y() << " " << v.z() << std::endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
47
src/osgParticle/IO_VariableRateCounter.cpp
Normal file
47
src/osgParticle/IO_VariableRateCounter.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
|
||||
#include <osgParticle/VariableRateCounter>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/Input>
|
||||
#include <osgDB/Output>
|
||||
|
||||
bool VariableRateCounter_readLocalData(osg::Object &obj, osgDB::Input &fr);
|
||||
bool VariableRateCounter_writeLocalData(const osg::Object &obj, osgDB::Output &fw);
|
||||
|
||||
osgDB::RegisterDotOsgWrapperProxy VariableRateCounter_Proxy
|
||||
(
|
||||
0,
|
||||
"VariableRateCounter",
|
||||
"Object Counter VariableRateCounter",
|
||||
VariableRateCounter_readLocalData,
|
||||
VariableRateCounter_writeLocalData
|
||||
);
|
||||
|
||||
bool VariableRateCounter_readLocalData(osg::Object &obj, osgDB::Input &fr)
|
||||
{
|
||||
osgParticle::VariableRateCounter &myobj = static_cast<osgParticle::VariableRateCounter &>(obj);
|
||||
bool itAdvanced = false;
|
||||
|
||||
osgParticle::rangef r;
|
||||
if (fr[0].matchWord("rateRange")) {
|
||||
if (fr[1].getFloat(r.min) && fr[2].getFloat(r.max)) {
|
||||
myobj.setRateRange(r);
|
||||
fr += 3;
|
||||
itAdvanced = true;
|
||||
}
|
||||
}
|
||||
|
||||
return itAdvanced;
|
||||
}
|
||||
|
||||
bool VariableRateCounter_writeLocalData(const osg::Object &obj, osgDB::Output &fw)
|
||||
{
|
||||
const osgParticle::VariableRateCounter &myobj = static_cast<const osgParticle::VariableRateCounter &>(obj);
|
||||
|
||||
osgParticle::rangef r = myobj.getRateRange();
|
||||
fw.indent() << "rateRange " << r.min << " " << r.max << std::endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
45
src/osgParticle/Makefile
Normal file
45
src/osgParticle/Makefile
Normal file
@@ -0,0 +1,45 @@
|
||||
TOPDIR = ../..
|
||||
include $(TOPDIR)/Make/makedefs
|
||||
|
||||
CXXFILES =\
|
||||
Emitter.cpp\
|
||||
FluidFrictionOperator.cpp\
|
||||
IO_AccelOperator.cpp\
|
||||
IO_CenteredPlacer.cpp\
|
||||
IO_Emitter.cpp\
|
||||
IO_FluidFrictionOperator.cpp\
|
||||
IO_ForceOperator.cpp\
|
||||
IO_LinearInterpolator.cpp\
|
||||
IO_ModularEmitter.cpp\
|
||||
IO_ModularProgram.cpp\
|
||||
IO_MultiSegmentPlacer.cpp\
|
||||
IO_Particle.cpp\
|
||||
IO_ParticleProcessor.cpp\
|
||||
IO_ParticleSystem.cpp\
|
||||
IO_ParticleSystemUpdater.cpp\
|
||||
IO_PointPlacer.cpp\
|
||||
IO_Program.cpp\
|
||||
IO_RadialShooter.cpp\
|
||||
IO_RandomRateCounter.cpp\
|
||||
IO_SectorPlacer.cpp\
|
||||
IO_SegmentPlacer.cpp\
|
||||
IO_VariableRateCounter.cpp\
|
||||
ModularEmitter.cpp\
|
||||
ModularProgram.cpp\
|
||||
MultiSegmentPlacer.cpp\
|
||||
Particle.cpp\
|
||||
ParticleProcessor.cpp\
|
||||
ParticleSystem.cpp\
|
||||
ParticleSystemUpdater.cpp\
|
||||
Program.cpp\
|
||||
Version.cpp\
|
||||
|
||||
|
||||
|
||||
LIBS += -losg $(OTHER_LIBS) $(DYNAMICLIBRARYLIB)
|
||||
DEF += -DOSGPARTICLE_LIBRARY
|
||||
|
||||
TARGET_BASENAME = osgParticle
|
||||
LIB = $(LIB_PREFIX)$(TARGET_BASENAME).$(LIB_EXT)
|
||||
|
||||
include $(TOPDIR)/Make/makerules
|
||||
33
src/osgParticle/ModularEmitter.cpp
Normal file
33
src/osgParticle/ModularEmitter.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
#include <osgParticle/ModularEmitter>
|
||||
#include <osgParticle/Emitter>
|
||||
|
||||
osgParticle::ModularEmitter::ModularEmitter()
|
||||
: Emitter(),
|
||||
counter_(osgNew RandomRateCounter),
|
||||
placer_(osgNew PointPlacer),
|
||||
shooter_(osgNew RadialShooter)
|
||||
{
|
||||
}
|
||||
|
||||
osgParticle::ModularEmitter::ModularEmitter(const ModularEmitter ©, const osg::CopyOp ©op)
|
||||
: Emitter(copy, copyop),
|
||||
counter_(static_cast<Counter *>(copyop(copy.counter_.get()))),
|
||||
placer_(static_cast<Placer *>(copyop(copy.placer_.get()))),
|
||||
shooter_(static_cast<Shooter *>(copyop(copy.shooter_.get())))
|
||||
{
|
||||
}
|
||||
|
||||
void osgParticle::ModularEmitter::emit(double dt)
|
||||
{
|
||||
int n = counter_->numParticlesToCreate(dt);
|
||||
for (int i=0; i<n; ++i) {
|
||||
Particle *P = getParticleSystem()->createParticle(getUseDefaultTemplate()? 0: &getParticleTemplate());
|
||||
if (P) {
|
||||
placer_->place(P);
|
||||
shooter_->shoot(P);
|
||||
if (getReferenceFrame() == RELATIVE_TO_PARENTS) {
|
||||
P->transformPositionVelocity(getLocalToWorldMatrix());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
37
src/osgParticle/ModularProgram.cpp
Normal file
37
src/osgParticle/ModularProgram.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
#include <osgParticle/ModularProgram>
|
||||
#include <osgParticle/Program>
|
||||
#include <osgParticle/ParticleSystem>
|
||||
#include <osgParticle/Particle>
|
||||
|
||||
osgParticle::ModularProgram::ModularProgram()
|
||||
: Program()
|
||||
{
|
||||
}
|
||||
|
||||
osgParticle::ModularProgram::ModularProgram(const ModularProgram ©, const osg::CopyOp ©op)
|
||||
: Program(copy, copyop)
|
||||
{
|
||||
Operator_vector::const_iterator ci;
|
||||
for (ci=copy.operators_.begin(); ci!=copy.operators_.end(); ++ci) {
|
||||
operators_.push_back(static_cast<Operator *>(copyop(ci->get())));
|
||||
}
|
||||
}
|
||||
|
||||
void osgParticle::ModularProgram::execute(double dt)
|
||||
{
|
||||
Operator_vector::iterator ci;
|
||||
Operator_vector::iterator ci_end = operators_.end();
|
||||
|
||||
ParticleSystem *ps = getParticleSystem();
|
||||
for (ci=operators_.begin(); ci!=ci_end; ++ci) {
|
||||
(*ci)->beginOperate(this);
|
||||
int n = ps->numParticles();
|
||||
for (int i=0; i<n; ++i) {
|
||||
Particle *P = ps->getParticle(i);
|
||||
if (P->isAlive() && (*ci)->isEnabled()) {
|
||||
(*ci)->operate(P, dt);
|
||||
}
|
||||
}
|
||||
(*ci)->endOperate();
|
||||
}
|
||||
}
|
||||
51
src/osgParticle/MultiSegmentPlacer.cpp
Normal file
51
src/osgParticle/MultiSegmentPlacer.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
#include <osgParticle/MultiSegmentPlacer>
|
||||
#include <osgParticle/Placer>
|
||||
|
||||
#include <osg/CopyOp>
|
||||
#include <osg/Vec3>
|
||||
|
||||
osgParticle::MultiSegmentPlacer::MultiSegmentPlacer()
|
||||
: Placer(), total_length_(0)
|
||||
{
|
||||
}
|
||||
|
||||
osgParticle::MultiSegmentPlacer::MultiSegmentPlacer(const MultiSegmentPlacer ©, const osg::CopyOp ©op)
|
||||
: Placer(copy, copyop), vx_(copy.vx_), total_length_(copy.total_length_)
|
||||
{
|
||||
}
|
||||
|
||||
void osgParticle::MultiSegmentPlacer::recompute_length()
|
||||
{
|
||||
Vertex_vector::iterator i;
|
||||
Vertex_vector::iterator i0 = vx_.begin();
|
||||
|
||||
total_length_ = 0;
|
||||
for (i=vx_.begin(); i!=vx_.end(); ++i) {
|
||||
total_length_ += (i->first - i0->first).length();
|
||||
i->second = total_length_;
|
||||
i0 = i;
|
||||
}
|
||||
}
|
||||
|
||||
void osgParticle::MultiSegmentPlacer::place(Particle *P) const
|
||||
{
|
||||
if (vx_.size() >= 2) {
|
||||
float x = rangef(0, total_length_).get_random();
|
||||
|
||||
Vertex_vector::const_iterator i;
|
||||
Vertex_vector::const_iterator i0 = vx_.begin();
|
||||
const Vertex_vector::const_iterator vend = vx_.end();
|
||||
|
||||
for (i=vx_.begin(); i!=vend; ++i) {
|
||||
if (x <= i->second) {
|
||||
float t = (x - i0->second) / (i->second - i0->second);
|
||||
P->setPosition(i0->first + (i->first - i0->first) * t);
|
||||
return;
|
||||
}
|
||||
i0 = i;
|
||||
}
|
||||
} else {
|
||||
osg::notify(osg::WARN) << "this MultiSegmentPlacer has less than 2 vertices\n";
|
||||
}
|
||||
}
|
||||
|
||||
146
src/osgParticle/Particle.cpp
Normal file
146
src/osgParticle/Particle.cpp
Normal file
@@ -0,0 +1,146 @@
|
||||
#include <osgParticle/Particle>
|
||||
#include <osgParticle/LinearInterpolator>
|
||||
|
||||
#include <osg/Vec3>
|
||||
#include <osg/Vec4>
|
||||
#include <osg/Matrix>
|
||||
#include <osg/GL>
|
||||
#include <osg/Notify>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
const float cosPI3 = cosf(osg::PI / 3.0f);
|
||||
const float sinPI3 = sinf(osg::PI / 3.0f);
|
||||
const float hex_texcoord_x1 = 0.5f + 0.5f * cosPI3;
|
||||
const float hex_texcoord_x2 = 0.5f - 0.5f * cosPI3;
|
||||
const float hex_texcoord_y1 = 0.5f + 0.5f * sinPI3;
|
||||
const float hex_texcoord_y2 = 0.5f - 0.5f * sinPI3;
|
||||
|
||||
}
|
||||
|
||||
osgParticle::Particle::Particle()
|
||||
: shape_(QUAD),
|
||||
sr_(0.2f, 0.2f),
|
||||
ar_(1, 0),
|
||||
cr_(osg::Vec4(1, 1, 1, 1), osg::Vec4(1, 1, 1, 1)),
|
||||
si_(osgNew LinearInterpolator),
|
||||
ai_(osgNew LinearInterpolator),
|
||||
ci_(osgNew LinearInterpolator),
|
||||
alive_(true),
|
||||
mustdie_(false),
|
||||
lifetime_(2),
|
||||
radius_(0.2f),
|
||||
mass_(0.1f),
|
||||
massinv_(10.0f),
|
||||
prev_pos_(0, 0, 0),
|
||||
position_(0, 0, 0),
|
||||
velocity_(0, 0, 0),
|
||||
t0_(0)
|
||||
{
|
||||
}
|
||||
|
||||
bool osgParticle::Particle::update(double dt)
|
||||
{
|
||||
// this method should return false when the particle dies;
|
||||
// so, if we were instructed to die, do it now and return.
|
||||
if (mustdie_) {
|
||||
alive_ = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
double x = 0;
|
||||
|
||||
// if we don't live forever, compute our normalized age.
|
||||
if (lifetime_ > 0) {
|
||||
x = t0_ / lifetime_;
|
||||
}
|
||||
|
||||
t0_ += dt;
|
||||
|
||||
// if our age is over the lifetime limit, then die and return.
|
||||
if (x > 1) {
|
||||
alive_ = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
// compute the current values for size, alpha and color.
|
||||
current_size_ = si_.get()->interpolate(x, sr_);
|
||||
current_alpha_ = ai_.get()->interpolate(x, ar_);
|
||||
current_color_ = ci_.get()->interpolate(x, cr_);
|
||||
|
||||
// update position
|
||||
prev_pos_ = position_;
|
||||
position_ += velocity_ * dt;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void osgParticle::Particle::render(const osg::Matrix &modelview, float scale) const
|
||||
{
|
||||
osg::Vec3 xpos = modelview.preMult(position_);
|
||||
|
||||
glColor4f( current_color_.x(),
|
||||
current_color_.y(),
|
||||
current_color_.z(),
|
||||
current_color_.w() * current_alpha_);
|
||||
|
||||
float cs = current_size_ * scale;
|
||||
|
||||
switch (shape_)
|
||||
{
|
||||
case POINT:
|
||||
glVertex3f(xpos.x(), xpos.y(), xpos.z());
|
||||
break;
|
||||
|
||||
case QUAD:
|
||||
glTexCoord2f(0, 0);
|
||||
glVertex3f(xpos.x() - cs, xpos.y() - cs, xpos.z());
|
||||
glTexCoord2f(1, 0);
|
||||
glVertex3f(xpos.x() + cs, xpos.y() - cs, xpos.z());
|
||||
glTexCoord2f(1, 1);
|
||||
glVertex3f(xpos.x() + cs, xpos.y() + cs, xpos.z());
|
||||
glTexCoord2f(0, 1);
|
||||
glVertex3f(xpos.x() - cs, xpos.y() + cs, xpos.z());
|
||||
break;
|
||||
|
||||
case QUAD_TRIANGLESTRIP:
|
||||
// we must glBegin() and glEnd() here, because each particle is a single strip
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
glTexCoord2f(1, 1);
|
||||
glVertex3f(xpos.x() + cs, xpos.y() + cs, xpos.z());
|
||||
glTexCoord2f(0, 1);
|
||||
glVertex3f(xpos.x() - cs, xpos.y() + cs, xpos.z());
|
||||
glTexCoord2f(1, 0);
|
||||
glVertex3f(xpos.x() + cs, xpos.y() - cs, xpos.z());
|
||||
glTexCoord2f(0, 0);
|
||||
glVertex3f(xpos.x() - cs, xpos.y() - cs, xpos.z());
|
||||
glEnd();
|
||||
break;
|
||||
|
||||
case HEXAGON:
|
||||
// we must glBegin() and glEnd() here, because each particle is a single fan
|
||||
glBegin(GL_TRIANGLE_FAN);
|
||||
glTexCoord2f(0.5f, 0.5f);
|
||||
glVertex3f(xpos.x(), xpos.y(), xpos.z());
|
||||
glTexCoord2f(hex_texcoord_x1, hex_texcoord_y1);
|
||||
glVertex3f(xpos.x() + cs * cosPI3, xpos.y() + cs * sinPI3, xpos.z());
|
||||
glTexCoord2f(hex_texcoord_x2, hex_texcoord_y1);
|
||||
glVertex3f(xpos.x() - cs * cosPI3, xpos.y() + cs * sinPI3, xpos.z());
|
||||
glTexCoord2f(0, 0.5f);
|
||||
glVertex3f(xpos.x() - cs, xpos.y(), xpos.z());
|
||||
glTexCoord2f(hex_texcoord_x2, hex_texcoord_y2);
|
||||
glVertex3f(xpos.x() - cs * cosPI3, xpos.y() - cs * sinPI3, xpos.z());
|
||||
glTexCoord2f(hex_texcoord_x1, hex_texcoord_y2);
|
||||
glVertex3f(xpos.x() + cs * cosPI3, xpos.y() - cs * sinPI3, xpos.z());
|
||||
glTexCoord2f(1, 0.5f);
|
||||
glVertex3f(xpos.x() + cs, xpos.y(), xpos.z());
|
||||
glTexCoord2f(hex_texcoord_x1, hex_texcoord_y1);
|
||||
glVertex3f(xpos.x() + cs * cosPI3, xpos.y() + cs * sinPI3, xpos.z());
|
||||
glEnd();
|
||||
break;
|
||||
|
||||
default:
|
||||
osg::notify(osg::WARN) << "Invalid shape for particles\n";
|
||||
}
|
||||
}
|
||||
75
src/osgParticle/ParticleProcessor.cpp
Normal file
75
src/osgParticle/ParticleProcessor.cpp
Normal file
@@ -0,0 +1,75 @@
|
||||
#include <osgParticle/ParticleProcessor>
|
||||
|
||||
#include <osg/Node>
|
||||
#include <osg/NodeVisitor>
|
||||
#include <osg/CopyOp>
|
||||
#include <osg/Matrix>
|
||||
#include <osg/Notify>
|
||||
|
||||
#include <osgUtil/CullVisitor>
|
||||
|
||||
osgParticle::ParticleProcessor::ParticleProcessor()
|
||||
: osg::Node(),
|
||||
rf_(RELATIVE_TO_PARENTS),
|
||||
enabled_(true),
|
||||
t0_(-1),
|
||||
ps_(0)
|
||||
{
|
||||
setCullingActive(false);
|
||||
}
|
||||
|
||||
osgParticle::ParticleProcessor::ParticleProcessor(const ParticleProcessor ©, const osg::CopyOp ©op)
|
||||
: osg::Node(copy, copyop),
|
||||
rf_(copy.rf_),
|
||||
enabled_(copy.enabled_),
|
||||
t0_(copy.t0_),
|
||||
ps_(static_cast<ParticleSystem *>(copyop(copy.ps_.get())))
|
||||
{
|
||||
}
|
||||
|
||||
void osgParticle::ParticleProcessor::traverse(osg::NodeVisitor &nv)
|
||||
{
|
||||
// continue only if enabled
|
||||
if (enabled_) {
|
||||
|
||||
// typecast the NodeVisitor to CullVisitor
|
||||
osgUtil::CullVisitor *cv = dynamic_cast<osgUtil::CullVisitor *>(&nv);
|
||||
|
||||
// continue only if the visitor actually is a cull visitor
|
||||
if (cv) {
|
||||
|
||||
// continue only if the particle system is valid
|
||||
if (ps_.valid()) {
|
||||
|
||||
// retrieve the current time
|
||||
double t = nv.getFrameStamp()->getReferenceTime();
|
||||
|
||||
// skip if we haven't initialized t0_ yet
|
||||
if (t0_ != -1) {
|
||||
|
||||
// check whether the particle system is frozen/culled
|
||||
if (!ps_->isFrozen() && (ps_->getLastFrameNumber() >= (nv.getFrameStamp()->getFrameNumber() - 1) || !ps_->getFreezeOnCull())) {
|
||||
|
||||
// initialize matrix flags
|
||||
need_ltw_matrix_ = true;
|
||||
need_wtl_matrix_ = true;
|
||||
current_nodevisitor_ = &nv;
|
||||
|
||||
// do some process (unimplemented in this base class)
|
||||
process(t - t0_);
|
||||
}
|
||||
}
|
||||
|
||||
// update t0_
|
||||
t0_ = t;
|
||||
|
||||
} else {
|
||||
osg::notify(osg::WARN) << "ParticleProcessor \"" << getName() << "\": invalid particle system\n";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// call the inherited method
|
||||
osg::Node::traverse(nv);
|
||||
}
|
||||
201
src/osgParticle/ParticleSystem.cpp
Normal file
201
src/osgParticle/ParticleSystem.cpp
Normal file
@@ -0,0 +1,201 @@
|
||||
#include <osgParticle/ParticleSystem>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <osg/Drawable>
|
||||
#include <osg/CopyOp>
|
||||
#include <osg/State>
|
||||
#include <osg/Matrix>
|
||||
#include <osg/GL>
|
||||
#include <osg/StateSet>
|
||||
#include <osg/Texture>
|
||||
#include <osg/Transparency>
|
||||
#include <osg/TexEnv>
|
||||
#include <osg/Material>
|
||||
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
osgParticle::ParticleSystem::ParticleSystem()
|
||||
: osg::Drawable(),
|
||||
def_bbox_(osg::Vec3(-10, -10, -10), osg::Vec3(10, 10, 10)),
|
||||
doublepass_(false),
|
||||
frozen_(false),
|
||||
display_list_id_(-1),
|
||||
bmin_(0, 0, 0),
|
||||
bmax_(0, 0, 0),
|
||||
bounds_computed_(false),
|
||||
def_ptemp_(Particle()),
|
||||
last_frame_(0),
|
||||
freeze_on_cull_(true),
|
||||
detail_(1),
|
||||
draw_count_(0)
|
||||
{
|
||||
// we don't support display lists because particle systems
|
||||
// are dynamic, and they always changes between frames
|
||||
setSupportsDisplayList(false);
|
||||
}
|
||||
|
||||
osgParticle::ParticleSystem::ParticleSystem(const ParticleSystem ©, const osg::CopyOp ©op)
|
||||
: osg::Drawable(copy, copyop),
|
||||
def_bbox_(copy.def_bbox_),
|
||||
doublepass_(copy.doublepass_),
|
||||
frozen_(copy.frozen_),
|
||||
display_list_id_(-1),
|
||||
bmin_(copy.bmin_),
|
||||
bmax_(copy.bmax_),
|
||||
bounds_computed_(copy.bounds_computed_),
|
||||
def_ptemp_(copy.def_ptemp_),
|
||||
last_frame_(copy.last_frame_),
|
||||
freeze_on_cull_(copy.freeze_on_cull_),
|
||||
detail_(copy.detail_),
|
||||
draw_count_(0)
|
||||
{
|
||||
}
|
||||
|
||||
osgParticle::ParticleSystem::~ParticleSystem()
|
||||
{
|
||||
}
|
||||
|
||||
void osgParticle::ParticleSystem::update(double dt)
|
||||
{
|
||||
// reset bounds
|
||||
reset_bounds_flag_ = true;
|
||||
|
||||
// set up iterators for particles
|
||||
Particle_vector::iterator i;
|
||||
Particle_vector::iterator end = particles_.end();
|
||||
|
||||
// update particles
|
||||
for (i=particles_.begin(); i!=end; ++i) {
|
||||
if (i->isAlive()) {
|
||||
if (i->update(dt)) {
|
||||
update_bounds(i->getPosition());
|
||||
} else {
|
||||
deadparts_.push(&(*i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// force recomputing of bounding box on next frame
|
||||
dirtyBound();
|
||||
}
|
||||
|
||||
void osgParticle::ParticleSystem::drawImmediateMode(osg::State &state)
|
||||
{
|
||||
// update the frame count, so other objects can detect when
|
||||
// this particle system is culled
|
||||
last_frame_ = state.getFrameStamp()->getFrameNumber();
|
||||
|
||||
// get the current modelview matrix
|
||||
const osg::Matrix &modelview = state.getModelViewMatrix();
|
||||
|
||||
// set modelview = identity
|
||||
state.applyModelViewMatrix(0);
|
||||
|
||||
// set up depth mask for first rendering pass
|
||||
glPushAttrib(GL_DEPTH_BUFFER_BIT);
|
||||
glDepthMask(GL_FALSE);
|
||||
|
||||
// render, first pass
|
||||
if (doublepass_) {
|
||||
|
||||
// generate a display list ID if necessary
|
||||
if (display_list_id_ == -1) {
|
||||
display_list_id_ = glGenLists(1);
|
||||
}
|
||||
|
||||
#ifdef USE_SEPERATE_COMPILE_AND_EXECUTE
|
||||
glNewList(display_list_id_, GL_COMPILE);
|
||||
single_pass_render(modelview);
|
||||
glEndList();
|
||||
glCallList(display_list_id_);
|
||||
#else
|
||||
glNewList(display_list_id_, GL_COMPILE_AND_EXECUTE);
|
||||
single_pass_render(modelview);
|
||||
glEndList();
|
||||
#endif
|
||||
|
||||
} else {
|
||||
single_pass_render(modelview);
|
||||
}
|
||||
|
||||
// restore depth mask settings
|
||||
glPopAttrib();
|
||||
|
||||
// render, second pass
|
||||
if (doublepass_) {
|
||||
// set up color mask for second rendering pass
|
||||
glPushAttrib(GL_COLOR_BUFFER_BIT);
|
||||
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
||||
|
||||
// call the display list to render the particles onto the depth buffer
|
||||
glCallList(display_list_id_);
|
||||
|
||||
// restore color mask settings
|
||||
glPopAttrib();
|
||||
}
|
||||
}
|
||||
|
||||
void osgParticle::ParticleSystem::setDefaultAttributes(const std::string &texturefile, bool emissive_particles, bool lighting)
|
||||
{
|
||||
osg::StateSet *stateset = osgNew osg::StateSet;
|
||||
|
||||
stateset->setMode(GL_LIGHTING, lighting? osg::StateAttribute::ON: osg::StateAttribute::OFF);
|
||||
stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
|
||||
|
||||
osg::Material *material = osgNew osg::Material;
|
||||
material->setSpecular(osg::Material::FRONT, osg::Vec4(0, 0, 0, 1));
|
||||
material->setEmission(osg::Material::FRONT, osg::Vec4(0, 0, 0, 1));
|
||||
material->setColorMode(lighting? osg::Material::AMBIENT_AND_DIFFUSE : osg::Material::OFF);
|
||||
stateset->setAttributeAndModes(material, osg::StateAttribute::ON);
|
||||
|
||||
if (!texturefile.empty()) {
|
||||
osg::Texture *texture = osgNew osg::Texture;
|
||||
texture->setImage(osgDB::readImageFile(texturefile));
|
||||
texture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
|
||||
texture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
|
||||
stateset->setAttributeAndModes(texture, osg::StateAttribute::ON);
|
||||
|
||||
osg::TexEnv *texenv = osgNew osg::TexEnv;
|
||||
texenv->setMode(osg::TexEnv::MODULATE);
|
||||
stateset->setAttribute(texenv);
|
||||
}
|
||||
|
||||
osg::Transparency *transparency = osgNew osg::Transparency;
|
||||
if (emissive_particles) {
|
||||
transparency->setFunction(osg::Transparency::SRC_ALPHA, osg::Transparency::ONE);
|
||||
} else {
|
||||
transparency->setFunction(osg::Transparency::SRC_ALPHA, osg::Transparency::ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
stateset->setAttributeAndModes(transparency, osg::StateAttribute::ON);
|
||||
|
||||
setStateSet(stateset);
|
||||
}
|
||||
|
||||
|
||||
void osgParticle::ParticleSystem::single_pass_render(const osg::Matrix &modelview)
|
||||
{
|
||||
draw_count_ = 0;
|
||||
if (particles_.size() <= 0) return;
|
||||
|
||||
Particle_vector::iterator i;
|
||||
Particle_vector::iterator i0 = particles_.begin();
|
||||
Particle_vector::iterator end = particles_.end();
|
||||
|
||||
i0->beginRender();
|
||||
|
||||
for (i=i0; i<end; i+=detail_) {
|
||||
if (i->isAlive()) {
|
||||
if (i->getShape() != i0->getShape()) {
|
||||
i0->endRender();
|
||||
i->beginRender();
|
||||
i0 = i;
|
||||
}
|
||||
++draw_count_;
|
||||
i->render(modelview, sqrtf(static_cast<float>(detail_)));
|
||||
}
|
||||
}
|
||||
|
||||
i0->endRender();
|
||||
|
||||
}
|
||||
37
src/osgParticle/ParticleSystemUpdater.cpp
Normal file
37
src/osgParticle/ParticleSystemUpdater.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
#include <osgParticle/ParticleSystemUpdater>
|
||||
|
||||
#include <osg/CopyOp>
|
||||
#include <osg/Node>
|
||||
|
||||
osgParticle::ParticleSystemUpdater::ParticleSystemUpdater()
|
||||
: osg::Node(), t0_(-1)
|
||||
{
|
||||
setCullingActive(false);
|
||||
}
|
||||
|
||||
osgParticle::ParticleSystemUpdater::ParticleSystemUpdater(const ParticleSystemUpdater ©, const osg::CopyOp ©op)
|
||||
: osg::Node(copy, copyop), t0_(copy.t0_)
|
||||
{
|
||||
ParticleSystem_Vector::const_iterator i;
|
||||
for (i=copy.psv_.begin(); i!=copy.psv_.end(); ++i) {
|
||||
psv_.push_back(static_cast<ParticleSystem *>(copyop(i->get())));
|
||||
}
|
||||
}
|
||||
|
||||
void osgParticle::ParticleSystemUpdater::traverse(osg::NodeVisitor &nv)
|
||||
{
|
||||
osgUtil::CullVisitor *cv = dynamic_cast<osgUtil::CullVisitor *>(&nv);
|
||||
if (cv) {
|
||||
double t = nv.getFrameStamp()->getReferenceTime();
|
||||
if (t0_ != -1) {
|
||||
ParticleSystem_Vector::iterator i;
|
||||
for (i=psv_.begin(); i!=psv_.end(); ++i) {
|
||||
if (!i->get()->isFrozen() && (i->get()->getLastFrameNumber() >= (nv.getFrameStamp()->getFrameNumber() - 1) || !i->get()->getFreezeOnCull())) {
|
||||
i->get()->update(t - t0_);
|
||||
}
|
||||
}
|
||||
}
|
||||
t0_ = t;
|
||||
}
|
||||
osg::Node::traverse(nv);
|
||||
}
|
||||
14
src/osgParticle/Program.cpp
Normal file
14
src/osgParticle/Program.cpp
Normal file
@@ -0,0 +1,14 @@
|
||||
#include <osgParticle/Program>
|
||||
#include <osgParticle/ParticleProcessor>
|
||||
|
||||
#include <osg/CopyOp>
|
||||
|
||||
osgParticle::Program::Program()
|
||||
: ParticleProcessor()
|
||||
{
|
||||
}
|
||||
|
||||
osgParticle::Program::Program(const Program ©, const osg::CopyOp ©op)
|
||||
: ParticleProcessor(copy, copyop)
|
||||
{
|
||||
}
|
||||
12
src/osgParticle/Version.cpp
Normal file
12
src/osgParticle/Version.cpp
Normal file
@@ -0,0 +1,12 @@
|
||||
#include <osgParticle/Version>
|
||||
|
||||
const char* osgParticleGetVersion()
|
||||
{
|
||||
return "0.8.45";
|
||||
}
|
||||
|
||||
|
||||
const char* osgParticleGetLibraryName()
|
||||
{
|
||||
return "Open Scene Graph Particle Library";
|
||||
}
|
||||
Reference in New Issue
Block a user