15 #include "cullableObject.h" 16 #include "lightAttrib.h" 18 #include "colorAttrib.h" 19 #include "texGenAttrib.h" 20 #include "textureAttrib.h" 21 #include "renderState.h" 22 #include "clockObject.h" 23 #include "cullTraverser.h" 24 #include "sceneSetup.h" 26 #include "stateMunger.h" 27 #include "pStatTimer.h" 28 #include "geomVertexWriter.h" 29 #include "geomVertexReader.h" 30 #include "geomTriangles.h" 32 #include "lightMutexHolder.h" 37 PStatCollector CullableObject::_munge_geom_pcollector(
"*:Munge:Geom");
38 PStatCollector CullableObject::_munge_sprites_pcollector(
"*:Munge:Sprites");
39 PStatCollector CullableObject::_munge_sprites_verts_pcollector(
"*:Munge:Sprites:Verts");
40 PStatCollector CullableObject::_munge_sprites_prims_pcollector(
"*:Munge:Sprites:Prims");
41 PStatCollector CullableObject::_sw_sprites_pcollector(
"SW Sprites");
62 PStatTimer timer(_munge_geom_pcollector, current_thread);
63 if (_geom != (
Geom *)NULL) {
70 _munged_data = geom_reader.get_vertex_data();
75 data_reader.check_array_readers();
76 nassertr(geom_reader.check_valid(&data_reader),
false);
80 geom_rendering = geom_reader.get_geom_rendering();
81 geom_rendering = _state->get_geom_rendering(geom_rendering);
82 geom_rendering = _internal_transform->get_geom_rendering(geom_rendering);
84 if (geom_rendering & Geom::GR_point_bits) {
85 if (geom_reader.get_primitive_type() != Geom::PT_points) {
86 if (singular_points) {
88 _geom = _geom->make_points();
95 int gsg_bits = gsg->get_supported_geom_rendering();
96 if (!hardware_point_sprites) {
100 gsg_bits &= ~(Geom::GR_point_perspective | Geom::GR_point_sprite);
102 if (!hardware_points) {
105 gsg_bits &= ~(Geom::GR_point_bits & ~
Geom::GR_point);
107 int unsupported_bits = geom_rendering & ~gsg_bits;
109 if ((unsupported_bits & Geom::GR_point_bits) != 0) {
114 if (pgraph_cat.is_spam()) {
116 <<
"munge_points_to_quads() for geometry with bits: " 117 << hex << geom_rendering <<
", unsupported: " 118 << (unsupported_bits & Geom::GR_point_bits) << dec <<
"\n";
120 if (!munge_points_to_quads(traverser, force)) {
127 if (!munger->
munge_geom(_geom, _munged_data, force, current_thread)) {
132 DCAST_INTO_R(state_munger, munger,
false);
133 _state = state_munger->munge_state(_state);
139 bool cpu_animated =
false;
142 _munged_data->animate_vertices(force, current_thread);
143 if (animated_vertices != _munged_data) {
145 swap(_munged_data, animated_vertices);
149 if (show_vertex_animation) {
151 bool hardware_animated = (data_reader.get_format()->get_animation().get_animation_type() == Geom::AT_hardware);
152 if (cpu_animated || hardware_animated) {
154 static const double flash_rate = 1.0;
156 if ((cycle & 1) == 0) {
157 _state = cpu_animated ? get_flash_cpu_state() : get_flash_hardware_state();
172 void CullableObject::
173 output(ostream &out)
const {
174 if (_geom != (
Geom *)NULL) {
189 bool CullableObject::
190 munge_points_to_quads(
const CullTraverser *traverser,
bool force) {
196 _munged_data->animate_vertices(force, current_thread);
198 if (!force && !source_data->request_resident()) {
202 PStatTimer timer(_munge_sprites_pcollector, current_thread);
203 _sw_sprites_pcollector.add_level(source_data->get_num_rows());
219 GeomVertexReader aspect_ratio(source_data, InternalName::get_aspect_ratio(),
227 bool has_aspect_ratio = (aspect_ratio.
has_column());
229 bool sprite_texcoord =
false;
233 sprite_texcoord =
true;
240 PN_stdfloat point_size = 1;
241 bool perspective =
false;
247 if (render_mode->
get_mode() != RenderModeAttrib::M_filled_flat) {
250 _state = _state->set_attrib(RenderModeAttrib::make(RenderModeAttrib::M_filled_flat));
255 CPT(GeomVertexFormat) new_format;
259 SourceFormat sformat(source_data->get_format(), sprite_texcoord);
260 FormatMap::iterator fmi = _format_map.find(sformat);
261 if (fmi != _format_map.end()) {
262 new_format = (*fmi).second;
266 PT(GeomVertexArrayFormat) new_array_format;
267 if (sformat._retransform_sprites) {
271 new GeomVertexArrayFormat(InternalName::get_vertex(), 3,
278 new GeomVertexArrayFormat(InternalName::get_vertex(), 4,
284 new_array_format->add_column
290 new_array_format->add_column
294 if (sprite_texcoord) {
295 new_array_format->add_column
296 (InternalName::get_texcoord(), 2,
300 }
else if (has_texcoord) {
302 new_array_format->add_column
307 new_format = GeomVertexFormat::register_format(new_array_format);
308 _format_map[sformat] = new_format;
312 CoordinateSystem internal_cs = gsg->get_internal_coordinate_system();
313 LMatrix4 internal = _internal_transform->get_mat();
314 PN_stdfloat scale = _internal_transform->get_scale()[1];
334 LMatrix4 render_transform =
internal * projection;
336 inv_render_transform.
invert_from(render_transform);
342 int orig_verts = source_data->get_num_rows();
343 int new_verts = 4 * orig_verts;
346 (source_data->get_name(), new_format, Geom::UH_stream);
359 PStatTimer t2(_munge_sprites_verts_pcollector, current_thread);
360 points = (PointData *)alloca(orig_verts *
sizeof(PointData));
365 PN_stdfloat dist = gsg->compute_distance_to(eye);
366 points[vi]._dist = dist;
375 PN_stdfloat scale_y = point_size;
381 LVector3 height(0.0f, point_size * scale, scale);
382 height = height * height_projection;
383 scale_y = height[1] * viewport_height;
396 PN_stdfloat scale_x = scale_y;
397 if (has_aspect_ratio) {
415 PN_stdfloat rx = 1.0f / viewport_width;
416 PN_stdfloat ry = 1.0f / viewport_height;
417 c0.set(c0[0] * rx, c0[1] * ry);
418 c1.set(c1[0] * rx, c1[1] * ry);
420 if (retransform_sprites) {
423 new_vertex.
set_data4(inv_render_transform.
xform(
LPoint4(p4[0] + c0[0], p4[1] + c0[1], p4[2], p4[3])));
424 new_vertex.
set_data4(inv_render_transform.
xform(
LPoint4(p4[0] + c1[0], p4[1] + c1[1], p4[2], p4[3])));
425 new_vertex.
set_data4(inv_render_transform.
xform(
LPoint4(p4[0] - c1[0], p4[1] - c1[1], p4[2], p4[3])));
426 new_vertex.
set_data4(inv_render_transform.
xform(
LPoint4(p4[0] - c0[0], p4[1] - c0[1], p4[2], p4[3])));
439 new_vertex.
set_data4(p4[0] + c0[0], p4[1] + c0[1], p4[2], p4[3]);
440 new_vertex.
set_data4(p4[0] + c1[0], p4[1] + c1[1], p4[2], p4[3]);
441 new_vertex.
set_data4(p4[0] - c1[0], p4[1] - c1[1], p4[2], p4[3]);
442 new_vertex.
set_data4(p4[0] - c0[0], p4[1] - c0[1], p4[2], p4[3]);
459 if (sprite_texcoord) {
464 }
else if (has_texcoord) {
475 nassertr(vi == orig_verts,
false);
476 nassertr(new_data->get_num_rows() == new_verts,
false);
481 const GeomVertexArrayFormat *new_prim_format = NULL;
482 if (new_verts < 0xffff) {
489 PT(
Geom) new_geom =
new Geom(new_data);
505 PStatTimer t3(_munge_sprites_prims_pcollector, current_thread);
507 int num_primitives = geom_reader.get_num_primitives();
508 for (
int pi = 0; pi < num_primitives; ++pi) {
509 const GeomPrimitive *primitive = geom_reader.get_primitive(pi);
513 unsigned int *vertices = (
unsigned int *)alloca(num_vertices *
sizeof(
unsigned int));
514 unsigned int *vertices_end = vertices + num_vertices;
519 for (
unsigned int *vi = vertices; vi != vertices_end; ++vi) {
521 nassertr(v < (
unsigned int)orig_verts,
false);
527 for (
int i = 0; i < num_vertices; ++i) {
528 unsigned int v = i + first_vertex;
529 nassertr(v < (
unsigned int)orig_verts,
false);
536 sort(vertices, vertices_end, SortPoints(points));
545 int new_prim_verts = 6 * num_vertices;
549 new_index->unclean_set_num_rows(new_prim_verts);
553 for (
unsigned int *vi = vertices; vi != vertices_end; ++vi) {
554 int new_vi = (*vi) * 4;
555 nassertr(index.
get_write_row() + 6 <= new_prim_verts,
false);
563 new_primitive->set_vertices(new_index, new_prim_verts);
567 new_primitive->set_minmax(min_vi * 4, max_vi * 4 + 3, NULL, NULL);
569 new_geom->add_primitive(new_primitive);
574 _geom = new_geom.p();
576 #ifdef USE_MOVE_SEMANTICS 577 _munged_data = move(new_data);
579 _munged_data = new_data;
593 get_flash_cpu_state() {
594 static const LColor flash_cpu_color(0.8f, 0.2, 0.2, 1.0f);
599 if (flash_cpu_state == (
const RenderState *)NULL) {
600 flash_cpu_state = RenderState::make
601 (LightAttrib::make_all_off(),
602 TextureAttrib::make_off(),
603 ColorAttrib::make_flat(flash_cpu_color));
606 return flash_cpu_state;
617 get_flash_hardware_state() {
618 static const LColor flash_hardware_color(0.2, 0.2, 0.8, 1.0);
623 if (flash_hardware_state == (
const RenderState *)NULL) {
624 flash_hardware_state = RenderState::make
625 (LightAttrib::make_all_off(),
626 TextureAttrib::make_off(),
627 ColorAttrib::make_flat(flash_hardware_color));
630 return flash_hardware_state;
638 CullableObject::SourceFormat::
639 SourceFormat(
const GeomVertexFormat *format,
bool sprite_texcoord) :
641 _sprite_texcoord(sprite_texcoord)
643 _retransform_sprites = retransform_sprites;
This is just a simple derivative of GeomMunger that adds the ability to munge states.
static ClockObject * get_global_clock()
Returns a pointer to the global ClockObject.
This object provides a high-level interface for quickly writing a sequence of numeric values from a v...
Mode get_mode() const
Returns the render mode.
This is our own Panda specialization on the default STL map.
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.
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.
virtual bool is_orthographic() const
Returns true if the lens represents a orthographic projection (i.e.
int get_max_vertex() const
Returns the maximum vertex index number used by all the primitives in this object.
void set_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. ...
LVecBase3f xform_vec(const LVecBase3f &v) const
The matrix transforms a 3-component vector (without translation component) and returns the result...
Thread * get_current_thread() const
Returns the currently-executing thread object, as passed to the CullTraverser constructor.
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 ...
const GeomVertexColumn * get_column() const
Returns the description of the data type that the reader is working on.
This is an abstract base class for a family of classes that represent the fundamental geometry primit...
int get_num_vertices() const
Returns the number of indices used by all the primitives in this object.
const LVecBase4 & get_data4()
Returns the data associated with the read row, expressed as a 4-component value, and advances the rea...
const Lens * get_lens() const
Returns the particular Lens used for rendering.
This is a three-component vector distance (as opposed to a three-component point, which represents a ...
void set_data1i(int data)
Sets the write row to a particular 1-component value, and advances the write row. ...
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
This is a three-component point in space (as opposed to a three-component vector, which represents a ...
double get_frame_time(Thread *current_thread=Thread::get_current_thread()) const
Returns the time in seconds as of the last time tick() was called (typically, this will be as of the ...
bool get_perspective() const
Returns the perspective flag.
Encapsulates the data from a Geom, pre-fetched for one stage of the pipeline.
static const LMatrix4f & convert_mat(CoordinateSystem from, CoordinateSystem to)
Returns a matrix that transforms from the indicated coordinate system to the indicated coordinate sys...
int get_first_vertex() const
Returns the first vertex number referenced by the primitive.
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.
void set_data2(PN_stdfloat x, PN_stdfloat y)
Sets the write row to a particular 2-component value, and advances the write row. ...
A lightweight class that represents a single element that may be timed and/or counted via stats...
PN_stdfloat get_thickness() const
Returns the line width or point thickness.
int get_min_vertex() const
Returns the minimum vertex index number used by all the primitives in this object.
This is a 4-by-4 transform matrix.
Similar to MutexHolder, but for a light mutex.
bool has_column() const
Returns true if a valid data type has been successfully set, or false if the data type does not exist...
int get_viewport_width() const
Returns the width of the viewport (display region) in pixels.
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
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.
bool invert_from(const LMatrix4f &other)
Computes the inverse of the other matrix, and stores the result in this matrix.
const LVecBase3 & get_data3()
Returns the data associated with the read row, expressed as a 3-component value, and advances the rea...
void set_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. ...
LVecBase4f xform(const LVecBase4f &v) const
4-component vector or point times matrix.
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.
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
This is the base class for all three-component vectors and points.
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...
This is a base class for the GraphicsStateGuardian class, which is itself a base class for the variou...
bool has_column() const
Returns true if a valid data type has been successfully set, or false if the data type does not exist...
This is a four-component point in space.
A thread; that is, a lightweight process.
This object provides a high-level interface for quickly reading a sequence of numeric values from a v...
static LMatrix3f rotate_mat(float angle)
Returns a matrix that rotates by the given angle in degrees counterclockwise.
SceneSetup * get_scene() const
Returns the SceneSetup object.
bool is_at_end() const
Returns true if the reader is currently at the end of the list of vertices, false otherwise...
CoordinateSystem get_coordinate_system() const
Returns the coordinate system that all 3-d computations are performed within for this Lens...
Defines a series of disconnected triangles.
Specifies how polygons are to be drawn.
Encapsulates the data from a GeomVertexData, pre-fetched for one stage of the pipeline.
This is a two-component point in space.
TypeHandle is the identifier used to differentiate C++ class types.
This is a 3-by-3 transform matrix.
This object holds the camera position, etc., and other general setup information for rendering a part...
static TextureStage * get_default()
Returns the default TextureStage that will be used for all texturing that does not name a particular ...
This is a standard, non-reentrant mutex, similar to the Mutex class.
int get_num_components() const
Returns the number of components of the column: the number of instances of the NumericType in each el...
Computes texture coordinates for geometry automatically based on vertex position and/or normal...
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...
bool is_indexed() const
Returns true if the primitive is indexed, false otherwise.
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling...
int get_write_row() const
Returns the row index to which the data will be written at the next call to set_data*() or add_data*(...
This is the data for one array of a GeomVertexData structure.
PN_stdfloat get_data1()
Returns the data associated with the read row, expressed as a 1-component value, and advances the rea...