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 }