00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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
00028
00029
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
00052
00053
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
00074
00075
00076
00077 SpriteParticleRenderer::
00078 ~SpriteParticleRenderer(void) {
00079 }
00080
00081
00082
00083
00084
00085
00086 BaseParticleRenderer *SpriteParticleRenderer::
00087 make_copy(void) {
00088 return new SpriteParticleRenderer(*this);
00089 }
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099 void SpriteParticleRenderer::
00100 set_from_node(const NodePath &node_path) {
00101 nassertv(!node_path.is_empty());
00102
00103
00104
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
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
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
00162
00163
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
00172
00173
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
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
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
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
00228
00229
00230
00231
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
00244
00245
00246
00247
00248
00249 void SpriteParticleRenderer::
00250 birth_particle(int) {
00251 }
00252
00253
00254
00255
00256
00257
00258 void SpriteParticleRenderer::
00259 kill_particle(int) {
00260 }
00261
00262
00263
00264
00265
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
00290 _aabb_min.set(99999.0f, 99999.0f, 99999.0f);
00291 _aabb_max.set(-99999.0f, -99999.0f, -99999.0f);
00292
00293
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
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
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
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
00319 *cur_vert++ = cur_particle->get_position();
00320
00321
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
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
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
00363 if (_animate_theta == true)
00364 *cur_theta++ = cur_particle->get_theta();
00365
00366
00367 remaining_particles--;
00368 if (remaining_particles == 0)
00369 break;
00370 }
00371
00372 _sprite_primitive->set_num_prims(ttl_particles);
00373
00374
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 }