Panda3D
|
00001 // Filename: pointParticleRenderer.cxx 00002 // Created by: charles (20Jun00) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #include "pointParticleRenderer.h" 00016 #include "boundingSphere.h" 00017 #include "geomNode.h" 00018 #include "geom.h" 00019 #include "geomVertexWriter.h" 00020 #include "indent.h" 00021 #include "pStatTimer.h" 00022 00023 PStatCollector PointParticleRenderer::_render_collector("App:Particles:Point:Render"); 00024 00025 //////////////////////////////////////////////////////////////////// 00026 // Function : PointParticleRenderer 00027 // Access : Public 00028 // Description : special constructor 00029 //////////////////////////////////////////////////////////////////// 00030 00031 PointParticleRenderer:: 00032 PointParticleRenderer(ParticleRendererAlphaMode am, 00033 PN_stdfloat point_size, 00034 PointParticleBlendType bt, 00035 ParticleRendererBlendMethod bm, 00036 const LColor& sc, const LColor& ec) : 00037 BaseParticleRenderer(am), 00038 _start_color(sc), _end_color(ec), 00039 _blend_type(bt), _blend_method(bm) 00040 { 00041 set_point_size(point_size); 00042 resize_pool(0); 00043 } 00044 00045 //////////////////////////////////////////////////////////////////// 00046 // Function : PointParticleRenderer 00047 // Access : Public 00048 // Description : Copy constructor 00049 //////////////////////////////////////////////////////////////////// 00050 00051 PointParticleRenderer:: 00052 PointParticleRenderer(const PointParticleRenderer& copy) : 00053 BaseParticleRenderer(copy) 00054 { 00055 _blend_type = copy._blend_type; 00056 _blend_method = copy._blend_method; 00057 _start_color = copy._start_color; 00058 _end_color = copy._end_color; 00059 _point_size = copy._point_size; 00060 _thick = copy._thick; 00061 resize_pool(0); 00062 } 00063 00064 //////////////////////////////////////////////////////////////////// 00065 // Function : ~PointParticleRenderer 00066 // Access : Public 00067 // Description : Simple destructor 00068 //////////////////////////////////////////////////////////////////// 00069 00070 PointParticleRenderer:: 00071 ~PointParticleRenderer() { 00072 } 00073 00074 //////////////////////////////////////////////////////////////////// 00075 // Function : make_copy 00076 // Access : Public 00077 // Description : for spawning systems from dead particles 00078 //////////////////////////////////////////////////////////////////// 00079 00080 BaseParticleRenderer *PointParticleRenderer:: 00081 make_copy() { 00082 return new PointParticleRenderer(*this); 00083 } 00084 00085 //////////////////////////////////////////////////////////////////// 00086 // Function : resize_pool 00087 // Access : Public 00088 // Description : reallocate the space for the vertex and color 00089 // pools 00090 //////////////////////////////////////////////////////////////////// 00091 00092 void PointParticleRenderer:: 00093 resize_pool(int new_size) { 00094 if (new_size == _max_pool_size) 00095 return; 00096 00097 _max_pool_size = new_size; 00098 00099 init_geoms(); 00100 } 00101 00102 //////////////////////////////////////////////////////////////////// 00103 // Function : init_geoms 00104 // Access : Private 00105 // Description : On-construction initialization 00106 //////////////////////////////////////////////////////////////////// 00107 00108 void PointParticleRenderer:: 00109 init_geoms() { 00110 _vdata = new GeomVertexData 00111 ("point_particles", GeomVertexFormat::get_v3cp(), 00112 Geom::UH_stream); 00113 PT(Geom) geom = new Geom(_vdata); 00114 _point_primitive = geom; 00115 _points = new GeomPoints(Geom::UH_stream); 00116 geom->add_primitive(_points); 00117 00118 GeomNode *render_node = get_render_node(); 00119 render_node->remove_all_geoms(); 00120 render_node->add_geom(_point_primitive, _render_state->add_attrib(_thick)); 00121 } 00122 00123 //////////////////////////////////////////////////////////////////// 00124 // Function : birth_particle 00125 // Access : Private, virtual 00126 // Description : child birth 00127 //////////////////////////////////////////////////////////////////// 00128 00129 void PointParticleRenderer:: 00130 birth_particle(int) { 00131 } 00132 00133 //////////////////////////////////////////////////////////////////// 00134 // Function : kill_particle 00135 // Access : Private, virtual 00136 // Description : child kill 00137 //////////////////////////////////////////////////////////////////// 00138 00139 void PointParticleRenderer:: 00140 kill_particle(int) { 00141 } 00142 00143 //////////////////////////////////////////////////////////////////// 00144 // Function : create_color 00145 // Access : Private 00146 // Description : Generates the point color based on the render_type 00147 //////////////////////////////////////////////////////////////////// 00148 00149 LColor PointParticleRenderer:: 00150 create_color(const BaseParticle *p) { 00151 LColor color; 00152 PN_stdfloat life_t, vel_t; 00153 PN_stdfloat parameterized_age = 1.0f; 00154 bool have_alpha_t = false; 00155 00156 switch (_blend_type) { 00157 00158 //// Constant solid color 00159 00160 case PP_ONE_COLOR: 00161 color = _start_color; 00162 break; 00163 00164 //// Blending colors based on life 00165 00166 case PP_BLEND_LIFE: 00167 parameterized_age = p->get_parameterized_age(); 00168 life_t = parameterized_age; 00169 have_alpha_t = true; 00170 00171 if (_blend_method == PP_BLEND_CUBIC) 00172 life_t = CUBIC_T(life_t); 00173 00174 color = LERP(life_t, _start_color, _end_color); 00175 00176 break; 00177 00178 //// Blending colors based on vel 00179 00180 case PP_BLEND_VEL: 00181 vel_t = p->get_parameterized_vel(); 00182 00183 if (_blend_method == PP_BLEND_CUBIC) 00184 vel_t = CUBIC_T(vel_t); 00185 00186 color = LERP(vel_t, _start_color, _end_color); 00187 00188 break; 00189 } 00190 00191 // handle alpha channel 00192 00193 if(_alpha_mode != PR_ALPHA_NONE) { 00194 if(_alpha_mode == PR_ALPHA_USER) { 00195 parameterized_age = 1.0; 00196 } else { 00197 if(!have_alpha_t) 00198 parameterized_age = p->get_parameterized_age(); 00199 00200 if(_alpha_mode==PR_ALPHA_OUT) { 00201 parameterized_age = 1.0f - parameterized_age; 00202 } else if(_alpha_mode==PR_ALPHA_IN_OUT) { 00203 parameterized_age = 2.0f * min(parameterized_age, 00204 1.0f - parameterized_age); 00205 } 00206 } 00207 color[3] = parameterized_age * get_user_alpha(); 00208 } 00209 00210 return color; 00211 } 00212 00213 //////////////////////////////////////////////////////////////////// 00214 // Function : render 00215 // Access : Public 00216 // Description : renders the particle system out to a GeomNode 00217 //////////////////////////////////////////////////////////////////// 00218 00219 void PointParticleRenderer:: 00220 render(pvector< PT(PhysicsObject) >& po_vector, int ttl_particles) { 00221 PStatTimer t1(_render_collector); 00222 00223 BaseParticle *cur_particle; 00224 00225 int remaining_particles = ttl_particles; 00226 int i; 00227 00228 GeomVertexWriter vertex(_vdata, InternalName::get_vertex()); 00229 GeomVertexWriter color(_vdata, InternalName::get_color()); 00230 00231 // init the aabb 00232 00233 _aabb_min.set(99999.0f, 99999.0f, 99999.0f); 00234 _aabb_max.set(-99999.0f, -99999.0f, -99999.0f); 00235 00236 // run through every filled slot 00237 00238 for (i = 0; i < (int)po_vector.size(); i++) { 00239 cur_particle = (BaseParticle *) po_vector[i].p(); 00240 00241 if (!cur_particle->get_alive()) 00242 continue; 00243 00244 LPoint3 position = cur_particle->get_position(); 00245 00246 // x aabb adjust 00247 00248 if (position[0] > _aabb_max[0]) 00249 _aabb_max[0] = position[0]; 00250 else if (position[0] < _aabb_min[0]) 00251 _aabb_min[0] = position[0]; 00252 00253 // y aabb adjust 00254 00255 if (position[1] > _aabb_max[1]) 00256 _aabb_max[1] = position[1]; 00257 else if (position[1] < _aabb_min[1]) 00258 _aabb_min[1] = position[1]; 00259 00260 // z aabb adjust 00261 00262 if (position[2] > _aabb_max[2]) 00263 _aabb_max[2] = position[2]; 00264 else if (position[2] < _aabb_min[2]) 00265 _aabb_min[2] = position[2]; 00266 00267 // stuff it into the arrays 00268 00269 vertex.add_data3(position); 00270 color.add_data4(create_color(cur_particle)); 00271 00272 // maybe jump out early? 00273 00274 remaining_particles--; 00275 if (remaining_particles == 0) 00276 break; 00277 } 00278 00279 _points->clear_vertices(); 00280 _points->add_next_vertices(ttl_particles); 00281 00282 // done filling geompoint node, now do the bb stuff 00283 00284 LPoint3 aabb_center = _aabb_min + ((_aabb_max - _aabb_min) * 0.5f); 00285 PN_stdfloat radius = (aabb_center - _aabb_min).length(); 00286 00287 BoundingSphere sphere(aabb_center, radius); 00288 _point_primitive->set_bounds(&sphere); 00289 get_render_node()->mark_internal_bounds_stale(); 00290 } 00291 00292 //////////////////////////////////////////////////////////////////// 00293 // Function : output 00294 // Access : Public 00295 // Description : Write a string representation of this instance to 00296 // <out>. 00297 //////////////////////////////////////////////////////////////////// 00298 void PointParticleRenderer:: 00299 output(ostream &out) const { 00300 #ifndef NDEBUG //[ 00301 out<<"PointParticleRenderer"; 00302 #endif //] NDEBUG 00303 } 00304 00305 //////////////////////////////////////////////////////////////////// 00306 // Function : write 00307 // Access : Public 00308 // Description : Write a string representation of this instance to 00309 // <out>. 00310 //////////////////////////////////////////////////////////////////// 00311 void PointParticleRenderer:: 00312 write(ostream &out, int indent_level) const { 00313 indent(out, indent_level) << "PointParticleRenderer:\n"; 00314 indent(out, indent_level + 2) << "_start_color "<<_start_color<<"\n"; 00315 indent(out, indent_level + 2) << "_end_color "<<_end_color<<"\n"; 00316 indent(out, indent_level + 2) << "_point_size "<<_point_size<<"\n"; 00317 indent(out, indent_level + 2) << "_point_primitive "<<_point_primitive<<"\n"; 00318 indent(out, indent_level + 2) << "_max_pool_size "<<_max_pool_size<<"\n"; 00319 indent(out, indent_level + 2) << "_blend_type "<<_blend_type<<"\n"; 00320 indent(out, indent_level + 2) << "_blend_method "<<_blend_method<<"\n"; 00321 indent(out, indent_level + 2) << "_aabb_min "<<_aabb_min<<"\n"; 00322 indent(out, indent_level + 2) << "_aabb_max "<<_aabb_max<<"\n"; 00323 BaseParticleRenderer::write(out, indent_level + 2); 00324 }