Checked in osgParticle, writtten by Marco Jez.

This commit is contained in:
Robert Osfield
2002-06-05 12:44:55 +00:00
parent f8ffc692be
commit 9ba7505d1e
110 changed files with 10467 additions and 0 deletions

View 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

View 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

View 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;
}

View 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 &copy, const osg::CopyOp &copyop)
: ParticleProcessor(copy, copyop),
usedeftemp_(copy.usedeftemp_),
ptemp_(copy.ptemp_)
{
}

View 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 &copy, const osg::CopyOp &copyop)
: 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));
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

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

View 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 &copy, const osg::CopyOp &copyop)
: 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());
}
}
}
}

View 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 &copy, const osg::CopyOp &copyop)
: 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();
}
}

View 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 &copy, const osg::CopyOp &copyop)
: 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";
}
}

View 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";
}
}

View 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 &copy, const osg::CopyOp &copyop)
: 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);
}

View 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 &copy, const osg::CopyOp &copyop)
: 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();
}

View 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 &copy, const osg::CopyOp &copyop)
: 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);
}

View File

@@ -0,0 +1,14 @@
#include <osgParticle/Program>
#include <osgParticle/ParticleProcessor>
#include <osg/CopyOp>
osgParticle::Program::Program()
: ParticleProcessor()
{
}
osgParticle::Program::Program(const Program &copy, const osg::CopyOp &copyop)
: ParticleProcessor(copy, copyop)
{
}

View File

@@ -0,0 +1,12 @@
#include <osgParticle/Version>
const char* osgParticleGetVersion()
{
return "0.8.45";
}
const char* osgParticleGetLibraryName()
{
return "Open Scene Graph Particle Library";
}