34CullableObject::FormatMap CullableObject::_format_map;
38PStatCollector CullableObject::_munge_geom_pcollector(
"*:Munge:Geom");
39PStatCollector CullableObject::_munge_sprites_pcollector(
"*:Munge:Sprites");
40PStatCollector CullableObject::_munge_sprites_verts_pcollector(
"*:Munge:Sprites:Verts");
41PStatCollector CullableObject::_munge_sprites_prims_pcollector(
"*:Munge:Sprites:Prims");
42PStatCollector CullableObject::_sw_sprites_pcollector(
"SW Sprites");
56 nassertr(munger !=
nullptr,
false);
59 PStatTimer timer(_munge_pcollector, current_thread);
60 if (_geom !=
nullptr) {
62 int gsg_bits = gsg->get_supported_geom_rendering();
63 if (!hardware_point_sprites) {
66 gsg_bits &= ~(Geom::GR_point_perspective | Geom::GR_point_sprite);
68 if (!hardware_points) {
71 gsg_bits &= ~(Geom::GR_point_bits &
~Geom::GR_point);
78 _munged_data = geom_reader.get_vertex_data();
83 data_reader.check_array_readers();
84 nassertr(geom_reader.check_valid(&data_reader),
false);
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;
93 if (unsupported_bits & Geom::GR_per_point_size) {
97 if (_state->get_attrib(sattr) && sattr->get_flag(ShaderAttrib::F_shader_point_size)) {
98 unsupported_bits &=
~Geom::GR_per_point_size;
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) {
107 _geom = _geom->make_points();
111 if (unsupported_bits & Geom::GR_render_mode_wireframe) {
112 if (geom_reader.get_primitive_type() != Geom::PT_lines) {
113 _geom = _geom->make_lines();
118 if ((unsupported_bits & Geom::GR_point_bits) != 0) {
123 if (pgraph_cat.is_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";
129 if (!munge_points_to_quads(traverser, force)) {
137 PStatTimer timer(_munge_geom_pcollector, current_thread);
138 if (!munger->
munge_geom(_geom, _munged_data, force, current_thread)) {
147 if (_state->get_attrib(sattr) && sattr->
auto_shader()) {
149 if (data_reader.get_format()->
get_animation().get_animation_type() == Geom::AT_hardware) {
152 _state = _state->compose(state);
155 gsg->ensure_generated_shader(_state);
167 bool cpu_animated =
false;
170 _munged_data->animate_vertices(force, current_thread);
171 if (animated_vertices != _munged_data) {
173 std::swap(_munged_data, animated_vertices);
177 if (show_vertex_animation) {
179 bool hardware_animated = (data_reader.get_format()->get_animation().get_animation_type() == Geom::AT_hardware);
180 if (cpu_animated || hardware_animated) {
182 static const double flash_rate = 1.0;
184 if ((cycle & 1) == 0) {
185 _state = cpu_animated ? get_flash_cpu_state() : get_flash_hardware_state();
199output(std::ostream &out)
const {
200 if (_geom !=
nullptr) {
214munge_points_to_quads(
const CullTraverser *traverser,
bool force) {
219 CPT(GeomVertexData) source_data =
220 _munged_data->animate_vertices(force, current_thread);
222 if (!force && !source_data->request_resident()) {
226 GeomVertexDataPipelineReader reader(source_data, current_thread);
227 reader.check_array_readers();
229 PStatTimer timer(_munge_sprites_pcollector, current_thread);
230 _sw_sprites_pcollector.add_level(reader.get_num_rows());
232 GraphicsStateGuardianBase *gsg = traverser->
get_gsg();
234 GeomVertexReader vertex(&reader, InternalName::get_vertex());
235 GeomVertexReader normal(&reader, InternalName::get_normal());
236 GeomVertexReader rotate(&reader, InternalName::get_rotate());
237 GeomVertexReader size(&reader, InternalName::get_size());
238 GeomVertexReader aspect_ratio(&reader, InternalName::get_aspect_ratio());
240 bool has_normal = (normal.has_column());
241 bool has_color = (reader.has_column(InternalName::get_color()));
242 bool has_texcoord = (reader.has_column(InternalName::get_texcoord()));
243 bool has_rotate = (rotate.has_column());
244 bool has_size = (size.has_column());
245 bool has_aspect_ratio = (aspect_ratio.has_column());
247 bool sprite_texcoord =
false;
248 const TexGenAttrib *tex_gen = DCAST(TexGenAttrib, _state->get_attrib(TexGenAttrib::get_class_slot()));
249 if (tex_gen !=
nullptr) {
251 sprite_texcoord =
true;
258 PN_stdfloat point_size = 1;
259 bool perspective =
false;
260 const RenderModeAttrib *render_mode = DCAST(RenderModeAttrib, _state->get_attrib(RenderModeAttrib::get_class_slot()));
261 if (render_mode !=
nullptr) {
265 if (render_mode->
get_mode() != RenderModeAttrib::M_filled_flat) {
273 CPT(GeomVertexFormat) new_format;
276 LightMutexHolder holder(_format_lock);
277 SourceFormat sformat(reader.get_format(), sprite_texcoord);
278 FormatMap::iterator fmi = _format_map.find(sformat);
279 if (fmi != _format_map.end()) {
280 new_format = (*fmi).second;
284 PT(GeomVertexArrayFormat) new_array_format;
285 if (sformat._retransform_sprites) {
289 new GeomVertexArrayFormat(InternalName::get_vertex(), 3,
296 new GeomVertexArrayFormat(InternalName::get_vertex(), 4,
301 const GeomVertexColumn *c = reader.get_format()->get_normal_column();
302 new_array_format->add_column
307 const GeomVertexColumn *c = reader.get_format()->get_color_column();
308 new_array_format->add_column
312 if (sprite_texcoord) {
313 new_array_format->add_column
314 (InternalName::get_texcoord(), 2,
318 }
else if (has_texcoord) {
319 const GeomVertexColumn *c = reader.get_format()->get_column(InternalName::get_texcoord());
320 new_array_format->add_column
326 for (
size_t ai = 0; ai < sformat._format->get_num_arrays(); ++ai) {
327 const GeomVertexArrayFormat *aformat = sformat._format->get_array(ai);
330 const GeomVertexColumn *column = aformat->
get_column(ci);
331 const InternalName *name = column->
get_name();
332 if (name != InternalName::get_vertex() &&
333 name != InternalName::get_normal() &&
334 name != InternalName::get_color() &&
335 name != InternalName::get_texcoord() &&
336 name != InternalName::get_rotate() &&
337 name != InternalName::get_size() &&
338 name != InternalName::get_aspect_ratio()) {
340 new_array_format->add_column(name,
347 new_format = GeomVertexFormat::register_format(new_array_format);
348 _format_map[sformat] = new_format;
352 CoordinateSystem internal_cs = gsg->get_internal_coordinate_system();
353 LMatrix4 internal = _internal_transform->get_mat();
354 PN_stdfloat scale = _internal_transform->get_scale()[1];
356 SceneSetup *scene = traverser->
get_scene();
357 const Lens *lens = scene->
get_lens();
358 LMatrix4 projection =
367 LMatrix4 height_projection;
374 LMatrix4 render_transform = internal * projection;
375 LMatrix4 inv_render_transform;
376 inv_render_transform.invert_from(render_transform);
381 int orig_verts = reader.get_num_rows();
382 int new_verts = 4 * orig_verts;
384 PT(GeomVertexData) new_data =
new GeomVertexData
385 (source_data->get_name(), new_format, Geom::UH_stream);
386 new_data->unclean_set_num_rows(new_verts);
388 GeomVertexWriter new_vertex(new_data, InternalName::get_vertex());
389 GeomVertexWriter new_normal(new_data, InternalName::get_normal());
390 GeomVertexWriter new_texcoord(new_data, InternalName::get_texcoord());
392 nassertr(new_vertex.has_column(),
false);
393 unsigned char *write_ptr = new_vertex.get_array_handle()->get_write_pointer();
397 unsigned char *_to_pointer;
398 const unsigned char *_from_pointer;
402 pvector<CopyOp> copies;
404 const GeomVertexArrayFormat *aformat = new_format->get_array(0);
406 const GeomVertexColumn *column = aformat->
get_column(ci);
407 const InternalName *name = column->
get_name();
408 if (name != InternalName::get_vertex() &&
409 (retransform_sprites || name != InternalName::get_normal()) &&
410 (!sprite_texcoord || name != InternalName::get_texcoord())) {
413 const GeomVertexColumn *source_column;
414 if (reader.get_format()->get_array_info(name, source_array, source_column)) {
416 copy._to_pointer = write_ptr + (size_t)column->
get_start();
417 copy._from_pointer = reader.get_array_reader(source_array)->get_read_pointer(
true) + (size_t)source_column->
get_start();
419 copy._from_stride = reader.get_format()->get_array(source_array)->get_stride();
421 if (!copies.empty() &&
422 (copy._to_pointer == copies.back()._to_pointer + copies.back()._num_bytes) &&
423 (copy._from_pointer == copies.back()._from_pointer + copies.back()._num_bytes)) {
425 copies.back()._num_bytes += copy._num_bytes;
427 copies.push_back(copy);
439 PStatTimer t2(_munge_sprites_verts_pcollector, current_thread);
440 points = (PointData *)alloca(orig_verts *
sizeof(PointData));
442 while (!vertex.is_at_end()) {
444 LPoint3 eye = internal.xform_point(vertex.get_data3());
445 PN_stdfloat dist = gsg->compute_distance_to(eye);
446 points[vi]._dist = dist;
449 LPoint4 p4 = LPoint4(eye[0], eye[1], eye[2], 1.0f) * projection;
452 point_size = size.get_data1();
455 PN_stdfloat scale_y = point_size;
460 LVector3 height(0.0f, point_size * scale, scale);
461 height = height * height_projection;
462 scale_y = height[1] * viewport_height;
475 PN_stdfloat scale_x = scale_y;
476 if (has_aspect_ratio) {
477 scale_x *= aspect_ratio.get_data1();
481 LPoint2 c0(scale_x, scale_y);
482 LPoint2 c1(-scale_x, scale_y);
486 PN_stdfloat r = rotate.get_data1();
487 LMatrix3 mat = LMatrix3::rotate_mat(r);
494 PN_stdfloat rx = 1.0f / viewport_width;
495 PN_stdfloat ry = 1.0f / viewport_height;
496 c0.set(c0[0] * rx, c0[1] * ry);
497 c1.set(c1[0] * rx, c1[1] * ry);
499 if (retransform_sprites) {
502 new_vertex.set_data4(inv_render_transform.xform(LPoint4(p4[0] + c0[0], p4[1] + c0[1], p4[2], p4[3])));
503 new_vertex.set_data4(inv_render_transform.xform(LPoint4(p4[0] + c1[0], p4[1] + c1[1], p4[2], p4[3])));
504 new_vertex.set_data4(inv_render_transform.xform(LPoint4(p4[0] - c1[0], p4[1] - c1[1], p4[2], p4[3])));
505 new_vertex.set_data4(inv_render_transform.xform(LPoint4(p4[0] - c0[0], p4[1] - c0[1], p4[2], p4[3])));
510 new_vertex.set_data4(p4[0] + c0[0], p4[1] + c0[1], p4[2], p4[3]);
511 new_vertex.set_data4(p4[0] + c1[0], p4[1] + c1[1], p4[2], p4[3]);
512 new_vertex.set_data4(p4[0] - c1[0], p4[1] - c1[1], p4[2], p4[3]);
513 new_vertex.set_data4(p4[0] - c0[0], p4[1] - c0[1], p4[2], p4[3]);
517 LNormal c = render_transform.xform_vec(normal.get_data3());
518 new_normal.set_data3(c);
519 new_normal.set_data3(c);
520 new_normal.set_data3(c);
521 new_normal.set_data3(c);
524 if (sprite_texcoord) {
525 new_texcoord.set_data2(1.0f, 0.0f);
526 new_texcoord.set_data2(0.0f, 0.0f);
527 new_texcoord.set_data2(1.0f, 1.0f);
528 new_texcoord.set_data2(0.0f, 1.0f);
532 for (CopyOp © : copies) {
533 memcpy(copy._to_pointer, copy._from_pointer, copy._num_bytes);
534 copy._to_pointer += to_stride;
535 memcpy(copy._to_pointer, copy._from_pointer, copy._num_bytes);
536 copy._to_pointer += to_stride;
537 memcpy(copy._to_pointer, copy._from_pointer, copy._num_bytes);
538 copy._to_pointer += to_stride;
539 memcpy(copy._to_pointer, copy._from_pointer, copy._num_bytes);
540 copy._to_pointer += to_stride;
541 copy._from_pointer += copy._from_stride;
547 nassertr(vi == orig_verts,
false);
548 nassertr(new_data->get_num_rows() == new_verts,
false);
553 const GeomVertexArrayFormat *new_prim_format =
nullptr;
554 if (new_verts < 0xffff) {
561 PT(Geom) new_geom =
new Geom(new_data);
576 PStatTimer t3(_munge_sprites_prims_pcollector, current_thread);
577 GeomPipelineReader geom_reader(_geom, current_thread);
578 int num_primitives = geom_reader.get_num_primitives();
579 for (
int pi = 0; pi < num_primitives; ++pi) {
580 const GeomPrimitive *primitive = geom_reader.get_primitive(pi);
584 unsigned int *vertices = (
unsigned int *)alloca(num_vertices *
sizeof(
unsigned int));
585 unsigned int *vertices_end = vertices + num_vertices;
589 GeomVertexReader index(primitive->get_vertices(), 0, current_thread);
590 for (
unsigned int *vi = vertices; vi != vertices_end; ++vi) {
591 unsigned int v = index.get_data1i();
592 nassertr(v < (
unsigned int)orig_verts,
false);
598 for (
int i = 0; i < num_vertices; ++i) {
599 unsigned int v = i + first_vertex;
600 nassertr(v < (
unsigned int)orig_verts,
false);
607 std::sort(vertices, vertices_end, SortPoints(points));
614 PT(GeomPrimitive) new_primitive =
new GeomTriangles(Geom::UH_stream);
615 int new_prim_verts = 6 * num_vertices;
617 PT(GeomVertexArrayData) new_index
618 =
new GeomVertexArrayData(new_prim_format, GeomEnums::UH_stream);
619 new_index->unclean_set_num_rows(new_prim_verts);
621 GeomVertexWriter index(new_index, 0);
622 nassertr(index.has_column(),
false);
623 for (
unsigned int *vi = vertices; vi != vertices_end; ++vi) {
624 int new_vi = (*vi) * 4;
625 nassertr(index.get_write_row() + 6 <= new_prim_verts,
false);
626 index.set_data1i(new_vi);
627 index.set_data1i(new_vi + 1);
628 index.set_data1i(new_vi + 2);
629 index.set_data1i(new_vi + 2);
630 index.set_data1i(new_vi + 1);
631 index.set_data1i(new_vi + 3);
633 new_primitive->set_vertices(new_index, new_prim_verts);
637 new_primitive->set_minmax(min_vi * 4, max_vi * 4 + 3,
nullptr,
nullptr);
639 new_geom->add_primitive(new_primitive);
644 _geom = new_geom.p();
645 _munged_data = std::move(new_data);
655get_flash_cpu_state() {
656 static const LColor flash_cpu_color(0.8f, 0.2, 0.2, 1.0f);
660 static CPT(RenderState) flash_cpu_state =
nullptr;
661 if (flash_cpu_state ==
nullptr) {
668 return flash_cpu_state;
676get_flash_hardware_state() {
677 static const LColor flash_hardware_color(0.2, 0.2, 0.8, 1.0);
681 static CPT(RenderState) flash_hardware_state =
nullptr;
682 if (flash_hardware_state ==
nullptr) {
689 return flash_hardware_state;
695CullableObject::SourceFormat::
698 _sprite_texcoord(sprite_texcoord)
700 _retransform_sprites = retransform_sprites;
static ClockObject * get_global_clock()
Returns a pointer to the global ClockObject.
static ConstPointerTo< RenderAttrib > make_flat(const LColor &color)
Constructs a new ColorAttrib object that indicates geometry should be rendered in the indicated color...
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling,...
Thread * get_current_thread() const
Returns the currently-executing thread object, as passed to the CullTraverser constructor.
SceneSetup * get_scene() const
Returns the SceneSetup object.
GraphicsStateGuardianBase * get_gsg() const
Returns the GraphicsStateGuardian in effect.
bool munge_geom(GraphicsStateGuardianBase *gsg, GeomMunger *munger, const CullTraverser *traverser, bool force)
Uses the indicated GeomMunger to transform the geom and/or its vertices.
Objects of this class are used to convert vertex data from a Geom into a format suitable for passing ...
bool munge_geom(ConstPointerTo< Geom > &geom, ConstPointerTo< 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...
Encapsulates the data from a Geom, pre-fetched for one stage of the pipeline.
int get_max_vertex() const
Returns the maximum vertex index number used by all the primitives in this object.
get_num_vertices
Returns the number of indices used by all the primitives in this object.
int get_first_vertex() const
Returns the first vertex number referenced by the primitive.
const GeomVertexArrayFormat * get_index_format() const
Returns a registered format appropriate for using to store the index table.
int get_min_vertex() const
Returns the minimum vertex index number used by all the primitives in this object.
bool is_indexed() const
Returns true if the primitive is indexed, false otherwise.
int get_start() const
Returns the byte within the array record at which this column starts.
NumericType get_numeric_type() const
Returns the token representing the numeric type of the data storage.
const InternalName * get_name() const
Returns the name of this particular data field, e.g.
Contents get_contents() const
Returns the token representing the semantic meaning of the stored value.
int get_total_bytes() const
Returns the number of bytes used by each element of the column: component_bytes * 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...
Encapsulates the data from a GeomVertexData, pre-fetched for one stage of the pipeline.
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
A container for geometry primitives.
This is a base class for the GraphicsStateGuardian class, which is itself a base class for the variou...
virtual bool is_orthographic() const
Returns true if the lens represents a orthographic projection (i.e.
get_coordinate_system
Returns the coordinate system that all 3-d computations are performed within for this Lens.
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,...
static ConstPointerTo< RenderAttrib > make_all_off()
Constructs a new LightAttrib object that turns off all lights (and hence disables lighting).
This is a standard, non-reentrant mutex, similar to the Mutex class.
A lightweight class that represents a single element that may be timed and/or counted via stats.
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
static ConstPointerTo< RenderAttrib > make(Mode mode, PN_stdfloat thickness=1.0f, bool perspective=false, const LColor &wireframe_color=LColor::zero())
Constructs a new RenderModeAttrib object that specifies whether to draw polygons in the normal,...
get_perspective
Returns the perspective flag.
get_thickness
Returns the line width or point thickness.
get_mode
Returns the render mode.
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
static ConstPointerTo< RenderState > make(const RenderAttrib *attrib, int override=0)
Returns a RenderState with one attribute set.
const Lens * get_lens() const
Returns the particular Lens used for rendering.
int get_viewport_width() const
Returns the width of the viewport (display region) in pixels.
int get_viewport_height() const
Returns the height of the viewport (display region) in pixels.
bool auto_shader() const
If true, then this ShaderAttrib does not contain an explicit shader - instead, it requests the automa...
static ConstPointerTo< RenderAttrib > make(const Shader *shader=nullptr, int priority=0)
Constructs a new ShaderAttrib object with nothing set.
This is just a simple derivative of GeomMunger that adds the ability to munge states.
ConstPointerTo< RenderState > munge_state(const RenderState *state)
Given an input state, returns the munged state.
bool should_munge_state() const
Returns true if this munger has something interesting to do to the state.
ConstPointerTo< RenderAttrib > remove_stage(TextureStage *stage) const
Returns a new TexGenAttrib just like this one, with the indicated stage removed.
Mode get_mode(TextureStage *stage) const
Returns the generation mode associated with the named texture stage, or M_off if nothing is associate...
static ConstPointerTo< RenderAttrib > make_off()
Constructs a new TextureAttrib object suitable for rendering untextured geometry.
get_default
Returns the default TextureStage that will be used for all texturing that does not name a particular ...
A thread; that is, a lightweight process.
TypeHandle is the identifier used to differentiate C++ class types.
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.
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.
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.
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.