Panda3D
 All Classes Functions Variables Enumerations
standardMunger.cxx
00001 // Filename: standardMunger.cxx
00002 // Created by:  drose (21Mar05)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "standardMunger.h"
00016 #include "renderState.h"
00017 #include "graphicsStateGuardian.h"
00018 #include "dcast.h"
00019 #include "config_gobj.h"
00020 #include "displayRegion.h"
00021 
00022 TypeHandle StandardMunger::_type_handle;
00023 
00024 ////////////////////////////////////////////////////////////////////
00025 //     Function: StandardMunger::Constructor
00026 //       Access: Public
00027 //  Description: The StandardMunger constructor accepts additional
00028 //               parameters that specify the GSG's preferred color
00029 //               format (since we might be munging the color anyway,
00030 //               we might as well convert it as we munge).
00031 ////////////////////////////////////////////////////////////////////
00032 StandardMunger::
00033 StandardMunger(GraphicsStateGuardianBase *gsg, const RenderState *state,
00034                int num_components,
00035                StandardMunger::NumericType numeric_type,
00036                StandardMunger::Contents contents) :
00037   StateMunger(gsg),
00038   _num_components(num_components),
00039   _numeric_type(numeric_type),
00040   _contents(contents)
00041 {
00042   _render_mode = DCAST(RenderModeAttrib, state->get_attrib(RenderModeAttrib::get_class_slot()));
00043 
00044   _munge_color = false;
00045   _munge_color_scale = false;
00046 
00047   if (!get_gsg()->get_runtime_color_scale()) {
00048     // We might need to munge the colors.
00049     CPT(ColorAttrib) color_attrib = DCAST(ColorAttrib, state->get_attrib(ColorAttrib::get_class_slot()));
00050     CPT(ColorScaleAttrib) color_scale_attrib = DCAST(ColorScaleAttrib, state->get_attrib(ColorScaleAttrib::get_class_slot()));
00051 
00052     if (color_attrib != (ColorAttrib *)NULL && 
00053         color_attrib->get_color_type() == ColorAttrib::T_flat) {
00054       
00055       if (!get_gsg()->get_color_scale_via_lighting()) {
00056         // We only need to munge the color directly if the GSG says it
00057         // can't cheat the color via lighting (presumably, in this case,
00058         // by applying a material).
00059         _color = color_attrib->get_color();
00060         if (color_scale_attrib != (ColorScaleAttrib *)NULL &&
00061             color_scale_attrib->has_scale()) {
00062           const LVecBase4 &cs = color_scale_attrib->get_scale();
00063           _color.set(_color[0] * cs[0],
00064                      _color[1] * cs[1],
00065                      _color[2] * cs[2],
00066                      _color[3] * cs[3]);
00067         }
00068         _munge_color = true;
00069       }
00070       
00071     } else if (color_scale_attrib != (ColorScaleAttrib *)NULL &&
00072                color_scale_attrib->has_scale()) {
00073       _color_scale = color_scale_attrib->get_scale();
00074       
00075       CPT(TextureAttrib) tex_attrib = DCAST(TextureAttrib, state->get_attrib(TextureAttrib::get_class_slot()));
00076       
00077       // If the GSG says it can't cheat this RGB or alpha scale, we have
00078       // to apply the color scale directly.
00079       if ((color_scale_attrib->has_rgb_scale() && !get_gsg()->get_color_scale_via_lighting()) ||
00080           (color_scale_attrib->has_alpha_scale() && !get_gsg()->get_alpha_scale_via_texture(tex_attrib))) {
00081         _munge_color_scale = true;
00082       }
00083       
00084       // Known bug: if there is a material on an object that would
00085       // obscure the effect of color_scale, we scale the lighting
00086       // anyway, thus applying the effect even if it should be obscured.
00087       // It doesn't seem worth the effort to detect this contrived
00088       // situation and handle it correctly.
00089     }
00090   }
00091 }
00092 
00093 ////////////////////////////////////////////////////////////////////
00094 //     Function: StandardMunger::Destructor
00095 //       Access: Public, Virtual
00096 //  Description: 
00097 ////////////////////////////////////////////////////////////////////
00098 StandardMunger::
00099 ~StandardMunger() {
00100 }
00101 
00102 ////////////////////////////////////////////////////////////////////
00103 //     Function: StandardMunger::munge_data_impl
00104 //       Access: Protected, Virtual
00105 //  Description: Given a source GeomVertexData, converts it as
00106 //               necessary for rendering.
00107 ////////////////////////////////////////////////////////////////////
00108 CPT(GeomVertexData) StandardMunger::
00109 munge_data_impl(const GeomVertexData *data) {
00110   CPT(GeomVertexData) new_data = data;
00111 
00112   if (_munge_color) {
00113     new_data = new_data->set_color(_color, _num_components, _numeric_type,
00114                                    _contents);
00115   } else if (_munge_color_scale) {
00116     new_data = new_data->scale_color(_color_scale, _num_components, 
00117                                      _numeric_type, _contents);
00118   }
00119 
00120   GeomVertexAnimationSpec animation = new_data->get_format()->get_animation();
00121   if (hardware_animated_vertices &&
00122       animation.get_animation_type() == AT_panda &&
00123       new_data->get_slider_table() == (SliderTable *)NULL) {
00124     // Maybe we can animate the vertices with hardware.
00125     const TransformBlendTable *table = new_data->get_transform_blend_table();
00126     if (table != (TransformBlendTable *)NULL &&
00127         table->get_num_transforms() != 0 &&
00128         table->get_max_simultaneous_transforms() <= 
00129         get_gsg()->get_max_vertex_transforms()) {
00130       if (matrix_palette && 
00131           table->get_num_transforms() <= get_gsg()->get_max_vertex_transform_indices()) {
00132 
00133         if (table->get_num_transforms() == table->get_max_simultaneous_transforms()) {
00134           // We can support an indexed palette, but since that won't
00135           // save us any per-vertex blends, go ahead and do a plain
00136           // old nonindexed table instead.
00137           animation.set_hardware(table->get_num_transforms(), false);
00138 
00139         } else {
00140           // We can support an indexed palette, and that means we can
00141           // reduce the number of blends we have to specify for each
00142           // vertex.
00143           animation.set_hardware(table->get_max_simultaneous_transforms(), true);
00144         }
00145 
00146       } else if (table->get_num_transforms() <=
00147                  get_gsg()->get_max_vertex_transforms()) {
00148         // We can't support an indexed palette, but we have few enough
00149         // transforms that we can do a nonindexed table.
00150         animation.set_hardware(table->get_num_transforms(), false);
00151       }
00152     }
00153   }
00154   
00155   CPT(GeomVertexFormat) orig_format = new_data->get_format();
00156   CPT(GeomVertexFormat) new_format = munge_format(orig_format, animation);
00157 
00158   if (new_format == orig_format) {
00159     // Trivial case.
00160     return new_data;
00161   }
00162 
00163   return new_data->convert_to(new_format);
00164 }
00165 
00166 ////////////////////////////////////////////////////////////////////
00167 //     Function: StandardMunger::munge_geom_impl
00168 //       Access: Protected, Virtual
00169 //  Description: Converts a Geom and/or its data as necessary.
00170 ////////////////////////////////////////////////////////////////////
00171 void StandardMunger::
00172 munge_geom_impl(CPT(Geom) &geom, CPT(GeomVertexData) &vertex_data, 
00173                 Thread *) {
00174   int supported_geom_rendering = get_gsg()->get_supported_geom_rendering();
00175 
00176   int unsupported_bits = geom->get_geom_rendering() & ~supported_geom_rendering;
00177   if (unsupported_bits != 0) {
00178     // Even beyond munging the vertex format, we have to convert the
00179     // Geom itself into a new primitive type the GSG can render
00180     // directly.
00181     if ((unsupported_bits & Geom::GR_composite_bits) != 0) {
00182       // This decomposes everything in the primitive, so that if (for
00183       // instance) the primitive contained both strips and fans, but
00184       // the GSG didn't support fans, it would decompose the strips
00185       // too.  To handle this correctly, we'd need a separate
00186       // decompose_fans() and decompose_strips() call; but for now,
00187       // we'll just say it's good enough.  In practice, we don't have
00188       // any GSG's that can support strips without also supporting
00189       // fans.
00190       geom = geom->decompose();
00191 
00192       // Decomposing might produce an indexed Geom, so re-check the
00193       // unsupported bits.
00194       unsupported_bits = geom->get_geom_rendering() & ~supported_geom_rendering;
00195     }
00196     if ((unsupported_bits & Geom::GR_shade_model_bits) != 0) {
00197       // Rotate the vertices to account for different shade-model
00198       // expectations (e.g. SM_flat_last_vertex to
00199       // SM_flat_first_vertex)
00200       geom = geom->rotate();
00201     }
00202     if ((unsupported_bits & Geom::GR_indexed_bits) != 0) {
00203       // Convert indexed geometry to nonindexed geometry.
00204       PT(Geom) new_geom = geom->make_copy();
00205       new_geom->set_vertex_data(vertex_data);
00206       new_geom->make_nonindexed(false);
00207       geom = new_geom;
00208       vertex_data = new_geom->get_vertex_data();
00209     }
00210   }
00211 }
00212 
00213 ////////////////////////////////////////////////////////////////////
00214 //     Function: StandardMunger::premunge_geom_impl
00215 //       Access: Protected, Virtual
00216 //  Description: Converts a Geom and/or its data as necessary.
00217 ////////////////////////////////////////////////////////////////////
00218 void StandardMunger::
00219 premunge_geom_impl(CPT(Geom) &geom, CPT(GeomVertexData) &vertex_data) {
00220   int supported_geom_rendering = get_gsg()->get_supported_geom_rendering();
00221 
00222   int unsupported_bits = geom->get_geom_rendering() & ~supported_geom_rendering;
00223   if (unsupported_bits != 0) {
00224     // Even beyond munging the vertex format, we have to convert the
00225     // Geom itself into a new primitive type the GSG can render
00226     // directly.
00227     if ((unsupported_bits & Geom::GR_composite_bits) != 0) {
00228       // This decomposes everything in the primitive, so that if (for
00229       // instance) the primitive contained both strips and fans, but
00230       // the GSG didn't support fans, it would decompose the strips
00231       // too.  To handle this correctly, we'd need a separate
00232       // decompose_fans() and decompose_strips() call; but for now,
00233       // we'll just say it's good enough.  In practice, we don't have
00234       // any GSG's that can support strips without also supporting
00235       // fans.
00236       geom = geom->decompose();
00237 
00238       // Decomposing might produce an indexed Geom, so re-check the
00239       // unsupported bits.
00240       unsupported_bits = geom->get_geom_rendering() & ~supported_geom_rendering;
00241     }
00242     if ((unsupported_bits & Geom::GR_shade_model_bits) != 0) {
00243       // Rotate the vertices to account for different shade-model
00244       // expectations (e.g. SM_flat_last_vertex to
00245       // SM_flat_first_vertex)
00246       geom = geom->rotate();
00247     }
00248     if ((unsupported_bits & Geom::GR_indexed_bits) != 0) {
00249       // Convert indexed geometry to nonindexed geometry.
00250       PT(Geom) new_geom = geom->make_copy();
00251       new_geom->set_vertex_data(vertex_data);
00252       new_geom->make_nonindexed(false);
00253       geom = new_geom;
00254       vertex_data = new_geom->get_vertex_data();
00255     }
00256   }
00257 }
00258 
00259 ////////////////////////////////////////////////////////////////////
00260 //     Function: StandardMunger::compare_to_impl
00261 //       Access: Protected, Virtual
00262 //  Description: Called to compare two GeomMungers who are known to be
00263 //               of the same type, for an apples-to-apples comparison.
00264 //               This will never be called on two pointers of a
00265 //               different type.
00266 ////////////////////////////////////////////////////////////////////
00267 int StandardMunger::
00268 compare_to_impl(const GeomMunger *other) const {
00269   const StandardMunger *om = DCAST(StandardMunger, other);
00270 
00271   if (_render_mode != om->_render_mode) {
00272     return _render_mode < om->_render_mode ? -1 : 1;
00273   }
00274 
00275   if (_munge_color != om->_munge_color) {
00276     return (int)_munge_color - (int)om->_munge_color;
00277   }
00278   if (_munge_color_scale != om->_munge_color_scale) {
00279     return (int)_munge_color_scale - (int)om->_munge_color_scale;
00280   }
00281   if (_munge_color) {
00282     int compare = _color.compare_to(om->_color);
00283     if (compare != 0) {
00284       return compare;
00285     }
00286   }
00287   if (_munge_color_scale) {
00288     int compare = _color_scale.compare_to(om->_color_scale);
00289     if (compare != 0) {
00290       return compare;
00291     }
00292   }
00293 
00294   return StateMunger::compare_to_impl(other);
00295 }
00296 
00297 ////////////////////////////////////////////////////////////////////
00298 //     Function: StandardMunger::geom_compare_to_impl
00299 //       Access: Protected, Virtual
00300 //  Description: Compares two GeomMungers, considering only whether
00301 //               they would produce a different answer to
00302 //               munge_format(), munge_data(), or munge_geom().  (They
00303 //               still might be different in other ways, but if they
00304 //               would produce the same answer, this function consider
00305 //               them to be the same.)
00306 ////////////////////////////////////////////////////////////////////
00307 int StandardMunger::
00308 geom_compare_to_impl(const GeomMunger *other) const {
00309   const StandardMunger *om = DCAST(StandardMunger, other);
00310   if (_munge_color != om->_munge_color) {
00311     return (int)_munge_color - (int)om->_munge_color;
00312   }
00313   if (_munge_color_scale != om->_munge_color_scale) {
00314     return (int)_munge_color_scale - (int)om->_munge_color_scale;
00315   }
00316   if (_munge_color) {
00317     int compare = _color.compare_to(om->_color);
00318     if (compare != 0) {
00319       return compare;
00320     }
00321   }
00322   if (_munge_color_scale) {
00323     int compare = _color_scale.compare_to(om->_color_scale);
00324     if (compare != 0) {
00325       return compare;
00326     }
00327   }
00328 
00329   return StateMunger::geom_compare_to_impl(other);
00330 }
00331 
00332 ////////////////////////////////////////////////////////////////////
00333 //     Function: StandardMunger::munge_state_impl
00334 //       Access: Protectes, Virtual
00335 //  Description: Given an input state, returns the munged state.
00336 ////////////////////////////////////////////////////////////////////
00337 CPT(RenderState) StandardMunger::
00338 munge_state_impl(const RenderState *state) {
00339   CPT(RenderState) munged_state = state;
00340 
00341   if (_munge_color) {
00342     munged_state = munged_state->remove_attrib(ColorAttrib::get_class_slot());
00343     munged_state = munged_state->remove_attrib(ColorScaleAttrib::get_class_slot());
00344   } else if (_munge_color_scale) {
00345     munged_state = munged_state->remove_attrib(ColorScaleAttrib::get_class_slot());
00346   }
00347 
00348   return munged_state;
00349 }
 All Classes Functions Variables Enumerations