|
@@ -21,6 +21,31 @@
|
|
|
GeomMunger *CLP(GeomMunger)::_deleted_chain = NULL;
|
|
GeomMunger *CLP(GeomMunger)::_deleted_chain = NULL;
|
|
|
TypeHandle CLP(GeomMunger)::_type_handle;
|
|
TypeHandle CLP(GeomMunger)::_type_handle;
|
|
|
|
|
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+// Function: CLP(GeomMunger)::Constructor
|
|
|
|
|
+// Access: Public
|
|
|
|
|
+// Description:
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+INLINE CLP(GeomMunger)::
|
|
|
|
|
+CLP(GeomMunger)(GraphicsStateGuardian *gsg, const RenderState *state) :
|
|
|
|
|
+ StandardMunger(gsg, state, 4, NT_uint8, C_color),
|
|
|
|
|
+ _texture(state->get_texture()),
|
|
|
|
|
+ _tex_gen(state->get_tex_gen())
|
|
|
|
|
+{
|
|
|
|
|
+ // Set a callback to unregister ourselves when either the Texture or
|
|
|
|
|
+ // the TexGen object gets deleted.
|
|
|
|
|
+ _texture.set_callback(this);
|
|
|
|
|
+ _tex_gen.set_callback(this);
|
|
|
|
|
+
|
|
|
|
|
+ _flags = 0;
|
|
|
|
|
+
|
|
|
|
|
+ if (CLP(interleaved_arrays)) {
|
|
|
|
|
+ _flags |= F_interleaved_arrays;
|
|
|
|
|
+ } else if (CLP(parallel_arrays)) {
|
|
|
|
|
+ _flags |= F_parallel_arrays;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
|
// Function: CLP(GeomMunger)::Destructor
|
|
// Function: CLP(GeomMunger)::Destructor
|
|
|
// Access: Public, Virtual
|
|
// Access: Public, Virtual
|
|
@@ -113,22 +138,211 @@ munge_format_impl(const GeomVertexFormat *orig,
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /*
|
|
|
|
|
- if (true) {
|
|
|
|
|
|
|
+ CPT(GeomVertexFormat) format = GeomVertexFormat::register_format(new_format);
|
|
|
|
|
+
|
|
|
|
|
+ if ((_flags & F_parallel_arrays) != 0) {
|
|
|
|
|
+ // Split out the interleaved array into n parallel arrays.
|
|
|
|
|
+ new_format = new GeomVertexFormat;
|
|
|
|
|
+ for (int i = 0; i < format->get_num_columns(); ++i) {
|
|
|
|
|
+ const GeomVertexColumn *column = format->get_column(i);
|
|
|
|
|
+ PT(GeomVertexArrayFormat) new_array_format = new GeomVertexArrayFormat;
|
|
|
|
|
+ new_array_format->add_column(column->get_name(), column->get_num_components(),
|
|
|
|
|
+ column->get_numeric_type(), column->get_contents());
|
|
|
|
|
+ new_format->add_array(new_array_format);
|
|
|
|
|
+ }
|
|
|
|
|
+ format = GeomVertexFormat::register_format(new_format);
|
|
|
|
|
+
|
|
|
|
|
+ } else if ((_flags & F_interleaved_arrays) != 0) {
|
|
|
|
|
+ // Combine the primary data columns into a single array.
|
|
|
|
|
+ new_format = new GeomVertexFormat(*format);
|
|
|
|
|
+ PT(GeomVertexArrayFormat) new_array_format = new GeomVertexArrayFormat;
|
|
|
|
|
+
|
|
|
|
|
+ const GeomVertexColumn *column = format->get_vertex_column();
|
|
|
|
|
+ if (column != (const GeomVertexColumn *)NULL) {
|
|
|
|
|
+ new_array_format->add_column
|
|
|
|
|
+ (column->get_name(), column->get_num_components(),
|
|
|
|
|
+ column->get_numeric_type(), column->get_contents());
|
|
|
|
|
+ new_format->remove_column(column->get_name());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ column = format->get_normal_column();
|
|
|
|
|
+ if (column != (const GeomVertexColumn *)NULL) {
|
|
|
|
|
+ new_array_format->add_column
|
|
|
|
|
+ (column->get_name(), column->get_num_components(),
|
|
|
|
|
+ column->get_numeric_type(), column->get_contents());
|
|
|
|
|
+ new_format->remove_column(column->get_name());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ column = format->get_color_column();
|
|
|
|
|
+ if (column != (const GeomVertexColumn *)NULL) {
|
|
|
|
|
+ new_array_format->add_column
|
|
|
|
|
+ (column->get_name(), column->get_num_components(),
|
|
|
|
|
+ column->get_numeric_type(), column->get_contents());
|
|
|
|
|
+ new_format->remove_column(column->get_name());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Put only the used texture coordinates into the interleaved
|
|
|
|
|
+ // array.
|
|
|
|
|
+ if (_texture != (TextureAttrib *)NULL) {
|
|
|
|
|
+ typedef pset<const InternalName *> UsedStages;
|
|
|
|
|
+ UsedStages used_stages;
|
|
|
|
|
+
|
|
|
|
|
+ int num_stages = _texture->get_num_on_stages();
|
|
|
|
|
+ for (int i = 0; i < num_stages; ++i) {
|
|
|
|
|
+ TextureStage *stage = _texture->get_on_stage(i);
|
|
|
|
|
+ if (_tex_gen == (TexGenAttrib *)NULL ||
|
|
|
|
|
+ !_tex_gen->has_stage(stage)) {
|
|
|
|
|
+ InternalName *name = stage->get_texcoord_name();
|
|
|
|
|
+ if (used_stages.insert(name).second) {
|
|
|
|
|
+ // This is the first time we've encountered this texcoord name.
|
|
|
|
|
+ const GeomVertexColumn *texcoord_type = format->get_column(name);
|
|
|
|
|
+
|
|
|
|
|
+ if (texcoord_type != (const GeomVertexColumn *)NULL) {
|
|
|
|
|
+ new_array_format->add_column
|
|
|
|
|
+ (name, texcoord_type->get_num_values(), NT_float32, C_texcoord);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // We have to add something as a placeholder, even if the
|
|
|
|
|
+ // texture coordinates aren't defined.
|
|
|
|
|
+ new_array_format->add_column(name, 2, NT_float32, C_texcoord);
|
|
|
|
|
+ }
|
|
|
|
|
+ new_format->remove_column(name);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ new_format->insert_array(0, new_array_format);
|
|
|
|
|
+ format = GeomVertexFormat::register_format(new_format);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return format;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+// Function: CLP(GeomMunger)::premunge_format_impl
|
|
|
|
|
+// Access: Protected, Virtual
|
|
|
|
|
+// Description: Given a source GeomVertexFormat, converts it if
|
|
|
|
|
+// necessary to the appropriate format for rendering.
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+CPT(GeomVertexFormat) CLP(GeomMunger)::
|
|
|
|
|
+premunge_format_impl(const GeomVertexFormat *orig) {
|
|
|
|
|
+ PT(GeomVertexFormat) new_format = new GeomVertexFormat(*orig);
|
|
|
|
|
+
|
|
|
|
|
+ const GeomVertexColumn *color_type = orig->get_color_column();
|
|
|
|
|
+ if (color_type != (GeomVertexColumn *)NULL &&
|
|
|
|
|
+ color_type->get_numeric_type() == NT_packed_dabc) {
|
|
|
|
|
+ // We need to convert the color format; OpenGL doesn't support the
|
|
|
|
|
+ // byte order of DirectX's packed ARGB format.
|
|
|
|
|
+ int color_array = orig->get_array_with(InternalName::get_color());
|
|
|
|
|
+
|
|
|
|
|
+ PT(GeomVertexArrayFormat) new_array_format = new_format->modify_array(color_array);
|
|
|
|
|
+
|
|
|
|
|
+ // Replace the existing color format with the new format.
|
|
|
|
|
+ new_array_format->add_column
|
|
|
|
|
+ (InternalName::get_color(), 4, NT_uint8,
|
|
|
|
|
+ C_color, color_type->get_start());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ CPT(GeomVertexFormat) format = GeomVertexFormat::register_format(new_format);
|
|
|
|
|
+
|
|
|
|
|
+ if ((_flags & F_parallel_arrays) != 0) {
|
|
|
// Split out the interleaved array into n parallel arrays.
|
|
// Split out the interleaved array into n parallel arrays.
|
|
|
- CPT(GeomVertexFormat) format = new_format;
|
|
|
|
|
new_format = new GeomVertexFormat;
|
|
new_format = new GeomVertexFormat;
|
|
|
- for (int i = 0; i < format->get_num_columns(); i++) {
|
|
|
|
|
|
|
+ for (int i = 0; i < format->get_num_columns(); ++i) {
|
|
|
const GeomVertexColumn *column = format->get_column(i);
|
|
const GeomVertexColumn *column = format->get_column(i);
|
|
|
PT(GeomVertexArrayFormat) new_array_format = new GeomVertexArrayFormat;
|
|
PT(GeomVertexArrayFormat) new_array_format = new GeomVertexArrayFormat;
|
|
|
new_array_format->add_column(column->get_name(), column->get_num_components(),
|
|
new_array_format->add_column(column->get_name(), column->get_num_components(),
|
|
|
- column->get_numeric_type());
|
|
|
|
|
|
|
+ column->get_numeric_type(), column->get_contents());
|
|
|
new_format->add_array(new_array_format);
|
|
new_format->add_array(new_array_format);
|
|
|
}
|
|
}
|
|
|
|
|
+ format = GeomVertexFormat::register_format(new_format);
|
|
|
|
|
+
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // Combine the primary data columns into a single array. Unlike
|
|
|
|
|
+ // the munge case, above, in the premunge case, we do this even if
|
|
|
|
|
+ // F_interleaved_arrays is not set (unless F_parallel_arrays is
|
|
|
|
|
+ // set), since the presumption is that you're more willing to pay
|
|
|
|
|
+ // the overhead of doing this step at load time than you might be
|
|
|
|
|
+ // at run time.
|
|
|
|
|
+ new_format = new GeomVertexFormat(*format);
|
|
|
|
|
+ PT(GeomVertexArrayFormat) new_array_format = new GeomVertexArrayFormat;
|
|
|
|
|
+
|
|
|
|
|
+ const GeomVertexColumn *column = format->get_vertex_column();
|
|
|
|
|
+ if (column != (const GeomVertexColumn *)NULL) {
|
|
|
|
|
+ new_array_format->add_column
|
|
|
|
|
+ (column->get_name(), column->get_num_components(),
|
|
|
|
|
+ column->get_numeric_type(), column->get_contents());
|
|
|
|
|
+ new_format->remove_column(column->get_name());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ column = format->get_normal_column();
|
|
|
|
|
+ if (column != (const GeomVertexColumn *)NULL) {
|
|
|
|
|
+ new_array_format->add_column
|
|
|
|
|
+ (column->get_name(), column->get_num_components(),
|
|
|
|
|
+ column->get_numeric_type(), column->get_contents());
|
|
|
|
|
+ new_format->remove_column(column->get_name());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ column = format->get_color_column();
|
|
|
|
|
+ if (column != (const GeomVertexColumn *)NULL) {
|
|
|
|
|
+ new_array_format->add_column
|
|
|
|
|
+ (column->get_name(), column->get_num_components(),
|
|
|
|
|
+ column->get_numeric_type(), column->get_contents());
|
|
|
|
|
+ new_format->remove_column(column->get_name());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Put only the used texture coordinates into the interleaved
|
|
|
|
|
+ // array. The others will be kept around, but in a parallel
|
|
|
|
|
+ // array.
|
|
|
|
|
+ if (_texture != (TextureAttrib *)NULL) {
|
|
|
|
|
+ typedef pset<const InternalName *> UsedStages;
|
|
|
|
|
+ UsedStages used_stages;
|
|
|
|
|
+
|
|
|
|
|
+ int num_stages = _texture->get_num_on_stages();
|
|
|
|
|
+ for (int i = 0; i < num_stages; ++i) {
|
|
|
|
|
+ TextureStage *stage = _texture->get_on_stage(i);
|
|
|
|
|
+ if (_tex_gen == (TexGenAttrib *)NULL ||
|
|
|
|
|
+ !_tex_gen->has_stage(stage)) {
|
|
|
|
|
+ InternalName *name = stage->get_texcoord_name();
|
|
|
|
|
+ if (used_stages.insert(name).second) {
|
|
|
|
|
+ // This is the first time we've encountered this texcoord name.
|
|
|
|
|
+ const GeomVertexColumn *texcoord_type = format->get_column(name);
|
|
|
|
|
+
|
|
|
|
|
+ if (texcoord_type != (const GeomVertexColumn *)NULL) {
|
|
|
|
|
+ new_array_format->add_column
|
|
|
|
|
+ (name, texcoord_type->get_num_values(), NT_float32, C_texcoord);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // We have to add something as a placeholder, even if the
|
|
|
|
|
+ // texture coordinates aren't defined.
|
|
|
|
|
+ new_array_format->add_column(name, 2, NT_float32, C_texcoord);
|
|
|
|
|
+ }
|
|
|
|
|
+ new_format->remove_column(name);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Now go through the remaining arrays and make sure they are
|
|
|
|
|
+ // tightly packed. If not, repack them.
|
|
|
|
|
+ for (int i = 0; i < new_format->get_num_arrays(); ++i) {
|
|
|
|
|
+ CPT(GeomVertexArrayFormat) orig_a = new_format->get_array(i);
|
|
|
|
|
+ if (orig_a->count_unused_space() != 0) {
|
|
|
|
|
+ PT(GeomVertexArrayFormat) new_a = new GeomVertexArrayFormat;
|
|
|
|
|
+ for (int j = 0; j < orig_a->get_num_columns(); ++j) {
|
|
|
|
|
+ const GeomVertexColumn *column = orig_a->get_column(j);
|
|
|
|
|
+ new_a->add_column(column->get_name(), column->get_num_components(),
|
|
|
|
|
+ column->get_numeric_type(), column->get_contents());
|
|
|
|
|
+ }
|
|
|
|
|
+ new_format->set_array(i, new_a);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Finally, insert the interleaved array first in the format.
|
|
|
|
|
+ new_format->insert_array(0, new_array_format);
|
|
|
|
|
+ format = GeomVertexFormat::register_format(new_format);
|
|
|
}
|
|
}
|
|
|
- */
|
|
|
|
|
|
|
|
|
|
- return GeomVertexFormat::register_format(new_format);
|
|
|
|
|
|
|
+ return format;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
@@ -148,6 +362,9 @@ compare_to_impl(const GeomMunger *other) const {
|
|
|
if (_tex_gen != om->_tex_gen) {
|
|
if (_tex_gen != om->_tex_gen) {
|
|
|
return _tex_gen < om->_tex_gen ? -1 : 1;
|
|
return _tex_gen < om->_tex_gen ? -1 : 1;
|
|
|
}
|
|
}
|
|
|
|
|
+ if (_flags != om->_flags) {
|
|
|
|
|
+ return _flags < om->_flags ? -1 : 1;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
return StandardMunger::compare_to_impl(other);
|
|
return StandardMunger::compare_to_impl(other);
|
|
|
}
|
|
}
|
|
@@ -162,8 +379,16 @@ compare_to_impl(const GeomMunger *other) const {
|
|
|
////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
|
int CLP(GeomMunger)::
|
|
int CLP(GeomMunger)::
|
|
|
geom_compare_to_impl(const GeomMunger *other) const {
|
|
geom_compare_to_impl(const GeomMunger *other) const {
|
|
|
- // We don't consider _texture and _tex_gen for this purpose; they
|
|
|
|
|
- // affect only whether the GL display list should be regenerated or
|
|
|
|
|
- // not, and don't require reconverting the vertices.
|
|
|
|
|
- return StandardMunger::geom_compare_to_impl(other);
|
|
|
|
|
|
|
+ const CLP(GeomMunger) *om = DCAST(CLP(GeomMunger), other);
|
|
|
|
|
+ if (_texture != om->_texture) {
|
|
|
|
|
+ return _texture < om->_texture ? -1 : 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (_tex_gen != om->_tex_gen) {
|
|
|
|
|
+ return _tex_gen < om->_tex_gen ? -1 : 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (_flags != om->_flags) {
|
|
|
|
|
+ return _flags < om->_flags ? -1 : 1;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return StandardMunger::compare_to_impl(other);
|
|
|
}
|
|
}
|