00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 #include "cullResult.h"
00020 #include "cullBinManager.h"
00021 #include "alphaTestAttrib.h"
00022 #include "transparencyAttrib.h"
00023 #include "renderState.h"
00024 #include "clockObject.h"
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 static const float dual_opaque_level = 252.0f / 256.0f;
00049 
00050 
00051 
00052 
00053 
00054 
00055 
00056 
00057 
00058 PT(CullResult) CullResult::
00059 make_next() const {
00060   PT(CullResult) new_result = new CullResult(_gsg);
00061   new_result->_bins.reserve(_bins.size());
00062 
00063   for (Bins::const_iterator bi = _bins.begin(); bi != _bins.end(); ++bi) {
00064     CullBin *old_bin = (*bi);
00065     if (old_bin == (CullBin *)NULL) {
00066       new_result->_bins.push_back((CullBin *)NULL);
00067     } else {
00068       new_result->_bins.push_back(old_bin->make_next());
00069     }
00070   }
00071 
00072   return new_result;
00073 }
00074 
00075 
00076 
00077 
00078 
00079 
00080 
00081 
00082 void CullResult::
00083 add_object(CullableObject *object) {
00084   
00085   const RenderState *state = object->_state;
00086   nassertv(state != (const RenderState *)NULL);
00087 
00088   const TransparencyAttrib *trans = state->get_transparency();
00089   if (trans != (const TransparencyAttrib *)NULL) {
00090     switch (trans->get_mode()) {
00091     case TransparencyAttrib::M_binary:
00092       
00093       object->_state = state->compose(get_binary_state());
00094       break;
00095 
00096     case TransparencyAttrib::M_dual:
00097       if (m_dual) {
00098         
00099         
00100         
00101         
00102         
00103         
00104         const CullBinAttrib *bin_attrib = state->get_bin();
00105         if (bin_attrib == (CullBinAttrib *)NULL || 
00106             bin_attrib->get_bin_name().empty()) {
00107           
00108           
00109 #ifndef NDEBUG
00110           if (m_dual_transparent) 
00111 #endif
00112           {
00113             CullableObject *transparent_part = new CullableObject(*object);
00114             CPT(RenderState) transparent_state = object->has_decals() ? 
00115               get_dual_transparent_state_decals() : 
00116               get_dual_transparent_state();
00117             transparent_part->_state = state->compose(transparent_state);
00118             CullBin *bin = get_bin(transparent_part->_state->get_bin_index());
00119             nassertv(bin != (CullBin *)NULL);
00120             bin->add_object(transparent_part);
00121           }
00122 
00123           
00124           
00125           object->_state = state->compose(get_dual_opaque_state());
00126 #ifndef NDEBUG
00127           if (!m_dual_opaque) {
00128             delete object;
00129             return;
00130           }
00131 #endif
00132         }
00133       }
00134       break;
00135 
00136     default:
00137       
00138       break;
00139     }
00140   }
00141   
00142   CullBin *bin = get_bin(object->_state->get_bin_index());
00143   nassertv(bin != (CullBin *)NULL);
00144   bin->add_object(object);
00145 }
00146 
00147 
00148 
00149 
00150 
00151 
00152 
00153 
00154 
00155 
00156 void CullResult::
00157 finish_cull() {
00158   for (Bins::iterator bi = _bins.begin(); bi != _bins.end(); ++bi) {
00159     CullBin *bin = (*bi);
00160     if (bin != (CullBin *)NULL) {
00161       bin->finish_cull();
00162     }
00163   }
00164 }
00165 
00166 
00167 
00168 
00169 
00170 
00171 
00172 void CullResult::
00173 draw() {
00174   
00175   CullBinManager *bin_manager = CullBinManager::get_global_ptr();
00176   int num_bins = bin_manager->get_num_bins();
00177   for (int i = 0; i < num_bins; i++) {
00178     int bin_index = bin_manager->get_bin(i);
00179     nassertv(bin_index >= 0);
00180 
00181     if (bin_index < (int)_bins.size() && _bins[bin_index] != (CullBin *)NULL) {
00182       _bins[bin_index]->draw();
00183     }
00184   }
00185 }
00186 
00187 
00188 
00189 
00190 
00191 
00192 
00193 
00194 
00195 void CullResult::
00196 bin_removed(int bin_index) {
00197   
00198   nassertv(false);
00199 }
00200 
00201 
00202 
00203 
00204 
00205 
00206 
00207 CullBin *CullResult::
00208 make_new_bin(int bin_index) {
00209   CullBinManager *bin_manager = CullBinManager::get_global_ptr();
00210   PT(CullBin) bin = bin_manager->make_new_bin(bin_index, _gsg);
00211   if (bin != (CullBin *)NULL) {
00212     
00213     while (bin_index >= (int)_bins.size()) {
00214       _bins.push_back((CullBin *)NULL);
00215     }
00216     nassertr(bin_index >= 0 && bin_index < (int)_bins.size(), NULL);
00217     _bins[bin_index] = bin;
00218   }
00219 
00220   return bin;
00221 }
00222 
00223 
00224 
00225 
00226 
00227 
00228 
00229 CPT(RenderState) CullResult::
00230 get_binary_state() {
00231   static CPT(RenderState) state = NULL;
00232   if (state == (const RenderState *)NULL) {
00233     state = RenderState::make(AlphaTestAttrib::make(AlphaTestAttrib::M_greater_equal, 0.5f),
00234                               TransparencyAttrib::make(TransparencyAttrib::M_none),
00235                               RenderState::get_max_priority());
00236   }
00237   return state;
00238 }
00239 
00240 #ifndef NDEBUG
00241 static const double m_dual_flash_rate = 1.0;  
00242 #endif
00243 
00244 
00245 
00246 
00247 
00248 
00249 
00250 
00251 
00252 CPT(RenderState) CullResult::
00253 get_dual_transparent_state() {
00254   static CPT(RenderState) state = NULL;
00255   if (state == (const RenderState *)NULL) {
00256     
00257     
00258     
00259     
00260     
00261     
00262     
00263     
00264     state = RenderState::make(AlphaTestAttrib::make(AlphaTestAttrib::M_greater, 0.0f),
00265                               TransparencyAttrib::make(TransparencyAttrib::M_alpha),
00266                               RenderState::get_max_priority());
00267   }
00268 
00269 #ifndef NDEBUG
00270   if (m_dual_flash) {
00271     int cycle = (int)(ClockObject::get_global_clock()->get_real_time() * m_dual_flash_rate);
00272     if ((cycle & 1) == 0) {
00273       static CPT(RenderState) flash_state = NULL;
00274       if (flash_state == (const RenderState *)NULL) {
00275         flash_state = state->add_attrib(ColorScaleAttrib::make(LVecBase4f(0.8f, 0.2f, 0.2f, 1.0f)));
00276         flash_state = flash_state->add_attrib(AlphaTestAttrib::make(AlphaTestAttrib::M_less, 1.0f));
00277       }
00278       return flash_state;
00279     }
00280   }
00281 #endif  // NDEBUG
00282 
00283   return state;
00284 }
00285 
00286 
00287 
00288 
00289 
00290 
00291 
00292 
00293 CPT(RenderState) CullResult::
00294 get_dual_transparent_state_decals() {
00295   static CPT(RenderState) state = NULL;
00296   if (state == (const RenderState *)NULL) {
00297     
00298     
00299     
00300     
00301     state = RenderState::make(AlphaTestAttrib::make(AlphaTestAttrib::M_less, dual_opaque_level),
00302                               TransparencyAttrib::make(TransparencyAttrib::M_alpha),
00303                               RenderState::get_max_priority());
00304   }
00305 
00306 #ifndef NDEBUG
00307   if (m_dual_flash) {
00308     int cycle = (int)(ClockObject::get_global_clock()->get_real_time() * m_dual_flash_rate);
00309     if ((cycle & 1) == 0) {
00310       static CPT(RenderState) flash_state = NULL;
00311       if (flash_state == (const RenderState *)NULL) {
00312         flash_state = state->add_attrib(ColorScaleAttrib::make(LVecBase4f(0.8f, 0.2f, 0.2f, 1.0f)));
00313       }
00314       return flash_state;
00315     }
00316   }
00317 #endif  // NDEBUG
00318 
00319   return state;
00320 }
00321 
00322 
00323 
00324 
00325 
00326 
00327 
00328 CPT(RenderState) CullResult::
00329 get_dual_opaque_state() {
00330   static CPT(RenderState) state = NULL;
00331   if (state == (const RenderState *)NULL) {
00332     state = RenderState::make(AlphaTestAttrib::make(AlphaTestAttrib::M_greater_equal, dual_opaque_level),
00333                               TransparencyAttrib::make(TransparencyAttrib::M_none),
00334                               RenderState::get_max_priority());
00335   }
00336 
00337 #ifndef NDEBUG
00338   if (m_dual_flash) {
00339     int cycle = (int)(ClockObject::get_global_clock()->get_real_time() * m_dual_flash_rate);
00340     if ((cycle & 1) == 0) {
00341       static CPT(RenderState) flash_state = NULL;
00342       if (flash_state == (const RenderState *)NULL) {
00343         flash_state = state->add_attrib(ColorScaleAttrib::make(LVecBase4f(0.2f, 0.2f, 0.8f, 1.0f)));
00344       }
00345       return flash_state;
00346     }
00347   }
00348 #endif  // NDEBUG
00349 
00350   return state;
00351 }