Panda3D
|
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 }