Panda3D
cullableObject.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file cullableObject.cxx
10  * @author drose
11  * @date 2002-03-04
12  */
13 
14 #include "cullableObject.h"
15 #include "lightAttrib.h"
16 #include "nodePath.h"
17 #include "colorAttrib.h"
18 #include "texGenAttrib.h"
19 #include "textureAttrib.h"
20 #include "shaderAttrib.h"
21 #include "renderState.h"
22 #include "clockObject.h"
23 #include "cullTraverser.h"
24 #include "sceneSetup.h"
25 #include "lens.h"
26 #include "stateMunger.h"
27 #include "pStatTimer.h"
28 #include "geomVertexWriter.h"
29 #include "geomVertexReader.h"
30 #include "geomTriangles.h"
31 #include "light.h"
32 #include "lightMutexHolder.h"
33 
34 CullableObject::FormatMap CullableObject::_format_map;
35 LightMutex CullableObject::_format_lock;
36 
37 PStatCollector CullableObject::_munge_pcollector("*:Munge");
38 PStatCollector CullableObject::_munge_geom_pcollector("*:Munge:Geom");
39 PStatCollector CullableObject::_munge_sprites_pcollector("*:Munge:Sprites");
40 PStatCollector CullableObject::_munge_sprites_verts_pcollector("*:Munge:Sprites:Verts");
41 PStatCollector CullableObject::_munge_sprites_prims_pcollector("*:Munge:Sprites:Prims");
42 PStatCollector CullableObject::_sw_sprites_pcollector("SW Sprites");
43 
44 TypeHandle CullableObject::_type_handle;
45 
46 /**
47  * Uses the indicated GeomMunger to transform the geom and/or its vertices.
48  *
49  * If force is false, this may do nothing and return false if the vertex data
50  * is nonresident. If force is true, this will always return true, but it may
51  * have to block while the vertex data is paged in.
52  */
55  const CullTraverser *traverser, bool force) {
56  nassertr(munger != nullptr, false);
57 
58  Thread *current_thread = traverser->get_current_thread();
59  PStatTimer timer(_munge_pcollector, current_thread);
60  if (_geom != nullptr) {
61  GraphicsStateGuardianBase *gsg = traverser->get_gsg();
62  int gsg_bits = gsg->get_supported_geom_rendering();
63  if (!hardware_point_sprites) {
64  // If support for hardware point sprites or perspective-scaled points is
65  // disabled, we don't allow the GSG to tell us it supports them.
66  gsg_bits &= ~(Geom::GR_point_perspective | Geom::GR_point_sprite);
67  }
68  if (!hardware_points) {
69  // If hardware-points is off, we don't allow any kind of point
70  // rendering, except plain old one-pixel points;
71  gsg_bits &= ~(Geom::GR_point_bits & ~Geom::GR_point);
72  }
73  int geom_rendering;
74  int unsupported_bits;
75 
76  {
77  GeomPipelineReader geom_reader(_geom, current_thread);
78  _munged_data = geom_reader.get_vertex_data();
79 
80 #ifdef _DEBUG
81  {
82  GeomVertexDataPipelineReader data_reader(_munged_data, current_thread);
83  data_reader.check_array_readers();
84  nassertr(geom_reader.check_valid(&data_reader), false);
85  }
86 #endif // _DEBUG
87 
88  geom_rendering = geom_reader.get_geom_rendering();
89  geom_rendering = _state->get_geom_rendering(geom_rendering);
90  geom_rendering = _internal_transform->get_geom_rendering(geom_rendering);
91  unsupported_bits = geom_rendering & ~gsg_bits;
92 
93  if (unsupported_bits & Geom::GR_per_point_size) {
94  // If we have a shader that processes the point size, we can assume it
95  // does the right thing.
96  const ShaderAttrib *sattr;
97  if (_state->get_attrib(sattr) && sattr->get_flag(ShaderAttrib::F_shader_point_size)) {
98  unsupported_bits &= ~Geom::GR_per_point_size;
99  }
100  }
101 
102  if (geom_rendering & Geom::GR_point_bits) {
103  if (geom_reader.get_primitive_type() != Geom::PT_points) {
104  if (singular_points ||
105  (unsupported_bits & Geom::GR_render_mode_point) != 0) {
106  // Isolate the points so there's no unneeded overlap.
107  _geom = _geom->make_points();
108  }
109  }
110  }
111  if (unsupported_bits & Geom::GR_render_mode_wireframe) {
112  if (geom_reader.get_primitive_type() != Geom::PT_lines) {
113  _geom = _geom->make_lines();
114  }
115  }
116  }
117 
118  if ((unsupported_bits & Geom::GR_point_bits) != 0) {
119  // The GSG doesn't support rendering these fancy points directly; we
120  // have to render them in software instead. Munge them into quads.
121  // This will replace the _geom and _munged_data, and might also replace
122  // _state.
123  if (pgraph_cat.is_spam()) {
124  pgraph_cat.spam()
125  << "munge_points_to_quads() for geometry with bits: "
126  << std::hex << geom_rendering << ", unsupported: "
127  << (unsupported_bits & Geom::GR_point_bits) << std::dec << "\n";
128  }
129  if (!munge_points_to_quads(traverser, force)) {
130  return false;
131  }
132  }
133 
134  // Now invoke the munger to ensure the resulting geometry is in a GSG-
135  // friendly form.
136  {
137  PStatTimer timer(_munge_geom_pcollector, current_thread);
138  if (!munger->munge_geom(_geom, _munged_data, force, current_thread)) {
139  return false;
140  }
141  }
142 
143  // If we have prepared it for skinning via the shader generator, mark a
144  // flag on the state so that the shader generator will do this. We should
145  // probably find a cleaner way to do this.
146  const ShaderAttrib *sattr;
147  if (_state->get_attrib(sattr) && sattr->auto_shader()) {
148  GeomVertexDataPipelineReader data_reader(_munged_data, current_thread);
149  if (data_reader.get_format()->get_animation().get_animation_type() == Geom::AT_hardware) {
150  static CPT(RenderState) state = RenderState::make(
151  DCAST(ShaderAttrib, ShaderAttrib::make())->set_flag(ShaderAttrib::F_hardware_skinning, true));
152  _state = _state->compose(state);
153  }
154 
155  gsg->ensure_generated_shader(_state);
156  } else {
157  // We may need to munge the state for the fixed-function pipeline.
158  StateMunger *state_munger = (StateMunger *)munger;
159  if (state_munger->should_munge_state()) {
160  _state = state_munger->munge_state(_state);
161  }
162  }
163 
164  // If there is any animation left in the vertex data after it has been
165  // munged--that is, we couldn't arrange to handle the animation in
166  // hardware--then we have to calculate that animation now.
167  bool cpu_animated = false;
168 
169  CPT(GeomVertexData) animated_vertices =
170  _munged_data->animate_vertices(force, current_thread);
171  if (animated_vertices != _munged_data) {
172  cpu_animated = true;
173  std::swap(_munged_data, animated_vertices);
174  }
175 
176 #ifndef NDEBUG
177  if (show_vertex_animation) {
178  GeomVertexDataPipelineReader data_reader(_munged_data, current_thread);
179  bool hardware_animated = (data_reader.get_format()->get_animation().get_animation_type() == Geom::AT_hardware);
180  if (cpu_animated || hardware_animated) {
181  // These vertices were animated, so flash them red or blue.
182  static const double flash_rate = 1.0; // 1 state change per second
183  int cycle = (int)(ClockObject::get_global_clock()->get_frame_time() * flash_rate);
184  if ((cycle & 1) == 0) {
185  _state = cpu_animated ? get_flash_cpu_state() : get_flash_hardware_state();
186  }
187  }
188  }
189 #endif
190  }
191 
192  return true;
193 }
194 
195 /**
196  *
197  */
198 void CullableObject::
199 output(std::ostream &out) const {
200  if (_geom != nullptr) {
201  out << *_geom;
202  } else {
203  out << "(null)";
204  }
205 }
206 
207 /**
208  * Converts a table of points to quads for rendering on systems that don't
209  * support fancy points.
210  *
211  * This may replace _geom, _munged_data, and _state.
212  */
213 bool CullableObject::
214 munge_points_to_quads(const CullTraverser *traverser, bool force) {
215  Thread *current_thread = traverser->get_current_thread();
216 
217  // Better get the animated vertices, in case we're showing sprites on an
218  // animated model for some reason.
219  CPT(GeomVertexData) source_data =
220  _munged_data->animate_vertices(force, current_thread);
221 
222  if (!force && !source_data->request_resident()) {
223  return false;
224  }
225 
226  PStatTimer timer(_munge_sprites_pcollector, current_thread);
227  _sw_sprites_pcollector.add_level(source_data->get_num_rows());
228 
229  GraphicsStateGuardianBase *gsg = traverser->get_gsg();
230 
231  GeomVertexReader vertex(source_data, InternalName::get_vertex(),
232  current_thread);
233  GeomVertexReader normal(source_data, InternalName::get_normal(),
234  current_thread);
235  GeomVertexReader color(source_data, InternalName::get_color(),
236  current_thread);
237  GeomVertexReader texcoord(source_data, InternalName::get_texcoord(),
238  current_thread);
239  GeomVertexReader rotate(source_data, InternalName::get_rotate(),
240  current_thread);
241  GeomVertexReader size(source_data, InternalName::get_size(),
242  current_thread);
243  GeomVertexReader aspect_ratio(source_data, InternalName::get_aspect_ratio(),
244  current_thread);
245 
246  bool has_normal = (normal.has_column());
247  bool has_color = (color.has_column());
248  bool has_texcoord = (texcoord.has_column());
249  bool has_rotate = (rotate.has_column());
250  bool has_size = (size.has_column());
251  bool has_aspect_ratio = (aspect_ratio.has_column());
252 
253  bool sprite_texcoord = false;
254  const TexGenAttrib *tex_gen = DCAST(TexGenAttrib, _state->get_attrib(TexGenAttrib::get_class_slot()));
255  if (tex_gen != nullptr) {
256  if (tex_gen->get_mode(TextureStage::get_default()) == TexGenAttrib::M_point_sprite) {
257  sprite_texcoord = true;
258 
259  // Turn off the TexGenAttrib, since we don't want it now.
260  _state = _state->set_attrib(tex_gen->remove_stage(TextureStage::get_default()));
261  }
262  }
263 
264  PN_stdfloat point_size = 1;
265  bool perspective = false;
266  const RenderModeAttrib *render_mode = DCAST(RenderModeAttrib, _state->get_attrib(RenderModeAttrib::get_class_slot()));
267  if (render_mode != nullptr) {
268  point_size = render_mode->get_thickness();
269  perspective = render_mode->get_perspective();
270 
271  if (render_mode->get_mode() != RenderModeAttrib::M_filled_flat) {
272  // Render the new polygons with M_filled_flat, for a slight performance
273  // advantage when software rendering.
274  _state = _state->set_attrib(RenderModeAttrib::make(RenderModeAttrib::M_filled_flat));
275  }
276  }
277 
278  // Get the vertex format of the newly created geometry.
279  CPT(GeomVertexFormat) new_format;
280 
281  {
282  LightMutexHolder holder(_format_lock);
283  SourceFormat sformat(source_data->get_format(), sprite_texcoord);
284  FormatMap::iterator fmi = _format_map.find(sformat);
285  if (fmi != _format_map.end()) {
286  new_format = (*fmi).second;
287 
288  } else {
289  // We have to construct the format now.
290  PT(GeomVertexArrayFormat) new_array_format;
291  if (sformat._retransform_sprites) {
292  // With retransform_sprites in effect, we will be sending ordinary 3-D
293  // points to the graphics API.
294  new_array_format =
295  new GeomVertexArrayFormat(InternalName::get_vertex(), 3,
296  Geom::NT_stdfloat,
297  Geom::C_point);
298  } else {
299  // Without retransform_sprites, we will be sending 4-component clip-
300  // space points.
301  new_array_format =
302  new GeomVertexArrayFormat(InternalName::get_vertex(), 4,
303  Geom::NT_stdfloat,
304  Geom::C_clip_point);
305  }
306  if (has_normal) {
307  const GeomVertexColumn *c = normal.get_column();
308  new_array_format->add_column
309  (InternalName::get_normal(), c->get_num_components(),
310  c->get_numeric_type(), c->get_contents());
311  }
312  if (has_color) {
313  const GeomVertexColumn *c = color.get_column();
314  new_array_format->add_column
315  (InternalName::get_color(), c->get_num_components(),
316  c->get_numeric_type(), c->get_contents());
317  }
318  if (sprite_texcoord) {
319  new_array_format->add_column
320  (InternalName::get_texcoord(), 2,
321  Geom::NT_stdfloat,
322  Geom::C_texcoord);
323 
324  } else if (has_texcoord) {
325  const GeomVertexColumn *c = texcoord.get_column();
326  new_array_format->add_column
327  (InternalName::get_texcoord(), c->get_num_components(),
328  c->get_numeric_type(), c->get_contents());
329  }
330 
331  new_format = GeomVertexFormat::register_format(new_array_format);
332  _format_map[sformat] = new_format;
333  }
334  }
335 
336  CoordinateSystem internal_cs = gsg->get_internal_coordinate_system();
337  LMatrix4 internal = _internal_transform->get_mat();
338  PN_stdfloat scale = _internal_transform->get_scale()[1];
339 
340  SceneSetup *scene = traverser->get_scene();
341  const Lens *lens = scene->get_lens();
342  LMatrix4 projection =
343  LMatrix4::convert_mat(internal_cs, lens->get_coordinate_system()) *
344  lens->get_projection_mat();
345 
346  int viewport_width = scene->get_viewport_width();
347  int viewport_height = scene->get_viewport_height();
348 
349  // We need a standard projection matrix, in a known coordinate system, to
350  // compute the perspective height.
351  LMatrix4 height_projection;
352  if (perspective) {
353  height_projection =
354  LMatrix4::convert_mat(CS_yup_right, lens->get_coordinate_system()) *
355  lens->get_projection_mat();
356  }
357 
358  LMatrix4 render_transform = internal * projection;
359  LMatrix4 inv_render_transform;
360  inv_render_transform.invert_from(render_transform);
361 
362  // Now convert all of the vertices in the GeomVertexData to quads. We
363  // always convert all the vertices, assuming all the vertices are referenced
364  // by GeomPrimitives, because we want to optimize for the most common case.
365  int orig_verts = source_data->get_num_rows();
366  int new_verts = 4 * orig_verts; // each vertex becomes four.
367 
368  PT(GeomVertexData) new_data = new GeomVertexData
369  (source_data->get_name(), new_format, Geom::UH_stream);
370  new_data->unclean_set_num_rows(new_verts);
371 
372  GeomVertexWriter new_vertex(new_data, InternalName::get_vertex());
373  GeomVertexWriter new_normal(new_data, InternalName::get_normal());
374  GeomVertexWriter new_color(new_data, InternalName::get_color());
375  GeomVertexWriter new_texcoord(new_data, InternalName::get_texcoord());
376 
377  // We'll keep an array of all of the points' eye-space coordinates, and
378  // their distance from the camera, so we can sort the points for each
379  // primitive, below.
380  PointData *points;
381  {
382  PStatTimer t2(_munge_sprites_verts_pcollector, current_thread);
383  points = (PointData *)alloca(orig_verts * sizeof(PointData));
384  int vi = 0;
385  while (!vertex.is_at_end()) {
386  // Get the point in eye-space coordinates.
387  LPoint3 eye = internal.xform_point(vertex.get_data3());
388  PN_stdfloat dist = gsg->compute_distance_to(eye);
389  points[vi]._dist = dist;
390 
391  // The point in clip coordinates.
392  LPoint4 p4 = LPoint4(eye[0], eye[1], eye[2], 1.0f) * projection;
393 
394  if (has_size) {
395  point_size = size.get_data1();
396  }
397 
398  PN_stdfloat scale_y = point_size;
399  if (perspective) {
400  // Perspective-sized points. Here point_size is the point's height in
401  // 3-d units. To arrange that, we need to figure out the appropriate
402  // scaling factor based on the current viewport and projection matrix.
403  LVector3 height(0.0f, point_size * scale, scale);
404  height = height * height_projection;
405  scale_y = height[1] * viewport_height;
406 
407  // We should then divide the radius by the distance from the camera
408  // plane, to emulate the glPointParameters() behavior.
409  if (!lens->is_orthographic()) {
410  scale_y /= dist;
411  }
412  }
413 
414  // Also factor in the homogeneous scale for being in clip coordinates
415  // still.
416  scale_y *= p4[3];
417 
418  PN_stdfloat scale_x = scale_y;
419  if (has_aspect_ratio) {
420  scale_x *= aspect_ratio.get_data1();
421  }
422 
423  // Define the first two corners based on the scales in X and Y.
424  LPoint2 c0(scale_x, scale_y);
425  LPoint2 c1(-scale_x, scale_y);
426 
427  if (has_rotate) {
428  // If we have a rotate factor, apply it to those two corners.
429  PN_stdfloat r = rotate.get_data1();
430  LMatrix3 mat = LMatrix3::rotate_mat(r);
431  c0 = c0 * mat;
432  c1 = c1 * mat;
433  }
434 
435  // Finally, scale the corners in their newly-rotated position, to
436  // compensate for the aspect ratio of the viewport.
437  PN_stdfloat rx = 1.0f / viewport_width;
438  PN_stdfloat ry = 1.0f / viewport_height;
439  c0.set(c0[0] * rx, c0[1] * ry);
440  c1.set(c1[0] * rx, c1[1] * ry);
441 
442  if (retransform_sprites) {
443  // With retransform_sprites in effect, we must reconvert the resulting
444  // quad back into the original 3-D space.
445  new_vertex.set_data4(inv_render_transform.xform(LPoint4(p4[0] + c0[0], p4[1] + c0[1], p4[2], p4[3])));
446  new_vertex.set_data4(inv_render_transform.xform(LPoint4(p4[0] + c1[0], p4[1] + c1[1], p4[2], p4[3])));
447  new_vertex.set_data4(inv_render_transform.xform(LPoint4(p4[0] - c1[0], p4[1] - c1[1], p4[2], p4[3])));
448  new_vertex.set_data4(inv_render_transform.xform(LPoint4(p4[0] - c0[0], p4[1] - c0[1], p4[2], p4[3])));
449 
450  if (has_normal) {
451  const LNormal &c = normal.get_data3();
452  new_normal.set_data3(c);
453  new_normal.set_data3(c);
454  new_normal.set_data3(c);
455  new_normal.set_data3(c);
456  }
457 
458  } else {
459  // Without retransform_sprites, we can simply load the clip-space
460  // coordinates.
461  new_vertex.set_data4(p4[0] + c0[0], p4[1] + c0[1], p4[2], p4[3]);
462  new_vertex.set_data4(p4[0] + c1[0], p4[1] + c1[1], p4[2], p4[3]);
463  new_vertex.set_data4(p4[0] - c1[0], p4[1] - c1[1], p4[2], p4[3]);
464  new_vertex.set_data4(p4[0] - c0[0], p4[1] - c0[1], p4[2], p4[3]);
465 
466  if (has_normal) {
467  LNormal c = render_transform.xform_vec(normal.get_data3());
468  new_normal.set_data3(c);
469  new_normal.set_data3(c);
470  new_normal.set_data3(c);
471  new_normal.set_data3(c);
472  }
473  }
474  if (has_color) {
475  const LColor &c = color.get_data4();
476  new_color.set_data4(c);
477  new_color.set_data4(c);
478  new_color.set_data4(c);
479  new_color.set_data4(c);
480  }
481  if (sprite_texcoord) {
482  new_texcoord.set_data2(1.0f, 0.0f);
483  new_texcoord.set_data2(0.0f, 0.0f);
484  new_texcoord.set_data2(1.0f, 1.0f);
485  new_texcoord.set_data2(0.0f, 1.0f);
486  } else if (has_texcoord) {
487  const LVecBase4 &c = texcoord.get_data4();
488  new_texcoord.set_data4(c);
489  new_texcoord.set_data4(c);
490  new_texcoord.set_data4(c);
491  new_texcoord.set_data4(c);
492  }
493 
494  ++vi;
495  }
496 
497  nassertr(vi == orig_verts, false);
498  nassertr(new_data->get_num_rows() == new_verts, false);
499  }
500 
501  // Determine the format we should use to store the indices. Don't choose
502  // NT_uint8, as Direct3D 9 doesn't support it.
503  const GeomVertexArrayFormat *new_prim_format = nullptr;
504  if (new_verts < 0xffff) {
505  new_prim_format = GeomPrimitive::get_index_format(GeomEnums::NT_uint16);
506 
507  } else {
508  new_prim_format = GeomPrimitive::get_index_format(GeomEnums::NT_uint32);
509  }
510 
511  PT(Geom) new_geom = new Geom(new_data);
512 
513  // Replace each primitive in the Geom (it's presumably a GeomPoints
514  // primitive, although it might be some other kind of primitive if we got
515  // here because RenderModeAttrib::M_point is enabled) with a new primitive
516  // that replaces each vertex with a quad of the appropriate scale and
517  // orientation.
518 
519  // BUG: if we're rendering polygons in M_point mode with a CullFaceAttrib in
520  // effect, we won't actually apply the CullFaceAttrib but will always render
521  // all of the vertices of the polygons. This is certainly a bug, but a very
522  // minor one; and in order to fix it we'd have to do the face culling
523  // ourselves--not sure if it's worth it.
524 
525  {
526  PStatTimer t3(_munge_sprites_prims_pcollector, current_thread);
527  GeomPipelineReader geom_reader(_geom, current_thread);
528  int num_primitives = geom_reader.get_num_primitives();
529  for (int pi = 0; pi < num_primitives; ++pi) {
530  const GeomPrimitive *primitive = geom_reader.get_primitive(pi);
531  if (primitive->get_num_vertices() != 0) {
532  // Extract out the list of vertices referenced by the primitive.
533  int num_vertices = primitive->get_num_vertices();
534  unsigned int *vertices = (unsigned int *)alloca(num_vertices * sizeof(unsigned int));
535  unsigned int *vertices_end = vertices + num_vertices;
536 
537  if (primitive->is_indexed()) {
538  // Indexed case.
539  GeomVertexReader index(primitive->get_vertices(), 0, current_thread);
540  for (unsigned int *vi = vertices; vi != vertices_end; ++vi) {
541  unsigned int v = index.get_data1i();
542  nassertr(v < (unsigned int)orig_verts, false);
543  (*vi) = v;
544  }
545  } else {
546  // Nonindexed case.
547  unsigned int first_vertex = primitive->get_first_vertex();
548  for (int i = 0; i < num_vertices; ++i) {
549  unsigned int v = i + first_vertex;
550  nassertr(v < (unsigned int)orig_verts, false);
551  vertices[i] = v;
552  }
553  }
554 
555  // Now sort the points in order from back-to-front so they will render
556  // properly with transparency, at least with each other.
557  std::sort(vertices, vertices_end, SortPoints(points));
558 
559  // Go through the points, now in sorted order, and generate a pair of
560  // triangles for each one. We generate indexed triangles instead of
561  // two-triangle strips, since this seems to be generally faster on PC
562  // hardware (otherwise, we'd have to nearly double the vertices to
563  // stitch all the little triangle strips together).
564  PT(GeomPrimitive) new_primitive = new GeomTriangles(Geom::UH_stream);
565  int new_prim_verts = 6 * num_vertices; // two triangles per point.
566 
567  PT(GeomVertexArrayData) new_index
568  = new GeomVertexArrayData(new_prim_format, GeomEnums::UH_stream);
569  new_index->unclean_set_num_rows(new_prim_verts);
570 
571  GeomVertexWriter index(new_index, 0);
572  nassertr(index.has_column(), false);
573  for (unsigned int *vi = vertices; vi != vertices_end; ++vi) {
574  int new_vi = (*vi) * 4;
575  nassertr(index.get_write_row() + 6 <= new_prim_verts, false);
576  index.set_data1i(new_vi);
577  index.set_data1i(new_vi + 1);
578  index.set_data1i(new_vi + 2);
579  index.set_data1i(new_vi + 2);
580  index.set_data1i(new_vi + 1);
581  index.set_data1i(new_vi + 3);
582  }
583  new_primitive->set_vertices(new_index, new_prim_verts);
584 
585  int min_vi = primitive->get_min_vertex();
586  int max_vi = primitive->get_max_vertex();
587  new_primitive->set_minmax(min_vi * 4, max_vi * 4 + 3, nullptr, nullptr);
588 
589  new_geom->add_primitive(new_primitive);
590  }
591  }
592  }
593 
594  _geom = new_geom.p();
595  _munged_data = std::move(new_data);
596 
597  return true;
598 }
599 
600 /**
601  * Returns a RenderState for flashing the object red, to show it is animated
602  * by the CPU when show-vertex-animation is on.
603  */
604 CPT(RenderState) CullableObject::
605 get_flash_cpu_state() {
606  static const LColor flash_cpu_color(0.8f, 0.2, 0.2, 1.0f);
607 
608  // Once someone asks for this pointer, we hold its reference count and never
609  // free it.
610  static CPT(RenderState) flash_cpu_state = nullptr;
611  if (flash_cpu_state == nullptr) {
612  flash_cpu_state = RenderState::make
613  (LightAttrib::make_all_off(),
614  TextureAttrib::make_off(),
615  ColorAttrib::make_flat(flash_cpu_color));
616  }
617 
618  return flash_cpu_state;
619 }
620 
621 /**
622  * Returns a RenderState for flashing the object blue, to show it is animated
623  * by the hardware when show-vertex-animation is on.
624  */
625 CPT(RenderState) CullableObject::
626 get_flash_hardware_state() {
627  static const LColor flash_hardware_color(0.2, 0.2, 0.8, 1.0);
628 
629  // Once someone asks for this pointer, we hold its reference count and never
630  // free it.
631  static CPT(RenderState) flash_hardware_state = nullptr;
632  if (flash_hardware_state == nullptr) {
633  flash_hardware_state = RenderState::make
634  (LightAttrib::make_all_off(),
635  TextureAttrib::make_off(),
636  ColorAttrib::make_flat(flash_hardware_color));
637  }
638 
639  return flash_hardware_state;
640 }
641 
642 /**
643  *
644  */
645 CullableObject::SourceFormat::
646 SourceFormat(const GeomVertexFormat *format, bool sprite_texcoord) :
647  _format(format),
648  _sprite_texcoord(sprite_texcoord)
649 {
650  _retransform_sprites = retransform_sprites;
651 }
Geom
A container for geometry primitives.
Definition: geom.h:54
RenderModeAttrib::get_mode
get_mode
Returns the render mode.
Definition: renderModeAttrib.h:69
SceneSetup::get_viewport_height
int get_viewport_height() const
Returns the height of the viewport (display region) in pixels.
Definition: sceneSetup.I:67
LightMutexHolder
Similar to MutexHolder, but for a light mutex.
Definition: lightMutexHolder.h:25
nodePath.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GeomVertexArrayData
This is the data for one array of a GeomVertexData structure.
Definition: geomVertexArrayData.h:58
GeomPrimitive::get_first_vertex
int get_first_vertex() const
Returns the first vertex number referenced by the primitive.
Definition: geomPrimitive.I:98
cullTraverser.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
RenderModeAttrib::get_thickness
get_thickness
Returns the line width or point thickness.
Definition: renderModeAttrib.h:70
geomVertexWriter.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Lens::get_projection_mat
const LMatrix4 & get_projection_mat(StereoChannel channel=SC_mono) const
Returns the complete transformation matrix from a 3-d point in space to a point on the film,...
Definition: lens.I:563
stateMunger.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GeomVertexData
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
Definition: geomVertexData.h:68
geomVertexReader.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
pmap
This is our own Panda specialization on the default STL map.
Definition: pmap.h:49
cullableObject.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
ShaderAttrib::auto_shader
bool auto_shader() const
If true, then this ShaderAttrib does not contain an explicit shader - instead, it requests the automa...
Definition: shaderAttrib.I:71
CullTraverser::get_scene
SceneSetup * get_scene() const
Returns the SceneSetup object.
Definition: cullTraverser.I:35
clockObject.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
pStatTimer.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
ClockObject::get_global_clock
static ClockObject * get_global_clock()
Returns a pointer to the global ClockObject.
Definition: clockObject.I:215
colorAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GeomVertexWriter
This object provides a high-level interface for quickly writing a sequence of numeric values from a v...
Definition: geomVertexWriter.h:55
CullTraverser
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling,...
Definition: cullTraverser.h:45
ShaderAttrib
Definition: shaderAttrib.h:39
GeomVertexReader
This object provides a high-level interface for quickly reading a sequence of numeric values from a v...
Definition: geomVertexReader.h:47
GeomMunger::munge_geom
bool munge_geom(CPT(Geom) &geom, CPT(GeomVertexData) &data, bool force, Thread *current_thread)
Applies the indicated munger to the geom and its data, and returns a (possibly different) geom and da...
Definition: geomMunger.cxx:95
CPT
CPT(RenderState) CullableObject
Returns a RenderState for flashing the object red, to show it is animated by the CPU when show-vertex...
Definition: cullableObject.cxx:604
RenderState
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Definition: renderState.h:47
LightMutex
This is a standard, non-reentrant mutex, similar to the Mutex class.
Definition: lightMutex.h:39
Lens::get_coordinate_system
get_coordinate_system
Returns the coordinate system that all 3-d computations are performed within for this Lens.
Definition: lens.h:74
PStatTimer
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
Definition: pStatTimer.h:30
GeomPrimitive::get_index_format
const GeomVertexArrayFormat * get_index_format() const
Returns a registered format appropriate for using to store the index table.
Definition: geomPrimitive.I:389
renderState.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
SceneSetup
This object holds the camera position, etc., and other general setup information for rendering a part...
Definition: sceneSetup.h:32
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
light.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GeomVertexFormat::get_animation
get_animation
Returns the GeomVertexAnimationSpec that indicates how this format's vertices are set up for animatio...
Definition: geomVertexFormat.h:72
texGenAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GeomPipelineReader
Encapsulates the data from a Geom, pre-fetched for one stage of the pipeline.
Definition: geom.h:405
GeomPrimitive::get_num_vertices
get_num_vertices
Returns the number of indices used by all the primitives in this object.
Definition: geomPrimitive.h:99
lightMutexHolder.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
CullTraverser::get_current_thread
Thread * get_current_thread() const
Returns the currently-executing thread object, as passed to the CullTraverser constructor.
Definition: cullTraverser.I:27
sceneSetup.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GeomPrimitive::get_min_vertex
int get_min_vertex() const
Returns the minimum vertex index number used by all the primitives in this object.
Definition: geomPrimitive.I:181
PStatCollector
A lightweight class that represents a single element that may be timed and/or counted via stats.
Definition: pStatCollector.h:43
RenderModeAttrib
Specifies how polygons are to be drawn.
Definition: renderModeAttrib.h:27
shaderAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
geomTriangles.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Lens
A base class for any number of different kinds of lenses, linear and otherwise.
Definition: lens.h:41
GeomPrimitive::get_max_vertex
int get_max_vertex() const
Returns the maximum vertex index number used by all the primitives in this object.
Definition: geomPrimitive.I:192
GeomVertexColumn::get_numeric_type
NumericType get_numeric_type() const
Returns the token representing the numeric type of the data storage.
Definition: geomVertexColumn.I:116
GeomVertexColumn::get_contents
Contents get_contents() const
Returns the token representing the semantic meaning of the stored value.
Definition: geomVertexColumn.I:124
GeomVertexFormat
This class defines the physical layout of the vertex data stored within a Geom.
Definition: geomVertexFormat.h:55
CullableObject::munge_geom
bool munge_geom(GraphicsStateGuardianBase *gsg, GeomMunger *munger, const CullTraverser *traverser, bool force)
Uses the indicated GeomMunger to transform the geom and/or its vertices.
Definition: cullableObject.cxx:54
GeomTriangles
Defines a series of disconnected triangles.
Definition: geomTriangles.h:23
StateMunger
This is just a simple derivative of GeomMunger that adds the ability to munge states.
Definition: stateMunger.h:26
textureAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
ClockObject::get_frame_time
get_frame_time
Returns the time in seconds as of the last time tick() was called (typically, this will be as of the ...
Definition: clockObject.h:91
GeomVertexColumn::get_num_components
int get_num_components() const
Returns the number of components of the column: the number of instances of the NumericType in each el...
Definition: geomVertexColumn.I:87
Lens::is_orthographic
virtual bool is_orthographic() const
Returns true if the lens represents a orthographic projection (i.e.
Definition: lens.cxx:558
TexGenAttrib
Computes texture coordinates for geometry automatically based on vertex position and/or normal.
Definition: texGenAttrib.h:32
GraphicsStateGuardianBase
This is a base class for the GraphicsStateGuardian class, which is itself a base class for the variou...
Definition: graphicsStateGuardianBase.h:110
GeomVertexColumn
This defines how a single column is interleaved within a vertex array stored within a Geom.
Definition: geomVertexColumn.h:37
CullTraverser::get_gsg
GraphicsStateGuardianBase * get_gsg() const
Returns the GraphicsStateGuardian in effect.
Definition: cullTraverser.I:18
TextureStage::get_default
get_default
Returns the default TextureStage that will be used for all texturing that does not name a particular ...
Definition: textureStage.h:205
lightAttrib.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GeomPrimitive::is_indexed
bool is_indexed() const
Returns true if the primitive is indexed, false otherwise.
Definition: geomPrimitive.I:86
StateMunger::should_munge_state
bool should_munge_state() const
Returns true if this munger has something interesting to do to the state.
Definition: stateMunger.I:28
Thread
A thread; that is, a lightweight process.
Definition: thread.h:46
SceneSetup::get_lens
const Lens * get_lens() const
Returns the particular Lens used for rendering.
Definition: sceneSetup.I:131
SceneSetup::get_viewport_width
int get_viewport_width() const
Returns the width of the viewport (display region) in pixels.
Definition: sceneSetup.I:59
RenderModeAttrib::get_perspective
get_perspective
Returns the perspective flag.
Definition: renderModeAttrib.h:71
GeomVertexArrayFormat
This describes the structure of a single array within a Geom data.
Definition: geomVertexArrayFormat.h:47
GeomPrimitive
This is an abstract base class for a family of classes that represent the fundamental geometry primit...
Definition: geomPrimitive.h:56
GeomVertexDataPipelineReader
Encapsulates the data from a GeomVertexData, pre-fetched for one stage of the pipeline.
Definition: geomVertexData.h:442
lens.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GeomMunger
Objects of this class are used to convert vertex data from a Geom into a format suitable for passing ...
Definition: geomMunger.h:50