Panda3D
pointParticleRenderer.cxx
1 // Filename: pointParticleRenderer.cxx
2 // Created by: charles (20Jun00)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "pointParticleRenderer.h"
16 #include "boundingSphere.h"
17 #include "geomNode.h"
18 #include "geom.h"
19 #include "geomVertexWriter.h"
20 #include "indent.h"
21 #include "pStatTimer.h"
22 
23 PStatCollector PointParticleRenderer::_render_collector("App:Particles:Point:Render");
24 
25 ////////////////////////////////////////////////////////////////////
26 // Function : PointParticleRenderer
27 // Access : Public
28 // Description : special constructor
29 ////////////////////////////////////////////////////////////////////
30 
32 PointParticleRenderer(ParticleRendererAlphaMode am,
33  PN_stdfloat point_size,
34  PointParticleBlendType bt,
35  ParticleRendererBlendMethod bm,
36  const LColor& sc, const LColor& ec) :
38  _start_color(sc), _end_color(ec),
39  _blend_type(bt), _blend_method(bm)
40 {
41  set_point_size(point_size);
42  resize_pool(0);
43 }
44 
45 ////////////////////////////////////////////////////////////////////
46 // Function : PointParticleRenderer
47 // Access : Public
48 // Description : Copy constructor
49 ////////////////////////////////////////////////////////////////////
50 
54 {
55  _blend_type = copy._blend_type;
56  _blend_method = copy._blend_method;
57  _start_color = copy._start_color;
58  _end_color = copy._end_color;
59  _point_size = copy._point_size;
60  _thick = copy._thick;
61  resize_pool(0);
62 }
63 
64 ////////////////////////////////////////////////////////////////////
65 // Function : ~PointParticleRenderer
66 // Access : Public
67 // Description : Simple destructor
68 ////////////////////////////////////////////////////////////////////
69 
72 }
73 
74 ////////////////////////////////////////////////////////////////////
75 // Function : make_copy
76 // Access : Public
77 // Description : for spawning systems from dead particles
78 ////////////////////////////////////////////////////////////////////
79 
82  return new PointParticleRenderer(*this);
83 }
84 
85 ////////////////////////////////////////////////////////////////////
86 // Function : resize_pool
87 // Access : Public
88 // Description : reallocate the space for the vertex and color
89 // pools
90 ////////////////////////////////////////////////////////////////////
91 
92 void PointParticleRenderer::
93 resize_pool(int new_size) {
94  if (new_size == _max_pool_size)
95  return;
96 
97  _max_pool_size = new_size;
98 
99  init_geoms();
100 }
101 
102 ////////////////////////////////////////////////////////////////////
103 // Function : init_geoms
104 // Access : Private
105 // Description : On-construction initialization
106 ////////////////////////////////////////////////////////////////////
107 
108 void PointParticleRenderer::
109 init_geoms() {
110  _vdata = new GeomVertexData
111  ("point_particles", GeomVertexFormat::get_v3cp(),
112  Geom::UH_stream);
113  PT(Geom) geom = new Geom(_vdata);
114  _point_primitive = geom;
115  _points = new GeomPoints(Geom::UH_stream);
116  geom->add_primitive(_points);
117 
118  GeomNode *render_node = get_render_node();
119  render_node->remove_all_geoms();
120  render_node->add_geom(_point_primitive, _render_state->add_attrib(_thick));
121 }
122 
123 ////////////////////////////////////////////////////////////////////
124 // Function : birth_particle
125 // Access : Private, virtual
126 // Description : child birth
127 ////////////////////////////////////////////////////////////////////
128 
129 void PointParticleRenderer::
130 birth_particle(int) {
131 }
132 
133 ////////////////////////////////////////////////////////////////////
134 // Function : kill_particle
135 // Access : Private, virtual
136 // Description : child kill
137 ////////////////////////////////////////////////////////////////////
138 
139 void PointParticleRenderer::
140 kill_particle(int) {
141 }
142 
143 ////////////////////////////////////////////////////////////////////
144 // Function : create_color
145 // Access : Private
146 // Description : Generates the point color based on the render_type
147 ////////////////////////////////////////////////////////////////////
148 
149 LColor PointParticleRenderer::
150 create_color(const BaseParticle *p) {
151  LColor color;
152  PN_stdfloat life_t, vel_t;
153  PN_stdfloat parameterized_age = 1.0f;
154  bool have_alpha_t = false;
155 
156  switch (_blend_type) {
157 
158  //// Constant solid color
159 
160  case PP_ONE_COLOR:
161  color = _start_color;
162  break;
163 
164  //// Blending colors based on life
165 
166  case PP_BLEND_LIFE:
167  parameterized_age = p->get_parameterized_age();
168  life_t = parameterized_age;
169  have_alpha_t = true;
170 
171  if (_blend_method == PP_BLEND_CUBIC)
172  life_t = CUBIC_T(life_t);
173 
174  color = LERP(life_t, _start_color, _end_color);
175 
176  break;
177 
178  //// Blending colors based on vel
179 
180  case PP_BLEND_VEL:
181  vel_t = p->get_parameterized_vel();
182 
183  if (_blend_method == PP_BLEND_CUBIC)
184  vel_t = CUBIC_T(vel_t);
185 
186  color = LERP(vel_t, _start_color, _end_color);
187 
188  break;
189  }
190 
191  // handle alpha channel
192 
193  if(_alpha_mode != PR_ALPHA_NONE) {
194  if(_alpha_mode == PR_ALPHA_USER) {
195  parameterized_age = 1.0;
196  } else {
197  if(!have_alpha_t)
198  parameterized_age = p->get_parameterized_age();
199 
200  if(_alpha_mode==PR_ALPHA_OUT) {
201  parameterized_age = 1.0f - parameterized_age;
202  } else if(_alpha_mode==PR_ALPHA_IN_OUT) {
203  parameterized_age = 2.0f * min(parameterized_age,
204  1.0f - parameterized_age);
205  }
206  }
207  color[3] = parameterized_age * get_user_alpha();
208  }
209 
210  return color;
211 }
212 
213 ////////////////////////////////////////////////////////////////////
214 // Function : render
215 // Access : Public
216 // Description : renders the particle system out to a GeomNode
217 ////////////////////////////////////////////////////////////////////
218 
219 void PointParticleRenderer::
220 render(pvector< PT(PhysicsObject) >& po_vector, int ttl_particles) {
221  PStatTimer t1(_render_collector);
222 
223  BaseParticle *cur_particle;
224 
225  int remaining_particles = ttl_particles;
226  int i;
227 
228  GeomVertexWriter vertex(_vdata, InternalName::get_vertex());
229  GeomVertexWriter color(_vdata, InternalName::get_color());
230 
231  // init the aabb
232 
233  _aabb_min.set(99999.0f, 99999.0f, 99999.0f);
234  _aabb_max.set(-99999.0f, -99999.0f, -99999.0f);
235 
236  // run through every filled slot
237 
238  for (i = 0; i < (int)po_vector.size(); i++) {
239  cur_particle = (BaseParticle *) po_vector[i].p();
240 
241  if (!cur_particle->get_alive())
242  continue;
243 
244  LPoint3 position = cur_particle->get_position();
245 
246  // x aabb adjust
247 
248  if (position[0] > _aabb_max[0])
249  _aabb_max[0] = position[0];
250  else if (position[0] < _aabb_min[0])
251  _aabb_min[0] = position[0];
252 
253  // y aabb adjust
254 
255  if (position[1] > _aabb_max[1])
256  _aabb_max[1] = position[1];
257  else if (position[1] < _aabb_min[1])
258  _aabb_min[1] = position[1];
259 
260  // z aabb adjust
261 
262  if (position[2] > _aabb_max[2])
263  _aabb_max[2] = position[2];
264  else if (position[2] < _aabb_min[2])
265  _aabb_min[2] = position[2];
266 
267  // stuff it into the arrays
268 
269  vertex.add_data3(position);
270  color.add_data4(create_color(cur_particle));
271 
272  // maybe jump out early?
273 
274  remaining_particles--;
275  if (remaining_particles == 0)
276  break;
277  }
278 
279  _points->clear_vertices();
280  _points->add_next_vertices(ttl_particles);
281 
282  // done filling geompoint node, now do the bb stuff
283 
284  LPoint3 aabb_center = _aabb_min + ((_aabb_max - _aabb_min) * 0.5f);
285  PN_stdfloat radius = (aabb_center - _aabb_min).length();
286 
287  BoundingSphere sphere(aabb_center, radius);
288  _point_primitive->set_bounds(&sphere);
289  get_render_node()->mark_internal_bounds_stale();
290 }
291 
292 ////////////////////////////////////////////////////////////////////
293 // Function : output
294 // Access : Public
295 // Description : Write a string representation of this instance to
296 // <out>.
297 ////////////////////////////////////////////////////////////////////
299 output(ostream &out) const {
300  #ifndef NDEBUG //[
301  out<<"PointParticleRenderer";
302  #endif //] NDEBUG
303 }
304 
305 ////////////////////////////////////////////////////////////////////
306 // Function : write
307 // Access : Public
308 // Description : Write a string representation of this instance to
309 // <out>.
310 ////////////////////////////////////////////////////////////////////
312 write(ostream &out, int indent_level) const {
313  indent(out, indent_level) << "PointParticleRenderer:\n";
314  indent(out, indent_level + 2) << "_start_color "<<_start_color<<"\n";
315  indent(out, indent_level + 2) << "_end_color "<<_end_color<<"\n";
316  indent(out, indent_level + 2) << "_point_size "<<_point_size<<"\n";
317  indent(out, indent_level + 2) << "_point_primitive "<<_point_primitive<<"\n";
318  indent(out, indent_level + 2) << "_max_pool_size "<<_max_pool_size<<"\n";
319  indent(out, indent_level + 2) << "_blend_type "<<_blend_type<<"\n";
320  indent(out, indent_level + 2) << "_blend_method "<<_blend_method<<"\n";
321  indent(out, indent_level + 2) << "_aabb_min "<<_aabb_min<<"\n";
322  indent(out, indent_level + 2) << "_aabb_max "<<_aabb_max<<"\n";
323  BaseParticleRenderer::write(out, indent_level + 2);
324 }
GeomNode * get_render_node() const
Query the geomnode pointer.
This object provides a high-level interface for quickly writing a sequence of numeric values from a v...
Defines a series of disconnected points.
Definition: geomPoints.h:25
This defines a bounding sphere, consisting of a center and a radius.
A body on which physics will be applied.
Definition: physicsObject.h:29
PointParticleRenderer(const PointParticleRenderer &copy)
Copy constructor.
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
Definition: pStatTimer.h:34
This is a three-component point in space (as opposed to a three-component vector, which represents a ...
Definition: lpoint3.h:99
void add_data4(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z, PN_stdfloat w)
Sets the write row to a particular 4-component value, and advances the write row. ...
virtual BaseParticleRenderer * make_copy()
for spawning systems from dead particles
This is our own Panda specialization on the default STL vector.
Definition: pvector.h:39
virtual void write(ostream &out, int indent_level=0) const
Write a string representation of this instance to <out>.
A lightweight class that represents a single element that may be timed and/or counted via stats...
Pure virtual particle renderer base class.
virtual void output(ostream &out) const
Write a string representation of this instance to <out>.
virtual ~PointParticleRenderer()
Simple destructor.
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
A container for geometry primitives.
Definition: geom.h:58
Simple point/point particle renderer.
void add_data3(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z)
Sets the write row to a particular 3-component value, and advances the write row. ...
PN_stdfloat get_user_alpha() const
gets alpha for "user" alpha mode
This is the base class for all three-component vectors and points.
Definition: lvecBase4.h:111
An individual, physically-modelable particle abstract base class.
Definition: baseParticle.h:26
LPoint3 get_position() const
Position Query.
virtual void write(ostream &out, int indent=0) const
Write a string representation of this instance to <out>.
A node that holds Geom objects, renderable pieces of geometry.
Definition: geomNode.h:37
void add_geom(Geom *geom, const RenderState *state=RenderState::make_empty())
Adds a new Geom to the node.
Definition: geomNode.cxx:642
void remove_all_geoms()
Removes all the geoms from the node at once.
Definition: geomNode.I:159