00001 // Filename: cullFaceAttrib.cxx 00002 // Created by: drose (27Feb02) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved 00008 // 00009 // All use of this software is subject to the terms of the Panda 3d 00010 // Software license. You should have received a copy of this license 00011 // along with this source code; you will also find a current copy of 00012 // the license at http://www.panda3d.org/license.txt . 00013 // 00014 // To contact the maintainers of this program write to 00015 // panda3d@yahoogroups.com . 00016 // 00017 //////////////////////////////////////////////////////////////////// 00018 00019 #include "cullFaceAttrib.h" 00020 #include "graphicsStateGuardianBase.h" 00021 #include "dcast.h" 00022 #include "bamReader.h" 00023 #include "bamWriter.h" 00024 #include "datagram.h" 00025 #include "datagramIterator.h" 00026 00027 TypeHandle CullFaceAttrib::_type_handle; 00028 00029 //////////////////////////////////////////////////////////////////// 00030 // Function: CullFaceAttrib::make 00031 // Access: Published, Static 00032 // Description: Constructs a new CullFaceAttrib object that specifies 00033 // how to cull geometry. By Panda convention, vertices 00034 // are ordered counterclockwise when seen from the 00035 // front, so the M_cull_clockwise will cull backfacing 00036 // polygons. 00037 // 00038 // M_cull_unchanged is an identity attrib; if this is 00039 // applied to vertices without any other intervening 00040 // attrib, it is the same as applying the default 00041 // attrib. 00042 //////////////////////////////////////////////////////////////////// 00043 CPT(RenderAttrib) CullFaceAttrib:: 00044 make(CullFaceAttrib::Mode mode) { 00045 CullFaceAttrib *attrib = new CullFaceAttrib(mode, false); 00046 return return_new(attrib); 00047 } 00048 00049 //////////////////////////////////////////////////////////////////// 00050 // Function: CullFaceAttrib::make_reverse 00051 // Access: Published, Static 00052 // Description: Constructs a new CullFaceAttrib object that reverses 00053 // the effects of any other CullFaceAttrib objects in 00054 // the scene graph. M_cull_clockwise will be treated as 00055 // M_cull_counter_clockwise, and vice-versa. 00056 // M_cull_none is unchanged. 00057 00058 00059 //////////////////////////////////////////////////////////////////// 00060 CPT(RenderAttrib) CullFaceAttrib:: 00061 make_reverse() { 00062 CullFaceAttrib *attrib = new CullFaceAttrib(M_cull_unchanged, true); 00063 return return_new(attrib); 00064 } 00065 00066 //////////////////////////////////////////////////////////////////// 00067 // Function: CullFaceAttrib::get_effective_mode 00068 // Access: Published 00069 // Description: Returns the effective culling mode. This is the same 00070 // as the actual culling mode, unless the reverse flag 00071 // is set, which swaps CW for CCW and vice-versa. Also, 00072 // M_cull_unchanged is mapped to M_cull_none. 00073 //////////////////////////////////////////////////////////////////// 00074 CullFaceAttrib::Mode CullFaceAttrib:: 00075 get_effective_mode() const { 00076 if (_reverse) { 00077 switch (_mode) { 00078 case M_cull_clockwise: 00079 case M_cull_unchanged: 00080 return M_cull_counter_clockwise; 00081 00082 case M_cull_counter_clockwise: 00083 return M_cull_clockwise; 00084 00085 default: 00086 break; 00087 } 00088 00089 } else { 00090 switch (_mode) { 00091 case M_cull_clockwise: 00092 case M_cull_unchanged: 00093 return M_cull_clockwise; 00094 00095 case M_cull_counter_clockwise: 00096 return M_cull_counter_clockwise; 00097 00098 default: 00099 break; 00100 } 00101 } 00102 00103 return M_cull_none; 00104 } 00105 00106 //////////////////////////////////////////////////////////////////// 00107 // Function: CullFaceAttrib::issue 00108 // Access: Public, Virtual 00109 // Description: Calls the appropriate method on the indicated GSG 00110 // to issue the graphics commands appropriate to the 00111 // given attribute. This is normally called 00112 // (indirectly) only from 00113 // GraphicsStateGuardian::set_state() or modify_state(). 00114 //////////////////////////////////////////////////////////////////// 00115 void CullFaceAttrib:: 00116 issue(GraphicsStateGuardianBase *gsg) const { 00117 gsg->issue_cull_face(this); 00118 } 00119 00120 //////////////////////////////////////////////////////////////////// 00121 // Function: CullFaceAttrib::output 00122 // Access: Public, Virtual 00123 // Description: 00124 //////////////////////////////////////////////////////////////////// 00125 void CullFaceAttrib:: 00126 output(ostream &out) const { 00127 out << get_type() << ":"; 00128 switch (get_actual_mode()) { 00129 case M_cull_none: 00130 out << "cull_none"; 00131 break; 00132 case M_cull_clockwise: 00133 out << "cull_clockwise"; 00134 break; 00135 case M_cull_counter_clockwise: 00136 out << "cull_counter_clockwise"; 00137 break; 00138 case M_cull_unchanged: 00139 out << "cull_unchanged"; 00140 break; 00141 } 00142 if (get_reverse()) { 00143 out << "(reverse)"; 00144 } 00145 } 00146 00147 //////////////////////////////////////////////////////////////////// 00148 // Function: CullFaceAttrib::compare_to_impl 00149 // Access: Protected, Virtual 00150 // Description: Intended to be overridden by derived CullFaceAttrib 00151 // types to return a unique number indicating whether 00152 // this CullFaceAttrib is equivalent to the other one. 00153 // 00154 // This should return 0 if the two CullFaceAttrib objects 00155 // are equivalent, a number less than zero if this one 00156 // should be sorted before the other one, and a number 00157 // greater than zero otherwise. 00158 // 00159 // This will only be called with two CullFaceAttrib 00160 // objects whose get_type() functions return the same. 00161 //////////////////////////////////////////////////////////////////// 00162 int CullFaceAttrib:: 00163 compare_to_impl(const RenderAttrib *other) const { 00164 const CullFaceAttrib *ta; 00165 DCAST_INTO_R(ta, other, 0); 00166 if (_mode != ta->_mode) { 00167 return (int)_mode - (int)ta->_mode; 00168 } 00169 return (int)_reverse - (int)ta->_reverse; 00170 } 00171 00172 //////////////////////////////////////////////////////////////////// 00173 // Function: CullFaceAttrib::compose_impl 00174 // Access: Protected, Virtual 00175 // Description: Intended to be overridden by derived RenderAttrib 00176 // types to specify how two consecutive RenderAttrib 00177 // objects of the same type interact. 00178 // 00179 // This should return the result of applying the other 00180 // RenderAttrib to a node in the scene graph below this 00181 // RenderAttrib, which was already applied. In most 00182 // cases, the result is the same as the other 00183 // RenderAttrib (that is, a subsequent RenderAttrib 00184 // completely replaces the preceding one). On the other 00185 // hand, some kinds of RenderAttrib (for instance, 00186 // ColorTransformAttrib) might combine in meaningful 00187 // ways. 00188 //////////////////////////////////////////////////////////////////// 00189 CPT(RenderAttrib) CullFaceAttrib:: 00190 compose_impl(const RenderAttrib *other) const { 00191 const CullFaceAttrib *ta; 00192 DCAST_INTO_R(ta, other, 0); 00193 00194 if (!_reverse && ta->_mode != M_cull_unchanged) { 00195 // The normal case (there is nothing funny going on): the second 00196 // attrib completely replaces this attrib. 00197 return other; 00198 } 00199 00200 // In the more complex case, the two attribs affect each other in 00201 // some way, and we must generate a new attrib from the result. 00202 Mode mode = _mode; 00203 if (ta->_mode != M_cull_unchanged) { 00204 mode = ta->_mode; 00205 } 00206 bool reverse = (_reverse && !ta->_reverse) || (!_reverse && ta->_reverse); 00207 00208 CullFaceAttrib *attrib = new CullFaceAttrib(mode, reverse); 00209 return return_new(attrib); 00210 } 00211 00212 //////////////////////////////////////////////////////////////////// 00213 // Function: CullFaceAttrib::invert_compose_impl 00214 // Access: Protected, Virtual 00215 // Description: Intended to be overridden by derived RenderAttrib 00216 // types to specify how two consecutive RenderAttrib 00217 // objects of the same type interact. 00218 // 00219 // See invert_compose() and compose_impl(). 00220 //////////////////////////////////////////////////////////////////// 00221 CPT(RenderAttrib) CullFaceAttrib:: 00222 invert_compose_impl(const RenderAttrib *other) const { 00223 const CullFaceAttrib *ta; 00224 DCAST_INTO_R(ta, other, 0); 00225 00226 // The invert case is the same as the normal case, except that the 00227 // meaning of _reverse is inverted. See compose_impl(), above. 00228 00229 if (_reverse && ta->_mode != M_cull_unchanged) { 00230 return other; 00231 } 00232 00233 Mode mode = _mode; 00234 if (ta->_mode != M_cull_unchanged) { 00235 mode = ta->_mode; 00236 } 00237 bool reverse = (!_reverse && !ta->_reverse) || (_reverse && ta->_reverse); 00238 00239 CullFaceAttrib *attrib = new CullFaceAttrib(mode, reverse); 00240 return return_new(attrib); 00241 } 00242 00243 //////////////////////////////////////////////////////////////////// 00244 // Function: CullFaceAttrib::make_default_impl 00245 // Access: Protected, Virtual 00246 // Description: Intended to be overridden by derived CullFaceAttrib 00247 // types to specify what the default property for a 00248 // CullFaceAttrib of this type should be. 00249 // 00250 // This should return a newly-allocated CullFaceAttrib of 00251 // the same type that corresponds to whatever the 00252 // standard default for this kind of CullFaceAttrib is. 00253 //////////////////////////////////////////////////////////////////// 00254 RenderAttrib *CullFaceAttrib:: 00255 make_default_impl() const { 00256 return new CullFaceAttrib(M_cull_clockwise, false); 00257 } 00258 00259 //////////////////////////////////////////////////////////////////// 00260 // Function: CullFaceAttrib::register_with_read_factory 00261 // Access: Public, Static 00262 // Description: Tells the BamReader how to create objects of type 00263 // CullFaceAttrib. 00264 //////////////////////////////////////////////////////////////////// 00265 void CullFaceAttrib:: 00266 register_with_read_factory() { 00267 BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); 00268 } 00269 00270 //////////////////////////////////////////////////////////////////// 00271 // Function: CullFaceAttrib::write_datagram 00272 // Access: Public, Virtual 00273 // Description: Writes the contents of this object to the datagram 00274 // for shipping out to a Bam file. 00275 //////////////////////////////////////////////////////////////////// 00276 void CullFaceAttrib:: 00277 write_datagram(BamWriter *manager, Datagram &dg) { 00278 RenderAttrib::write_datagram(manager, dg); 00279 00280 dg.add_int8(_mode); 00281 dg.add_bool(_reverse); 00282 } 00283 00284 //////////////////////////////////////////////////////////////////// 00285 // Function: CullFaceAttrib::make_from_bam 00286 // Access: Protected, Static 00287 // Description: This function is called by the BamReader's factory 00288 // when a new object of type CullFaceAttrib is encountered 00289 // in the Bam file. It should create the CullFaceAttrib 00290 // and extract its information from the file. 00291 //////////////////////////////////////////////////////////////////// 00292 TypedWritable *CullFaceAttrib:: 00293 make_from_bam(const FactoryParams ¶ms) { 00294 CullFaceAttrib *attrib = new CullFaceAttrib(M_cull_none, false); 00295 DatagramIterator scan; 00296 BamReader *manager; 00297 00298 parse_params(params, scan, manager); 00299 attrib->fillin(scan, manager); 00300 00301 return attrib; 00302 } 00303 00304 //////////////////////////////////////////////////////////////////// 00305 // Function: CullFaceAttrib::fillin 00306 // Access: Protected 00307 // Description: This internal function is called by make_from_bam to 00308 // read in all of the relevant data from the BamFile for 00309 // the new CullFaceAttrib. 00310 //////////////////////////////////////////////////////////////////// 00311 void CullFaceAttrib:: 00312 fillin(DatagramIterator &scan, BamReader *manager) { 00313 RenderAttrib::fillin(scan, manager); 00314 00315 _mode = (Mode)scan.get_int8(); 00316 if (manager->get_file_minor_ver() >= 1) { 00317 _reverse = scan.get_bool(); 00318 } 00319 }