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 }
This is just a simple derivative of GeomMunger that adds the ability to munge states.
Definition: stateMunger.h:26
static ClockObject * get_global_clock()
Returns a pointer to the global ClockObject.
Definition: clockObject.I:215
This object provides a high-level interface for quickly writing a sequence of numeric values from a v...
get_animation
Returns the GeomVertexAnimationSpec that indicates how this format's vertices are set up for animatio...
This is our own Panda specialization on the default STL map.
Definition: pmap.h:49
bool auto_shader() const
If true, then this ShaderAttrib does not contain an explicit shader - instead, it requests the automa...
Definition: shaderAttrib.I:71
const GeomVertexArrayFormat * get_index_format() const
Returns a registered format appropriate for using to store the index table.
Contents get_contents() const
Returns the token representing the semantic meaning of the stored value.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool unclean_set_num_rows(int n)
This method behaves like set_num_rows(), except the new data is not initialized.
A base class for any number of different kinds of lenses, linear and otherwise.
Definition: lens.h:41
virtual bool is_orthographic() const
Returns true if the lens represents a orthographic projection (i.e.
Definition: lens.cxx:558
int get_max_vertex() const
Returns the maximum vertex index number used by all the primitives in this object.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Thread * get_current_thread() const
Returns the currently-executing thread object, as passed to the CullTraverser constructor.
Definition: cullTraverser.I:27
NumericType get_numeric_type() const
Returns the token representing the numeric type of the data storage.
Objects of this class are used to convert vertex data from a Geom into a format suitable for passing ...
Definition: geomMunger.h:50
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is an abstract base class for a family of classes that represent the fundamental geometry primit...
Definition: geomPrimitive.h:56
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_num_vertices
Returns the number of indices used by all the primitives in this object.
Definition: geomPrimitive.h:99
const Lens * get_lens() const
Returns the particular Lens used for rendering.
Definition: sceneSetup.I:131
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
Definition: pStatTimer.h:30
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Encapsulates the data from a Geom, pre-fetched for one stage of the pipeline.
Definition: geom.h:405
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
int get_first_vertex() const
Returns the first vertex number referenced by the primitive.
Definition: geomPrimitive.I:98
This defines how a single column is interleaved within a vertex array stored within a Geom.
int get_viewport_height() const
Returns the height of the viewport (display region) in pixels.
Definition: sceneSetup.I:67
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A lightweight class that represents a single element that may be timed and/or counted via stats.
int get_min_vertex() const
Returns the minimum vertex index number used by all the primitives in this object.
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
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Similar to MutexHolder, but for a light mutex.
int get_viewport_width() const
Returns the width of the viewport (display region) in pixels.
Definition: sceneSetup.I:59
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool munge_geom(GraphicsStateGuardianBase *gsg, GeomMunger *munger, const CullTraverser *traverser, bool force)
Uses the indicated GeomMunger to transform the geom and/or its vertices.
A container for geometry primitives.
Definition: geom.h:54
get_coordinate_system
Returns the coordinate system that all 3-d computations are performed within for this Lens.
Definition: lens.h:74
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
int get_data1i()
Returns the data associated with the read row, expressed as a 1-component value, and advances the rea...
GraphicsStateGuardianBase * get_gsg() const
Returns the GraphicsStateGuardian in effect.
Definition: cullTraverser.I:18
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Definition: renderState.h:47
This class defines the physical layout of the vertex data stored within a Geom.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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
This is a base class for the GraphicsStateGuardian class, which is itself a base class for the variou...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool should_munge_state() const
Returns true if this munger has something interesting to do to the state.
Definition: stateMunger.I:28
get_mode
Returns the render mode.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A thread; that is, a lightweight process.
Definition: thread.h:46
This object provides a high-level interface for quickly reading a sequence of numeric values from a v...
SceneSetup * get_scene() const
Returns the SceneSetup object.
Definition: cullTraverser.I:35
This describes the structure of a single array within a Geom data.
Defines a series of disconnected triangles.
Definition: geomTriangles.h:23
get_thickness
Returns the line width or point thickness.
get_perspective
Returns the perspective flag.
Specifies how polygons are to be drawn.
Encapsulates the data from a GeomVertexData, pre-fetched for one stage of the pipeline.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
This object holds the camera position, etc., and other general setup information for rendering a part...
Definition: sceneSetup.h:32
This is a standard, non-reentrant mutex, similar to the Mutex class.
Definition: lightMutex.h:39
int get_num_components() const
Returns the number of components of the column: the number of instances of the NumericType in each el...
CPT(RenderState) CullableObject
Returns a RenderState for flashing the object red, to show it is animated by the CPU when show-vertex...
Computes texture coordinates for geometry automatically based on vertex position and/or normal.
Definition: texGenAttrib.h:32
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
bool is_indexed() const
Returns true if the primitive is indexed, false otherwise.
Definition: geomPrimitive.I:86
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling,...
Definition: cullTraverser.h:45
This is the data for one array of a GeomVertexData structure.