// Copyright (C) 2002-2003 Gideon May (gideon@computer.org) // // Permission to copy, use, sell and distribute this software is granted // provided this copyright notice appears in all copies. // Permission to modify the code and to distribute modified code is granted // provided this copyright notice appears in all copies, and a notice // that the code was modified is included with the copyright notice. // // This software is provided "as is" without express or implied warranty, // and with no claim as to its suitability for any purpose. // #include #include #include #include #include #include #include using namespace boost::python; namespace { class Particle : public osgParticle::Particle { public: Particle(PyObject * self) : osgParticle::Particle(), self_(self), has_render_(-1), has_beginRender_(-1), has_endRender_(-1) {} ~Particle() {} inline void beginRender() const { if (has_beginRender_ == -1) { has_beginRender_ = PyObject_HasAttrString(self_, "beginRender") ? 1 : 0; } if (has_beginRender_) { try { return call_method(self_, "beginRender"); } catch(...) { handle_exception(); PyErr_Print(); throw_error_already_set(); return; } } else { osgParticle::Particle::beginRender(); } } inline void endRender() const { if (has_endRender_ == -1) { has_endRender_ = PyObject_HasAttrString(self_, "endRender") ? 1 : 0; } if (has_endRender_) { try { return call_method(self_, "endRender"); } catch(...) { handle_exception(); PyErr_Print(); throw_error_already_set(); return; } } else { osgParticle::Particle::endRender(); } } void render(const osg::Vec3 &xpos, const osg::Vec3 &px, const osg::Vec3 &py, float scale = 1.0f) const { if (has_render_ == -1) { has_render_ = PyObject_HasAttrString(self_, "render") ? 1 : 0; } if (has_render_) { try { return call_method(self_, "render", xpos, px, py, scale); } catch(...) { handle_exception(); PyErr_Print(); throw_error_already_set(); return; } } else { osgParticle::Particle::render(xpos, px, py, scale); } } protected: PyObject * self_; mutable int has_render_; mutable int has_beginRender_; mutable int has_endRender_; }; } namespace PyOSGParticle { void init_Particle() { class_ particle("Particle", "Implementation of a particle.\n" "Objects of this class are particles, they have some graphical properties\n" "and some physical properties. Particles are created by emitters and then placed\n" "into Particle Systems, where they live and get updated at each frame.\n" "Particles can either live forever (lifeTime < 0), or die after a specified\n" "time (lifeTime >= 0). For each property which is defined as a range of values, a\n" "'current' value will be evaluated at each frame by interpolating the min\n" "and max values so that curr_value = min when t == 0, and \n" "curr_value = max when t == lifeTime.\n" "You may customize the interpolator objects to achieve any kind of transition.\n" "If you want the particle to live forever, set its lifetime to any value <= 0;\n" "in that case, no interpolation is done to compute real-time properties, and only\n" "minimum values are used.", no_init); scope particle_scope(particle); particle .def(init<>()) .def("getShape", &osgParticle::Particle::getShape, "Get the shape of the particle.") .def("setShape", &osgParticle::Particle::setShape, "Set the shape of the particle.") .def("isAlive", &osgParticle::Particle::isAlive, "Get whether the particle is still alive.") .def("getLifeTime", &osgParticle::Particle::getLifeTime, "Get the life time of the particle (in seconds).") .def("getAge", &osgParticle::Particle::getAge, "Get the age of the particle (in seconds).") ; particle.def("getSizeRange", &osgParticle::Particle::getSizeRange, "Get the minimum and maximum values for polygon size.", return_internal_reference<>()); particle.def("getAlphaRange", &osgParticle::Particle::getAlphaRange, "Get the minimum and maximum values for alpha.", return_internal_reference<>()); particle.def("getColorRange", &osgParticle::Particle::getColorRange, "Get the minimum and maximum values for color.", return_internal_reference<>()); particle.def("getSizeInterpolator", &osgParticle::Particle::getSizeInterpolator, "Get the interpolator for computing the size of polygons.", return_internal_reference<>()); particle.def("getAlphaInterpolator", &osgParticle::Particle::getAlphaInterpolator, "Get the interpolator for computing alpha values.", return_internal_reference<>()); particle.def("getColorInterpolator", &osgParticle::Particle::getColorInterpolator, "Get the interpolator for computing color values.", return_internal_reference<>()); particle.def("getRadius", &osgParticle::Particle::getRadius, "Get the physical radius of the particle." "For built-in operators to work correctly, lengths must be expressed in meters."); particle.def("getMass", &osgParticle::Particle::getMass, "Get the mass of the particle.\n" "For built-in operators to work correctly, remember that the mass is expressed in kg."); particle.def("getMassInv", &osgParticle::Particle::getMassInv, "Get 1 / getMass()."); particle.def("getPosition", &osgParticle::Particle::getPosition, "Get the position vector.", return_internal_reference<>()); particle.def("getVelocity", &osgParticle::Particle::getVelocity, "Get the velocity vector.\n" "For built-in operators to work correctly, remember that velocity components are expressed\n" "in meters per second.", return_internal_reference<>()); particle.def("getPreviousPosition", &osgParticle::Particle::getPreviousPosition, "Get the previous position (the position before last update).", return_internal_reference<>()); particle.def("kill", &osgParticle::Particle::kill, "Kill the particle on next update\n" "NOTE: after calling this function, the isAlive() method will still \n" "return true until the particle is updated again."); particle.def("setLifeTime", &osgParticle::Particle::setLifeTime, "Set the life time of the particle."); particle.def("setSizeRange", &osgParticle::Particle::setSizeRange, "Set the minimum and maximum values for polygon size."); particle.def("setAlphaRange", &osgParticle::Particle::setAlphaRange, "Set the minimum and maximum values for alpha."); particle.def("setColorRange", &osgParticle::Particle::setColorRange, "Set the minimum and maximum values for color."); particle.def("setSizeInterpolator", &osgParticle::Particle::setSizeInterpolator, "Set the interpolator for computing size values."); particle.def("setAlphaInterpolator", &osgParticle::Particle::setAlphaInterpolator, "Set the interpolator for computing alpha values. "); particle.def("setColorInterpolator", &osgParticle::Particle::setColorInterpolator, "Set the interpolator for computing color values."); particle.def("setRadius", &osgParticle::Particle::setRadius, "Set the physical radius of the particle.\n" "For built-in operators to work correctly, lengths must be expressed in meters."); particle.def("setMass", &osgParticle::Particle::setMass, "Set the mass of the particle.\n" "For built-in operators to work correctly, remember that the mass is expressed in kg."); particle.def("setPosition", &osgParticle::Particle::setPosition, "Set the position vector"); particle.def("setVelocity", &osgParticle::Particle::setVelocity, "Set the velocity vector.\n" "For built-in operators to work correctly, remember that velocity components are expressed\n" "in meters per second."); particle.def("addVelocity", &osgParticle::Particle::addVelocity, "Add a vector to the velocity vector."); particle.def("transformPositionVelocity", ( void (osgParticle::Particle::*)(const osg::Matrix&)) &osgParticle::Particle::transformPositionVelocity, "Transform position and velocity vectors by a matrix."); particle.def("transformPositionVelocity", ( void (osgParticle::Particle::*)(const osg::Matrix&, const osg::Matrix&, float)) &osgParticle::Particle::transformPositionVelocity, "Transform position and velocity vectors by a combination of two matrices."); particle.def("getCurrentSize", &osgParticle::Particle::getCurrentSize, "Get the current (interpolated) polygon size. Valid only after the first call to update()."); enum_ shape("Shape"); # define OSG_ENUM(VALUE) \ (shape.value(#VALUE, osgParticle::Particle::VALUE), \ particle.def(#VALUE, object(osgParticle::Particle::VALUE))) OSG_ENUM(POINT); // uses GL_POINTS as primitive OSG_ENUM(QUAD); // uses GL_QUADS as primitive OSG_ENUM(QUAD_TRIANGLESTRIP); // uses GL_TRIANGLE_STRIP as primitive, but each particle needs a glBegin/glEnd pair OSG_ENUM(HEXAGON); // may save some filling time, but uses more triangles scope(); } }