00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "cullableObject.h"
00016 #include "lightAttrib.h"
00017 #include "nodePath.h"
00018 #include "texGenAttrib.h"
00019 #include "renderState.h"
00020 #include "clockObject.h"
00021 #include "cullTraverser.h"
00022 #include "sceneSetup.h"
00023 #include "lens.h"
00024 #include "stateMunger.h"
00025 #include "pStatTimer.h"
00026 #include "geomVertexWriter.h"
00027 #include "geomVertexReader.h"
00028 #include "geomTriangles.h"
00029 #include "light.h"
00030 #include "lightMutexHolder.h"
00031 #include "geomDrawCallbackData.h"
00032
00033 CullableObject::FormatMap CullableObject::_format_map;
00034 LightMutex CullableObject::_format_lock;
00035
00036 PStatCollector CullableObject::_munge_geom_pcollector("*:Munge:Geom");
00037 PStatCollector CullableObject::_munge_sprites_pcollector("*:Munge:Sprites");
00038 PStatCollector CullableObject::_munge_sprites_verts_pcollector("*:Munge:Sprites:Verts");
00039 PStatCollector CullableObject::_munge_sprites_prims_pcollector("*:Munge:Sprites:Prims");
00040 PStatCollector CullableObject::_munge_light_vector_pcollector("*:Munge:Light Vector");
00041 PStatCollector CullableObject::_sw_sprites_pcollector("SW Sprites");
00042
00043 TypeHandle CullableObject::_type_handle;
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 bool CullableObject::
00057 munge_geom(GraphicsStateGuardianBase *gsg,
00058 GeomMunger *munger, const CullTraverser *traverser,
00059 bool force) {
00060 nassertr(munger != (GeomMunger *)NULL, false);
00061 Thread *current_thread = traverser->get_current_thread();
00062 PStatTimer timer(_munge_geom_pcollector, current_thread);
00063 if (_geom != (Geom *)NULL) {
00064 _munger = munger;
00065
00066 int geom_rendering;
00067
00068 {
00069 GeomPipelineReader geom_reader(_geom, current_thread);
00070 _munged_data = geom_reader.get_vertex_data();
00071
00072 #ifdef _DEBUG
00073 {
00074 GeomVertexDataPipelineReader data_reader(_munged_data, current_thread);
00075 data_reader.check_array_readers();
00076 nassertr(geom_reader.check_valid(&data_reader), false);
00077 }
00078 #endif // _DEBUG
00079
00080 geom_rendering = geom_reader.get_geom_rendering();
00081 geom_rendering = _state->get_geom_rendering(geom_rendering);
00082 geom_rendering = _modelview_transform->get_geom_rendering(geom_rendering);
00083
00084 if (geom_rendering & Geom::GR_point_bits) {
00085 if (geom_reader.get_primitive_type() != Geom::PT_points) {
00086 if (singular_points) {
00087
00088 _geom = _geom->make_points();
00089 }
00090 }
00091 }
00092 }
00093
00094 GraphicsStateGuardianBase *gsg = traverser->get_gsg();
00095 int gsg_bits = gsg->get_supported_geom_rendering();
00096 if (!hardware_point_sprites) {
00097
00098
00099
00100 gsg_bits &= ~(Geom::GR_point_perspective | Geom::GR_point_sprite);
00101 }
00102 if (!hardware_points) {
00103
00104
00105 gsg_bits &= ~(Geom::GR_point_bits & ~Geom::GR_point);
00106 }
00107 int unsupported_bits = geom_rendering & ~gsg_bits;
00108
00109 if ((unsupported_bits & Geom::GR_point_bits) != 0) {
00110
00111
00112
00113
00114 if (pgraph_cat.is_spam()) {
00115 pgraph_cat.spam()
00116 << "munge_points_to_quads() for geometry with bits: "
00117 << hex << geom_rendering << ", unsupported: "
00118 << (unsupported_bits & Geom::GR_point_bits) << dec << "\n";
00119 }
00120 if (!munge_points_to_quads(traverser, force)) {
00121 return false;
00122 }
00123 }
00124
00125 bool cpu_animated = false;
00126
00127 if (unsupported_bits & Geom::GR_texcoord_light_vector) {
00128
00129
00130
00131 CPT(GeomVertexData) animated_vertices =
00132 _munged_data->animate_vertices(force, current_thread);
00133 if (animated_vertices != _munged_data) {
00134 cpu_animated = true;
00135 _munged_data = animated_vertices;
00136 }
00137 if (!munge_texcoord_light_vector(traverser, force)) {
00138 return false;
00139 }
00140 }
00141
00142
00143
00144 if (!munger->munge_geom(_geom, _munged_data, force, current_thread)) {
00145 return false;
00146 }
00147
00148 StateMunger *state_munger;
00149 DCAST_INTO_R(state_munger, munger, false);
00150 _state = state_munger->munge_state(_state);
00151
00152 if (!cpu_animated) {
00153
00154
00155
00156
00157 CPT(GeomVertexData) animated_vertices =
00158 _munged_data->animate_vertices(force, current_thread);
00159 if (animated_vertices != _munged_data) {
00160 cpu_animated = true;
00161 _munged_data = animated_vertices;
00162 }
00163 }
00164
00165 #ifndef NDEBUG
00166 if (show_vertex_animation) {
00167 GeomVertexDataPipelineReader data_reader(_munged_data, current_thread);
00168 bool hardware_animated = (data_reader.get_format()->get_animation().get_animation_type() == Geom::AT_hardware);
00169 if (cpu_animated || hardware_animated) {
00170
00171 static const double flash_rate = 1.0;
00172 int cycle = (int)(ClockObject::get_global_clock()->get_frame_time() * flash_rate);
00173 if ((cycle & 1) == 0) {
00174 _state = cpu_animated ? get_flash_cpu_state() : get_flash_hardware_state();
00175 }
00176 }
00177 }
00178 #endif
00179 }
00180
00181 if (_fancy) {
00182
00183 if (_next != (CullableObject *)NULL) {
00184 if (_next->_state != (RenderState *)NULL) {
00185 _next->munge_geom(gsg, gsg->get_geom_munger(_next->_state, current_thread),
00186 traverser, force);
00187 } else {
00188 _next->munge_geom(gsg, munger, traverser, force);
00189 }
00190 }
00191 }
00192
00193 return true;
00194 }
00195
00196
00197
00198
00199
00200
00201 CullableObject::
00202 ~CullableObject() {
00203 if (_fancy) {
00204
00205 if (_next != (CullableObject *)NULL) {
00206 delete _next;
00207 }
00208 set_draw_callback(NULL);
00209 }
00210 }
00211
00212
00213
00214
00215
00216
00217 void CullableObject::
00218 output(ostream &out) const {
00219 if (_geom != (Geom *)NULL) {
00220 out << *_geom;
00221 } else {
00222 out << "(null)";
00223 }
00224 }
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235 bool CullableObject::
00236 munge_points_to_quads(const CullTraverser *traverser, bool force) {
00237 Thread *current_thread = traverser->get_current_thread();
00238
00239
00240
00241 CPT(GeomVertexData) source_data =
00242 _munged_data->animate_vertices(force, current_thread);
00243
00244 if (!force && !source_data->request_resident()) {
00245 return false;
00246 }
00247
00248 PStatTimer timer(_munge_sprites_pcollector, current_thread);
00249 _sw_sprites_pcollector.add_level(source_data->get_num_rows());
00250
00251 GraphicsStateGuardianBase *gsg = traverser->get_gsg();
00252
00253 GeomVertexReader vertex(source_data, InternalName::get_vertex(),
00254 current_thread);
00255 GeomVertexReader normal(source_data, InternalName::get_normal(),
00256 current_thread);
00257 GeomVertexReader color(source_data, InternalName::get_color(),
00258 current_thread);
00259 GeomVertexReader texcoord(source_data, InternalName::get_texcoord(),
00260 current_thread);
00261 GeomVertexReader rotate(source_data, InternalName::get_rotate(),
00262 current_thread);
00263 GeomVertexReader size(source_data, InternalName::get_size(),
00264 current_thread);
00265 GeomVertexReader aspect_ratio(source_data, InternalName::get_aspect_ratio(),
00266 current_thread);
00267
00268 bool has_normal = (normal.has_column());
00269 bool has_color = (color.has_column());
00270 bool has_texcoord = (texcoord.has_column());
00271 bool has_rotate = (rotate.has_column());
00272 bool has_size = (size.has_column());
00273 bool has_aspect_ratio = (aspect_ratio.has_column());
00274
00275 bool sprite_texcoord = false;
00276 const TexGenAttrib *tex_gen = DCAST(TexGenAttrib, _state->get_attrib(TexGenAttrib::get_class_slot()));
00277 if (tex_gen != (TexGenAttrib *)NULL) {
00278 if (tex_gen->get_mode(TextureStage::get_default()) == TexGenAttrib::M_point_sprite) {
00279 sprite_texcoord = true;
00280
00281
00282 _state = _state->set_attrib(tex_gen->remove_stage(TextureStage::get_default()));
00283 }
00284 }
00285
00286 PN_stdfloat point_size = 1.0f;
00287 bool perspective = false;
00288 const RenderModeAttrib *render_mode = DCAST(RenderModeAttrib, _state->get_attrib(RenderModeAttrib::get_class_slot()));
00289 if (render_mode != (RenderModeAttrib *)NULL) {
00290 point_size = render_mode->get_thickness();
00291 perspective = render_mode->get_perspective();
00292
00293 if (render_mode->get_mode() != RenderModeAttrib::M_filled_flat) {
00294
00295
00296 _state = _state->set_attrib(RenderModeAttrib::make(RenderModeAttrib::M_filled_flat));
00297 }
00298 }
00299
00300
00301 CPT(GeomVertexFormat) new_format;
00302
00303 {
00304 LightMutexHolder holder(_format_lock);
00305 SourceFormat sformat(source_data->get_format(), sprite_texcoord);
00306 FormatMap::iterator fmi = _format_map.find(sformat);
00307 if (fmi != _format_map.end()) {
00308 new_format = (*fmi).second;
00309
00310 } else {
00311
00312 PT(GeomVertexArrayFormat) new_array_format;
00313 if (sformat._retransform_sprites) {
00314
00315
00316 new_array_format =
00317 new GeomVertexArrayFormat(InternalName::get_vertex(), 3,
00318 Geom::NT_stdfloat,
00319 Geom::C_point);
00320 } else {
00321
00322
00323 new_array_format =
00324 new GeomVertexArrayFormat(InternalName::get_vertex(), 4,
00325 Geom::NT_stdfloat,
00326 Geom::C_clip_point);
00327 }
00328 if (has_normal) {
00329 const GeomVertexColumn *c = normal.get_column();
00330 new_array_format->add_column
00331 (InternalName::get_normal(), c->get_num_components(),
00332 c->get_numeric_type(), c->get_contents());
00333 }
00334 if (has_color) {
00335 const GeomVertexColumn *c = color.get_column();
00336 new_array_format->add_column
00337 (InternalName::get_color(), c->get_num_components(),
00338 c->get_numeric_type(), c->get_contents());
00339 }
00340 if (sprite_texcoord) {
00341 new_array_format->add_column
00342 (InternalName::get_texcoord(), 2,
00343 Geom::NT_stdfloat,
00344 Geom::C_texcoord);
00345
00346 } else if (has_texcoord) {
00347 const GeomVertexColumn *c = texcoord.get_column();
00348 new_array_format->add_column
00349 (InternalName::get_texcoord(), c->get_num_components(),
00350 c->get_numeric_type(), c->get_contents());
00351 }
00352
00353 new_format = GeomVertexFormat::register_format(new_array_format);
00354 _format_map[sformat] = new_format;
00355 }
00356 }
00357
00358 const LMatrix4 &modelview = _modelview_transform->get_mat();
00359
00360 SceneSetup *scene = traverser->get_scene();
00361 const Lens *lens = scene->get_lens();
00362 const LMatrix4 &projection = lens->get_projection_mat();
00363
00364 int viewport_width = scene->get_viewport_width();
00365 int viewport_height = scene->get_viewport_height();
00366
00367
00368
00369 LMatrix4 height_projection;
00370 if (perspective) {
00371 height_projection =
00372 LMatrix4::convert_mat(CS_yup_right, lens->get_coordinate_system()) *
00373 projection;
00374 }
00375
00376 LMatrix4 render_transform = modelview * projection;
00377 LMatrix4 inv_render_transform;
00378 inv_render_transform.invert_from(render_transform);
00379
00380
00381
00382
00383
00384 int orig_verts = source_data->get_num_rows();
00385 int new_verts = 4 * orig_verts;
00386
00387 PT(GeomVertexData) new_data = new GeomVertexData
00388 (source_data->get_name(), new_format, Geom::UH_stream);
00389 new_data->unclean_set_num_rows(new_verts);
00390
00391 GeomVertexWriter new_vertex(new_data, InternalName::get_vertex());
00392 GeomVertexWriter new_normal(new_data, InternalName::get_normal());
00393 GeomVertexWriter new_color(new_data, InternalName::get_color());
00394 GeomVertexWriter new_texcoord(new_data, InternalName::get_texcoord());
00395
00396
00397
00398
00399 PointData *points;
00400 {
00401 PStatTimer t2(_munge_sprites_verts_pcollector, current_thread);
00402 points = (PointData *)alloca(orig_verts * sizeof(PointData));
00403 int vi = 0;
00404 while (!vertex.is_at_end()) {
00405
00406 LPoint3 eye = modelview.xform_point(vertex.get_data3());
00407 points[vi]._eye = eye;
00408 points[vi]._dist = gsg->compute_distance_to(points[vi]._eye);
00409
00410
00411 LPoint4 p4 = LPoint4(eye[0], eye[1], eye[2], 1.0f) * projection;
00412
00413 if (has_size) {
00414 point_size = size.get_data1f();
00415 }
00416
00417 PN_stdfloat scale_y = point_size;
00418 if (perspective) {
00419
00420
00421
00422
00423 PN_stdfloat scale = _modelview_transform->get_scale()[1];
00424 LVector3 height(0.0f, point_size * scale, scale);
00425 height = height * height_projection;
00426 scale_y = height[1] * viewport_height;
00427
00428
00429
00430 if (!lens->is_orthographic()) {
00431 scale_y /= gsg->compute_distance_to(eye);
00432 }
00433 }
00434
00435
00436
00437 scale_y *= p4[3];
00438
00439 PN_stdfloat scale_x = scale_y;
00440 if (has_aspect_ratio) {
00441 scale_x *= aspect_ratio.get_data1f();
00442 }
00443
00444
00445 LPoint2 c0(scale_x, scale_y);
00446 LPoint2 c1(-scale_x, scale_y);
00447
00448 if (has_rotate) {
00449
00450 PN_stdfloat r = rotate.get_data1f();
00451 LMatrix3 mat = LMatrix3::rotate_mat(r);
00452 c0 = c0 * mat;
00453 c1 = c1 * mat;
00454 }
00455
00456
00457
00458 PN_stdfloat rx = 1.0f / viewport_width;
00459 PN_stdfloat ry = 1.0f / viewport_height;
00460 c0.set(c0[0] * rx, c0[1] * ry);
00461 c1.set(c1[0] * rx, c1[1] * ry);
00462
00463 if (retransform_sprites) {
00464
00465
00466 new_vertex.set_data4(inv_render_transform.xform(LPoint4(p4[0] + c0[0], p4[1] + c0[1], p4[2], p4[3])));
00467 new_vertex.set_data4(inv_render_transform.xform(LPoint4(p4[0] + c1[0], p4[1] + c1[1], p4[2], p4[3])));
00468 new_vertex.set_data4(inv_render_transform.xform(LPoint4(p4[0] - c1[0], p4[1] - c1[1], p4[2], p4[3])));
00469 new_vertex.set_data4(inv_render_transform.xform(LPoint4(p4[0] - c0[0], p4[1] - c0[1], p4[2], p4[3])));
00470
00471 if (has_normal) {
00472 const LNormal &c = normal.get_data3();
00473 new_normal.set_data3(c);
00474 new_normal.set_data3(c);
00475 new_normal.set_data3(c);
00476 new_normal.set_data3(c);
00477 }
00478
00479 } else {
00480
00481
00482 new_vertex.set_data4(p4[0] + c0[0], p4[1] + c0[1], p4[2], p4[3]);
00483 new_vertex.set_data4(p4[0] + c1[0], p4[1] + c1[1], p4[2], p4[3]);
00484 new_vertex.set_data4(p4[0] - c1[0], p4[1] - c1[1], p4[2], p4[3]);
00485 new_vertex.set_data4(p4[0] - c0[0], p4[1] - c0[1], p4[2], p4[3]);
00486
00487 if (has_normal) {
00488 LNormal c = render_transform.xform_vec(normal.get_data3());
00489 new_normal.set_data3(c);
00490 new_normal.set_data3(c);
00491 new_normal.set_data3(c);
00492 new_normal.set_data3(c);
00493 }
00494 }
00495 if (has_color) {
00496 const LColor &c = color.get_data4();
00497 new_color.set_data4(c);
00498 new_color.set_data4(c);
00499 new_color.set_data4(c);
00500 new_color.set_data4(c);
00501 }
00502 if (sprite_texcoord) {
00503 new_texcoord.set_data2(1.0f, 0.0f);
00504 new_texcoord.set_data2(0.0f, 0.0f);
00505 new_texcoord.set_data2(1.0f, 1.0f);
00506 new_texcoord.set_data2(0.0f, 1.0f);
00507 } else if (has_texcoord) {
00508 const LVecBase4 &c = texcoord.get_data4();
00509 new_texcoord.set_data4(c);
00510 new_texcoord.set_data4(c);
00511 new_texcoord.set_data4(c);
00512 new_texcoord.set_data4(c);
00513 }
00514
00515 ++vi;
00516 }
00517
00518 nassertr(vi == orig_verts, false);
00519 nassertr(new_data->get_num_rows() == new_verts, false);
00520 }
00521
00522 PT(Geom) new_geom = new Geom(new_data);
00523
00524
00525
00526 static CPT(GeomVertexArrayFormat) new_prim_format;
00527 if (new_prim_format == (GeomVertexArrayFormat *)NULL) {
00528 new_prim_format =
00529 GeomVertexArrayFormat::register_format
00530 (new GeomVertexArrayFormat(InternalName::get_index(), 1,
00531 GeomEnums::NT_uint16, GeomEnums::C_index));
00532 }
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547 {
00548 PStatTimer t3(_munge_sprites_prims_pcollector, current_thread);
00549 GeomPipelineReader geom_reader(_geom, current_thread);
00550 int num_primitives = geom_reader.get_num_primitives();
00551 for (int pi = 0; pi < num_primitives; ++pi) {
00552 const GeomPrimitive *primitive = geom_reader.get_primitive(pi);
00553 if (primitive->get_num_vertices() != 0) {
00554
00555 int num_vertices = primitive->get_num_vertices();
00556 unsigned int *vertices = (unsigned int *)alloca(num_vertices * sizeof(unsigned int));
00557 unsigned int *vertices_end = vertices + num_vertices;
00558
00559 if (primitive->is_indexed()) {
00560
00561 GeomVertexReader index(primitive->get_vertices(), 0, current_thread);
00562 for (unsigned int *vi = vertices; vi != vertices_end; ++vi) {
00563 unsigned int v = index.get_data1i();
00564 nassertr(v < (unsigned int)orig_verts, false);
00565 (*vi) = v;
00566 }
00567 } else {
00568
00569 unsigned int first_vertex = primitive->get_first_vertex();
00570 for (int i = 0; i < num_vertices; ++i) {
00571 unsigned int v = i + first_vertex;
00572 nassertr(v < (unsigned int)orig_verts, false);
00573 vertices[i] = v;
00574 }
00575 }
00576
00577
00578
00579 sort(vertices, vertices_end, SortPoints(points));
00580
00581
00582
00583
00584
00585
00586
00587 PT(GeomPrimitive) new_primitive = new GeomTriangles(Geom::UH_stream);
00588 int new_prim_verts = 6 * num_vertices;
00589
00590 PT(GeomVertexArrayData) new_index
00591 = new GeomVertexArrayData(new_prim_format, GeomEnums::UH_stream);
00592 new_index->unclean_set_num_rows(new_prim_verts);
00593
00594 GeomVertexWriter index(new_index, 0);
00595 nassertr(index.has_column(), false);
00596 for (unsigned int *vi = vertices; vi != vertices_end; ++vi) {
00597 int new_vi = (*vi) * 4;
00598 nassertr(index.get_write_row() + 6 <= new_prim_verts, false);
00599 index.set_data1i(new_vi);
00600 index.set_data1i(new_vi + 1);
00601 index.set_data1i(new_vi + 2);
00602 index.set_data1i(new_vi + 2);
00603 index.set_data1i(new_vi + 1);
00604 index.set_data1i(new_vi + 3);
00605 }
00606 new_primitive->set_vertices(new_index, new_prim_verts);
00607
00608 int min_vi = primitive->get_min_vertex();
00609 int max_vi = primitive->get_max_vertex();
00610 new_primitive->set_minmax(min_vi * 4, max_vi * 4 + 3, NULL, NULL);
00611
00612 new_geom->add_primitive(new_primitive);
00613 }
00614 }
00615 }
00616
00617 _geom = new_geom.p();
00618 _munged_data = new_data;
00619
00620 return true;
00621 }
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631 bool CullableObject::
00632 munge_texcoord_light_vector(const CullTraverser *traverser, bool force) {
00633 Thread *current_thread = traverser->get_current_thread();
00634 PStatTimer timer(_munge_light_vector_pcollector, current_thread);
00635
00636 if (_net_transform->is_singular()) {
00637
00638 return true;
00639 }
00640
00641 if (!_munged_data->has_column(InternalName::get_vertex()) ||
00642 !_munged_data->has_column(InternalName::get_normal())) {
00643
00644 return true;
00645 }
00646
00647 CPT(TexGenAttrib) tex_gen = DCAST(TexGenAttrib, _state->get_attrib(TexGenAttrib::get_class_slot()));
00648 nassertr(tex_gen != (TexGenAttrib *)NULL, false);
00649
00650 const TexGenAttrib::LightVectors &light_vectors = tex_gen->get_light_vectors();
00651 TexGenAttrib::LightVectors::const_iterator lvi;
00652 for (lvi = light_vectors.begin();
00653 lvi != light_vectors.end();
00654 ++lvi) {
00655 TextureStage *stage = (*lvi);
00656 NodePath light = tex_gen->get_light(stage);
00657 if (light.is_empty()) {
00658
00659
00660 CPT(RenderAttrib) attrib = _state->get_attrib(LightAttrib::get_class_slot());
00661 if (attrib != (RenderAttrib *)NULL) {
00662 CPT(LightAttrib) la = DCAST(LightAttrib, attrib);
00663 light = la->get_most_important_light();
00664 }
00665 }
00666 if (!light.is_empty()) {
00667 string source_name = tex_gen->get_source_name(stage);
00668 Light *light_obj = light.node()->as_light();
00669 nassertr(light_obj != (Light *)NULL, false);
00670
00671
00672
00673 PT(InternalName) tangent_name = InternalName::get_tangent_name(source_name);
00674 PT(InternalName) binormal_name = InternalName::get_binormal_name(source_name);
00675
00676 PT(InternalName) texcoord_name = stage->get_texcoord_name();
00677
00678 if (_munged_data->has_column(tangent_name) &&
00679 _munged_data->has_column(binormal_name)) {
00680
00681 if (!force && !_munged_data->request_resident()) {
00682
00683 return false;
00684 }
00685
00686
00687 PT(GeomVertexData) new_data = _munged_data->replace_column
00688 (texcoord_name, 3, Geom::NT_stdfloat, Geom::C_texcoord);
00689 _munged_data = new_data;
00690
00691
00692
00693 _state = _state->add_attrib(tex_gen->remove_stage(stage));
00694
00695
00696 CPT(TransformState) light_transform =
00697 _net_transform->invert_compose(light.get_net_transform());
00698 const LMatrix4 &light_mat = light_transform->get_mat();
00699
00700 GeomVertexWriter texcoord(new_data, texcoord_name, current_thread);
00701 GeomVertexReader vertex(new_data, InternalName::get_vertex(),
00702 current_thread);
00703 GeomVertexReader tangent(new_data, tangent_name, current_thread);
00704 GeomVertexReader binormal(new_data, binormal_name, current_thread);
00705 GeomVertexReader normal(new_data, InternalName::get_normal(),
00706 current_thread);
00707
00708 while (!vertex.is_at_end()) {
00709 LPoint3 p = vertex.get_data3();
00710 LVector3 t = tangent.get_data3();
00711 LVector3 b = binormal.get_data3();
00712 LVector3 n = normal.get_data3();
00713
00714 LVector3 lv;
00715 if (light_obj->get_vector_to_light(lv, p, light_mat)) {
00716 texcoord.add_data3(lv.dot(t), lv.dot(b), lv.dot(n));
00717 }
00718 }
00719 }
00720 }
00721 }
00722
00723 return true;
00724 }
00725
00726
00727
00728
00729
00730
00731
00732
00733 CPT(RenderState) CullableObject::
00734 get_flash_cpu_state() {
00735 static const LColor flash_cpu_color(0.8f, 0.2, 0.2, 1.0f);
00736
00737
00738
00739 static CPT(RenderState) flash_cpu_state = (const RenderState *)NULL;
00740 if (flash_cpu_state == (const RenderState *)NULL) {
00741 flash_cpu_state = RenderState::make
00742 (LightAttrib::make_all_off(),
00743 TextureAttrib::make_off(),
00744 ColorAttrib::make_flat(flash_cpu_color));
00745 }
00746
00747 return flash_cpu_state;
00748 }
00749
00750
00751
00752
00753
00754
00755
00756
00757 CPT(RenderState) CullableObject::
00758 get_flash_hardware_state() {
00759 static const LColor flash_hardware_color(0.2, 0.2, 0.8, 1.0);
00760
00761
00762
00763 static CPT(RenderState) flash_hardware_state = (const RenderState *)NULL;
00764 if (flash_hardware_state == (const RenderState *)NULL) {
00765 flash_hardware_state = RenderState::make
00766 (LightAttrib::make_all_off(),
00767 TextureAttrib::make_off(),
00768 ColorAttrib::make_flat(flash_hardware_color));
00769 }
00770
00771 return flash_hardware_state;
00772 }
00773
00774
00775
00776
00777
00778
00779 void CullableObject::
00780 draw_fancy(GraphicsStateGuardianBase *gsg, bool force,
00781 Thread *current_thread) {
00782 nassertv(_fancy);
00783 if (_draw_callback != (CallbackObject *)NULL) {
00784
00785 gsg->clear_before_callback();
00786 gsg->set_state_and_transform(_state, _internal_transform);
00787 GeomDrawCallbackData cbdata(this, gsg, force);
00788 _draw_callback->do_callback(&cbdata);
00789 if (cbdata.get_lost_state()) {
00790
00791 gsg->clear_state_and_transform();
00792 }
00793
00794
00795 } else if (_next != (CullableObject *)NULL) {
00796
00797 draw_with_decals(gsg, force, current_thread);
00798
00799 } else {
00800
00801
00802 gsg->set_state_and_transform(_state, _internal_transform);
00803 draw_inline(gsg, force, current_thread);
00804 nassertv(false);
00805 }
00806 }
00807
00808
00809
00810
00811
00812
00813
00814 void CullableObject::
00815 draw_with_decals(GraphicsStateGuardianBase *gsg, bool force,
00816 Thread *current_thread) {
00817 nassertv(_fancy && _next != (CullableObject *)NULL);
00818
00819
00820
00821 CPT(RenderState) state = gsg->begin_decal_base_first();
00822
00823 CullableObject *base = this;
00824 while (base != (CullableObject *)NULL && base->_geom != (Geom *)NULL) {
00825 gsg->set_state_and_transform(base->_state->compose(state), base->_internal_transform);
00826 base->draw_inline(gsg, force, current_thread);
00827
00828 base = base->_next;
00829 }
00830
00831 if (base != (CullableObject *)NULL) {
00832
00833 state = gsg->begin_decal_nested();
00834
00835 CullableObject *decal = base->_next;
00836 while (decal != (CullableObject *)NULL) {
00837 gsg->set_state_and_transform(decal->_state->compose(state), decal->_internal_transform);
00838 decal->draw_inline(gsg, force, current_thread);
00839 decal = decal->_next;
00840 }
00841 }
00842
00843
00844 state = gsg->begin_decal_base_second();
00845 if (state != (const RenderState *)NULL) {
00846 base = this;
00847 while (base != (CullableObject *)NULL && base->_geom != (Geom *)NULL) {
00848 gsg->set_state_and_transform(base->_state->compose(state), base->_internal_transform);
00849 base->draw_inline(gsg, force, current_thread);
00850
00851 base = base->_next;
00852 }
00853 }
00854 }
00855
00856
00857
00858
00859
00860
00861 CullableObject::SourceFormat::
00862 SourceFormat(const GeomVertexFormat *format, bool sprite_texcoord) :
00863 _format(format),
00864 _sprite_texcoord(sprite_texcoord)
00865 {
00866 _retransform_sprites = retransform_sprites;
00867 }