Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

panda/src/particlesystem/spriteParticleRenderer.cxx

Go to the documentation of this file.
00001 // Filename: spriteParticleRenderer.cxx
00002 // Created by:  charles (13Jul00)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 #include "spriteParticleRenderer.h"
00020 
00021 #include "boundingSphere.h"
00022 #include "geom.h"
00023 #include "nodePath.h"
00024 #include "dcast.h"
00025 
00026 ////////////////////////////////////////////////////////////////////
00027 //    Function : SpriteParticleRenderer::SpriteParticleRenderer
00028 //      Access : public
00029 // Description : constructor
00030 ////////////////////////////////////////////////////////////////////
00031 SpriteParticleRenderer::
00032 SpriteParticleRenderer(Texture *tex) :
00033   BaseParticleRenderer(PR_ALPHA_NONE),
00034   _color(Colorf(1.0f, 1.0f, 1.0f, 1.0f)),
00035   _initial_x_texel_ratio(0.02f),
00036   _final_x_texel_ratio(0.02f),
00037   _initial_y_texel_ratio(0.02f),
00038   _final_y_texel_ratio(0.02f),
00039   _theta(0.0f),
00040   _animate_x_ratio(false),
00041   _animate_y_ratio(false),
00042   _animate_theta(false),
00043   _blend_method(PP_BLEND_LINEAR),
00044   _pool_size(0)
00045 {
00046   _sprite_primitive = new GeomSprite(tex);
00047   init_geoms();
00048 }
00049 
00050 ////////////////////////////////////////////////////////////////////
00051 //    Function : SpriteParticleRenderer::SpriteParticleRenderer
00052 //      Access : public
00053 // Description : copy constructor
00054 ////////////////////////////////////////////////////////////////////
00055 SpriteParticleRenderer::
00056 SpriteParticleRenderer(const SpriteParticleRenderer& copy) :
00057   BaseParticleRenderer(copy), _pool_size(0) {
00058   _animate_x_ratio = copy._animate_x_ratio;
00059   _animate_y_ratio = copy._animate_y_ratio;
00060   _animate_theta = copy._animate_theta;
00061   _blend_method = copy._blend_method;
00062   _initial_x_texel_ratio = copy._initial_x_texel_ratio;
00063   _final_x_texel_ratio = copy._final_x_texel_ratio;
00064   _initial_y_texel_ratio = copy._initial_y_texel_ratio;
00065   _final_y_texel_ratio = copy._final_y_texel_ratio;
00066   _theta = copy._theta;
00067   _color = copy._color;
00068   _sprite_primitive = new GeomSprite(copy.get_texture());
00069   init_geoms();
00070 }
00071 
00072 ////////////////////////////////////////////////////////////////////
00073 //    Function : SpriteParticleRenderer::~SpriteParticleRenderer
00074 //      Access : public
00075 // Description : destructor
00076 ////////////////////////////////////////////////////////////////////
00077 SpriteParticleRenderer::
00078 ~SpriteParticleRenderer(void) {
00079 }
00080 
00081 ////////////////////////////////////////////////////////////////////
00082 //    Function : SpriteParticleRenderer::make_copy
00083 //      Access : public
00084 // Description : child dynamic copy
00085 ////////////////////////////////////////////////////////////////////
00086 BaseParticleRenderer *SpriteParticleRenderer::
00087 make_copy(void) {
00088   return new SpriteParticleRenderer(*this);
00089 }
00090 
00091 ////////////////////////////////////////////////////////////////////
00092 //    Function : SpriteParticleRenderer::set_from_node
00093 //      Access : public
00094 // Description : Sets the properties on this render from the geometry
00095 //               referenced by the indicated NodePath.  This should be
00096 //               a reference to a GeomNode; it extracts out the
00097 //               Texture and UV range from the GeomNode.
00098 ////////////////////////////////////////////////////////////////////
00099 void SpriteParticleRenderer::
00100 set_from_node(const NodePath &node_path) {
00101   nassertv(!node_path.is_empty());
00102 
00103   // The bottom node must be a GeomNode.  If it is not, find the first
00104   // GeomNode beneath it.
00105   NodePath geom_node_path = node_path;
00106   if (!geom_node_path.node()->is_geom_node()) {
00107     geom_node_path = node_path.find("**/+GeomNode");
00108     if (geom_node_path.is_empty()) {
00109       particlesystem_cat.error()
00110         << node_path << " does not contain a GeomNode.\n";
00111       return;
00112     }
00113   }
00114   GeomNode *gnode = DCAST(GeomNode, geom_node_path.node());
00115 
00116   // Get the texture off the node.  We'll take just the first texture.
00117   Texture *tex = geom_node_path.find_texture("*");
00118 
00119   if (tex == (Texture *)NULL) {
00120     particlesystem_cat.error()
00121       << geom_node_path << " has no texture.\n";
00122     return;
00123   }
00124 
00125   // Now examine the UV's of the first Geom within the GeomNode.
00126   nassertv(gnode->get_num_geoms() > 0);
00127   Geom *geom = gnode->get_geom(0);
00128 
00129   PTA_TexCoordf texcoords;
00130   GeomBindType bind;
00131   PTA_ushort tindex;
00132   geom->get_texcoords(texcoords, bind, tindex);
00133   if (bind != G_PER_VERTEX) {
00134     particlesystem_cat.error()
00135       << geom_node_path << " has no UV's in its first Geom.\n";
00136     return;
00137   }
00138 
00139   int num_verts = geom->get_num_vertices();
00140   if (num_verts == 0) {
00141     particlesystem_cat.error()
00142       << geom_node_path << " has no vertices in its first Geom.\n";
00143     return;
00144   }
00145 
00146   Geom::TexCoordIterator ti = geom->make_texcoord_iterator();
00147 
00148   const TexCoordf &first_texcoord = geom->get_next_texcoord(ti);
00149   TexCoordf min_uv = first_texcoord;
00150   TexCoordf max_uv = first_texcoord;
00151 
00152   for (int v = 1; v < num_verts; v++) {
00153     const TexCoordf &texcoord = geom->get_next_texcoord(ti);    
00154 
00155     min_uv[0] = min(min_uv[0], texcoord[0]);
00156     max_uv[0] = max(max_uv[0], texcoord[0]);
00157     min_uv[1] = min(min_uv[1], texcoord[1]);
00158     max_uv[1] = max(max_uv[1], texcoord[1]);
00159   }
00160 
00161   // We don't really pay attention to orientation of UV's here; a
00162   // minor flaw.  We assume the minimum is in the lower-left, and the
00163   // maximum is in the upper-right.
00164   set_texture(tex);
00165   set_ll_uv(min_uv);
00166   set_ur_uv(max_uv);
00167   _source_type = ST_from_node;
00168 }
00169 
00170 ////////////////////////////////////////////////////////////////////
00171 //    Function : SpriteParticleRenderer::resize_pool
00172 //      Access : private
00173 // Description : reallocate the vertex pool.
00174 ////////////////////////////////////////////////////////////////////
00175 void SpriteParticleRenderer::
00176 resize_pool(int new_size) {
00177   if (new_size == _pool_size)
00178     return;
00179 
00180   _pool_size = new_size;
00181 
00182   GeomBindType _x_bind, _y_bind, _theta_bind;
00183 
00184   // handle the x texel ratio
00185   if (_animate_x_ratio == true) {
00186     _x_texel_array = PTA_float::empty_array(new_size);
00187     _x_bind = G_PER_PRIM;
00188   }
00189   else {
00190     _x_texel_array = PTA_float::empty_array(1);
00191     _x_bind = G_OVERALL;
00192   }
00193 
00194   // handle the y texel ratio
00195   if (_animate_y_ratio == true) {
00196     _y_texel_array = PTA_float::empty_array(new_size);
00197     _y_bind = G_PER_PRIM;
00198   }
00199   else {
00200     _y_texel_array = PTA_float::empty_array(1);
00201     _y_bind = G_OVERALL;
00202   }
00203 
00204   // handle the theta vector
00205   if (_animate_theta == true) {
00206     _theta_array = PTA_float::empty_array(new_size);
00207     _theta_bind = G_PER_PRIM;
00208   }
00209   else {
00210     _theta_array = PTA_float::empty_array(1);
00211     _theta_bind = G_OVERALL;
00212   }
00213 
00214   _vertex_array = PTA_Vertexf::empty_array(new_size);
00215   _color_array = PTA_Colorf::empty_array(new_size);
00216 
00217   _sprite_primitive->set_coords(_vertex_array);
00218   _sprite_primitive->set_colors(_color_array, G_PER_PRIM);
00219   _sprite_primitive->set_x_texel_ratio(_x_texel_array, _x_bind);
00220   _sprite_primitive->set_y_texel_ratio(_y_texel_array, _y_bind);
00221   _sprite_primitive->set_thetas(_theta_array, _theta_bind);
00222 
00223   init_geoms();
00224 }
00225 
00226 ////////////////////////////////////////////////////////////////////
00227 //    Function : SpriteParticleRenderer::init_geoms
00228 //      Access : private
00229 // Description : initializes everything, called on traumatic events
00230 //               such as construction and serious particlesystem
00231 //               modifications
00232 ////////////////////////////////////////////////////////////////////
00233 void SpriteParticleRenderer::
00234 init_geoms(void) {
00235   _sprite_primitive->set_num_prims(0);
00236 
00237   GeomNode *render_node = get_render_node();
00238   render_node->remove_all_geoms();
00239   render_node->add_geom(_sprite_primitive, _render_state);
00240 }
00241 
00242 ////////////////////////////////////////////////////////////////////
00243 //    Function : SpriteParticleRenderer::birth_particle
00244 //      Access : private
00245 // Description : child birth, one of those 'there-if-we-want-it'
00246 //               things.  not really too useful here, so it turns
00247 //               out we don't really want it.
00248 ////////////////////////////////////////////////////////////////////
00249 void SpriteParticleRenderer::
00250 birth_particle(int) {
00251 }
00252 
00253 ////////////////////////////////////////////////////////////////////
00254 //    Function : SpriteParticleRenderer::kill_particle
00255 //      Access : private
00256 // Description : child death
00257 ////////////////////////////////////////////////////////////////////
00258 void SpriteParticleRenderer::
00259 kill_particle(int) {
00260 }
00261 
00262 ////////////////////////////////////////////////////////////////////
00263 //    Function : SpriteParticleRenderer::render
00264 //      Access : private
00265 // Description : big child render.  populates the geom node.
00266 ////////////////////////////////////////////////////////////////////
00267 void SpriteParticleRenderer::
00268 render(pvector< PT(PhysicsObject) >& po_vector, int ttl_particles) {
00269   BaseParticle *cur_particle;
00270 
00271   int remaining_particles = ttl_particles;
00272   int i;
00273 
00274   Vertexf *cur_vert = &_vertex_array[0];
00275   Colorf *cur_color = &_color_array[0];
00276   float *cur_x_texel = &_x_texel_array[0];
00277   float *cur_y_texel = &_y_texel_array[0];
00278   float *cur_theta = &_theta_array[0];
00279 
00280   if (_animate_x_ratio == false)
00281     *cur_x_texel = _initial_x_texel_ratio;
00282 
00283   if (_animate_y_ratio == false)
00284     *cur_y_texel = _initial_y_texel_ratio;
00285 
00286   if (_animate_theta == false)
00287     *cur_theta = _theta;
00288 
00289   // init the aabb
00290   _aabb_min.set(99999.0f, 99999.0f, 99999.0f);
00291   _aabb_max.set(-99999.0f, -99999.0f, -99999.0f);
00292 
00293   // run through every filled slot
00294   for (i = 0; i < (int)po_vector.size(); i++) {
00295     cur_particle = (BaseParticle *) po_vector[i].p();
00296 
00297     if (cur_particle->get_alive() == false)
00298       continue;
00299 
00300     // x aabb adjust
00301     if (cur_particle->get_position().get_x() > _aabb_max.get_x())
00302       _aabb_max[0] = cur_particle->get_position().get_x();
00303     else if (cur_particle->get_position().get_x() < _aabb_min.get_x())
00304       _aabb_min[0] = cur_particle->get_position().get_x();
00305 
00306     // y aabb adjust
00307     if (cur_particle->get_position().get_y() > _aabb_max.get_y())
00308       _aabb_max[1] = cur_particle->get_position().get_y();
00309     else if (cur_particle->get_position().get_y() < _aabb_min.get_y())
00310       _aabb_min[1] = cur_particle->get_position().get_y();
00311 
00312     // z aabb adjust
00313     if (cur_particle->get_position().get_z() > _aabb_max.get_z())
00314       _aabb_max[2] = cur_particle->get_position().get_z();
00315     else if (cur_particle->get_position().get_z() < _aabb_min.get_z())
00316       _aabb_min[2] = cur_particle->get_position().get_z();
00317 
00318     // put the current vertex into the array
00319     *cur_vert++ = cur_particle->get_position();
00320 
00321     // put the current color into the array
00322     Colorf c = _color;
00323 
00324     int alphamode=get_alpha_mode();
00325     if (alphamode != PR_ALPHA_NONE) {
00326       float t = cur_particle->get_parameterized_age();
00327 
00328       if (alphamode == PR_ALPHA_OUT)
00329         c[3] = (1.0f - t) * get_user_alpha();
00330       else if (alphamode == PR_ALPHA_IN)
00331         c[3] = t * get_user_alpha();
00332       else {
00333         assert(alphamode == PR_ALPHA_USER);
00334         c[3] = get_user_alpha();
00335       }
00336     }
00337 
00338     *cur_color++ = c;
00339 
00340     // handle x scaling
00341     if (_animate_x_ratio == true) {
00342       float t = cur_particle->get_parameterized_age();
00343 
00344       if (_blend_method == PP_BLEND_CUBIC)
00345         t = CUBIC_T(t);
00346 
00347       *cur_x_texel++ = (_initial_x_texel_ratio +
00348         (t * (_final_x_texel_ratio - _initial_x_texel_ratio)));
00349     }
00350 
00351     // handle y scaling
00352     if (_animate_y_ratio == true) {
00353       float t = cur_particle->get_parameterized_age();
00354 
00355       if (_blend_method == PP_BLEND_CUBIC)
00356         t = CUBIC_T(t);
00357 
00358       *cur_y_texel++ = (_initial_y_texel_ratio +
00359         (t * (_final_y_texel_ratio - _initial_y_texel_ratio)));
00360     }
00361 
00362     // handle theta
00363     if (_animate_theta == true)
00364       *cur_theta++ = cur_particle->get_theta();
00365 
00366     // maybe jump out early?
00367     remaining_particles--;
00368     if (remaining_particles == 0)
00369       break;
00370   }
00371 
00372   _sprite_primitive->set_num_prims(ttl_particles);
00373 
00374   // done filling geompoint node, now do the bb stuff
00375   LPoint3f aabb_center = _aabb_min + ((_aabb_max - _aabb_min) * 0.5f);
00376   float radius = (aabb_center - _aabb_min).length();
00377 
00378   _sprite_primitive->set_bound(BoundingSphere(aabb_center, radius));
00379   get_render_node()->mark_bound_stale();
00380 }

Generated on Fri May 2 00:41:01 2003 for Panda by doxygen1.3