111 LODInstance(
EggNode *egg_node);
112 bool operator < (
const LODInstance &other)
const {
113 return _d->_switch_in < other._d->_switch_in;
121LODInstance(
EggNode *egg_node) {
122 nassertv(egg_node !=
nullptr);
123 _egg_node = egg_node;
128 nassertv(egg_group->has_lod());
145 _dynamic_override =
false;
146 _dynamic_override_char_maker =
nullptr;
153EggLoader(
const EggData *data) :
157 _dynamic_override =
false;
158 _dynamic_override_char_maker =
nullptr;
167 _deferred_nodes.clear();
171 if (!expand_all_object_types(_data)) {
179 _data->clear_connected_shading();
180 _data->remove_unused_vertices(
true);
181 _data->get_connected_shading();
182 _data->unify_attributes(
true, egg_flat_shading,
true);
187 _data->clear_connected_shading();
188 _data->remove_unused_vertices(
true);
189 _data->get_connected_shading();
194 separate_switches(_data);
196 if (egg_emulate_bface) {
197 emulate_bface(_data);
201 _data->remove_invalid_primitives(
true);
203 binner.make_bins(_data);
208 _root =
new ModelRoot(_data->get_egg_filename(), _data->get_egg_timestamp());
210 EggGroupNode::const_iterator ci;
211 for (ci = _data->begin(); ci != _data->end(); ++ci) {
212 make_node(*ci, _root);
228 ExtraNodes::const_iterator di;
229 for (di = _decals.begin(); di != _decals.end(); ++di) {
231 nassertv(node !=
nullptr);
239 for (
int i = 0; i < num_children; i++) {
246 <<
"Decal onto " << parent.
node()->get_name()
247 <<
" uses base geometry with multiple GeomNodes.\n";
257 <<
"Ignoring decal onto " << parent.
node()->get_name()
258 <<
"; no geometry within group.\n";
264 while (i < num_children) {
288 ExtraNodes::const_iterator ni;
289 for (ni = _sequences.begin(); ni != _sequences.end(); ++ni) {
304 if (egg_bin->empty()) {
311 EggGroupNode::const_iterator ci = egg_bin->begin();
312 nassertv(ci != egg_bin->end());
314 nassertv(first_prim !=
nullptr);
316 DCAST_INTO_V(render_state, first_prim->get_user_data(EggRenderState::get_class_type()));
318 if (render_state->_hidden && egg_suppress_hidden) {
332 egg_bin->
mesh_triangles(render_state->_flat_shaded ? EggGroupNode::T_flat_shaded : 0);
352 EggVertexPools::iterator vpi;
353 for (vpi = vertex_pools.begin(); vpi != vertex_pools.end(); ++vpi) {
358 bool has_overall_color;
359 LColor overall_color;
361 if (!egg_flat_colors) {
365 has_overall_color =
false;
372 blend_table = make_blend_table(vertex_pool, egg_bin, character_maker);
386 for (ci = egg_bin->begin(); ci != egg_bin->end(); ++ci) {
388 DCAST_INTO_V(egg_prim, (*ci));
389 if (egg_prim->
get_pool() == vertex_pool) {
390 make_primitive(render_state, egg_prim, unique_primitives, primitives,
391 has_overall_color, overall_color);
395 if (!primitives.empty()) {
397 if (transform !=
nullptr) {
405 make_vertex_data(render_state, vertex_pool, egg_bin, mat, blend_table,
406 is_dynamic, character_maker, has_overall_color);
407 nassertv(vertex_data !=
nullptr);
410 PT(
Geom) geom =
new Geom(vertex_data);
413 Primitives::const_iterator pi;
414 for (pi = primitives.begin(); pi != primitives.end(); ++pi) {
417 if (primitive->is_indexed()) {
420 primitive->reserve_num_vertices(primitive->get_num_vertices());
423 geom->add_primitive(primitive);
430 if (geom_node ==
nullptr) {
435 geom_node = DCAST(
GeomNode, parent);
438 geom_node =
new GeomNode(egg_bin->get_name());
439 if (render_state->_hidden) {
442 parent->add_child(geom_node);
447 CPT(
RenderState) geom_state = render_state->_state;
448 if (has_overall_color) {
449 if (!overall_color.almost_equal(LColor(1.0f, 1.0f, 1.0f, 1.0f))) {
450 geom_state = geom_state->
add_attrib(ColorAttrib::make_flat(overall_color), -1);
453 geom_state = geom_state->add_attrib(ColorAttrib::make_vertex(), -1);
456 geom_node->add_geom(geom, geom_state);
460 if (geom_node !=
nullptr && egg_show_normals) {
462 for (vpi = vertex_pools.begin(); vpi != vertex_pools.end(); ++vpi) {
464 show_normals(vertex_pool, geom_node);
480 for (
int i = 0; i < num_components; i++) {
482 case EggTransform::CT_translate2d:
485 LVecBase3 trans3d(trans2d[0], trans2d[1], 0.0f);
486 ts = TransformState::make_pos(trans3d)->compose(ts);
490 case EggTransform::CT_translate3d:
493 ts = TransformState::make_pos(trans3d)->compose(ts);
497 case EggTransform::CT_rotate2d:
499 LRotation rot(LVector3(0.0f, 0.0f, 1.0f),
501 ts = TransformState::make_quat(rot)->compose(ts);
505 case EggTransform::CT_rotx:
507 LRotation rot(LVector3(1.0f, 0.0f, 0.0f),
509 ts = TransformState::make_quat(rot)->compose(ts);
513 case EggTransform::CT_roty:
515 LRotation rot(LVector3(0.0f, 1.0f, 0.0f),
517 ts = TransformState::make_quat(rot)->compose(ts);
521 case EggTransform::CT_rotz:
523 LRotation rot(LVector3(0.0f, 0.0f, 1.0f),
525 ts = TransformState::make_quat(rot)->compose(ts);
529 case EggTransform::CT_rotate3d:
533 ts = TransformState::make_quat(rot)->compose(ts);
537 case EggTransform::CT_scale2d:
540 LVecBase3 scale3d(scale2d[0], scale2d[1], 1.0f);
541 ts = TransformState::make_scale(scale3d)->compose(ts);
545 case EggTransform::CT_scale3d:
548 ts = TransformState::make_scale(scale3d)->compose(ts);
552 case EggTransform::CT_uniform_scale:
555 ts = TransformState::make_scale(scale)->compose(ts);
559 case EggTransform::CT_matrix3:
562 LMatrix4 mat4(m(0, 0), m(0, 1), 0.0, m(0, 2),
563 m(1, 0), m(1, 1), 0.0, m(1, 2),
565 m(2, 0), m(2, 1), 0.0, m(2, 2));
567 ts = TransformState::make_mat(mat4)->compose(ts);
571 case EggTransform::CT_matrix4:
574 ts = TransformState::make_mat(mat4)->compose(ts);
578 case EggTransform::CT_invalid:
584 if (ts->components_given()) {
593 TransformStates::iterator tsi = _transform_states.insert(TransformStates::value_type(ts->get_mat(), ts)).first;
595 return (*tsi).second;
607 new GeomVertexData(vertex_pool->get_name(), format, Geom::UH_static);
613 for (vi = vertex_pool->
begin(); vi != vertex_pool->
end(); ++vi) {
617 if (vert->has_normal()) {
618 vertex.add_data3d(pos);
619 vertex.add_data3d(pos + vert->get_normal() * egg_normal_scale);
620 color.add_data4(1.0f, 0.0f, 0.0f, 1.0f);
621 color.add_data4(1.0f, 0.0f, 0.0f, 1.0f);
622 primitive->add_next_vertices(2);
623 primitive->close_primitive();
630 if (uv_obj->has_tangent()) {
631 vertex.add_data3d(pos);
632 vertex.add_data3d(pos + uv_obj->get_tangent() * egg_normal_scale);
633 color.add_data4(0.0f, 1.0f, 0.0f, 1.0f);
634 color.add_data4(0.0f, 1.0f, 0.0f, 1.0f);
635 primitive->add_next_vertices(2);
636 primitive->close_primitive();
638 if (uv_obj->has_binormal()) {
639 vertex.add_data3d(pos);
640 vertex.add_data3d(pos + uv_obj->get_binormal() * egg_normal_scale);
641 color.add_data4(0.0f, 0.0f, 1.0f, 1.0f);
642 color.add_data4(0.0f, 0.0f, 1.0f, 1.0f);
643 primitive->add_next_vertices(2);
644 primitive->close_primitive();
649 PT(
Geom) geom =
new Geom(vertex_data);
650 geom->add_primitive(primitive);
659 const LMatrix4d &mat) {
660 if (egg_load_old_curves) {
662 make_old_nurbs_curve(egg_curve, parent, mat);
666 assert(parent !=
nullptr);
670 if (nurbs ==
nullptr) {
695 rope->set_curve(nurbs);
699 int subdiv_per_segment =
700 (int)((egg_curve->
get_subdiv() + 0.5) / nurbs->get_num_segments());
701 rope->set_num_subdiv(max(subdiv_per_segment, 1));
705 DCAST_INTO_V(render_state, egg_curve->
get_user_data(EggRenderState::get_class_type()));
706 if (render_state->_hidden && egg_suppress_hidden) {
711 rope->set_state(render_state->_state);
712 rope->set_uv_mode(RopeNode::UV_parametric);
716 rope->set_use_vertex_color(
true);
717 }
else if (egg_curve->has_color()) {
719 rope->set_attrib(ColorAttrib::make_flat(egg_curve->
get_color()));
722 parent->add_child(rope);
734 const LMatrix4d &mat) {
735 assert(parent !=
nullptr);
742 nassertv(nurbs !=
nullptr);
746 <<
"Invalid NURBSCurve order for " << egg_curve->get_name() <<
": "
752 nurbs->set_order(egg_curve->
get_order());
754 EggPrimitive::const_iterator pi;
755 for (pi = egg_curve->begin(); pi != egg_curve->end(); ++pi) {
756 nurbs->append_cv(LCAST(PN_stdfloat, (*pi)->get_pos4() * mat));
760 if (num_knots != nurbs->get_num_knots()) {
762 <<
"Invalid NURBSCurve number of knots for "
763 << egg_curve->get_name() <<
": got " << num_knots
764 <<
" knots, expected " << nurbs->get_num_knots() <<
"\n";
769 for (
int i = 0; i < num_knots; i++) {
770 nurbs->set_knot(i, egg_curve->
get_knot(i));
774 case EggCurve::CT_xyz:
775 curve->set_curve_type(PCT_XYZ);
778 case EggCurve::CT_hpr:
779 curve->set_curve_type(PCT_HPR);
783 curve->set_curve_type(PCT_T);
789 curve->set_name(egg_curve->get_name());
791 if (!curve->recompute()) {
793 <<
"Invalid NURBSCurve " << egg_curve->get_name() <<
"\n";
798 parent->add_child(curve);
806 const LMatrix4d &mat) {
807 assert(parent !=
nullptr);
811 if (nurbs ==
nullptr) {
817 sheet->set_surface(nurbs);
821 int u_subdiv_per_segment =
822 (int)((egg_surface->
get_u_subdiv() + 0.5) / nurbs->get_num_u_segments());
823 sheet->set_num_u_subdiv(max(u_subdiv_per_segment, 1));
826 int v_subdiv_per_segment =
827 (int)((egg_surface->
get_v_subdiv() + 0.5) / nurbs->get_num_v_segments());
828 sheet->set_num_v_subdiv(max(v_subdiv_per_segment, 1));
832 DCAST_INTO_V(render_state, egg_surface->
get_user_data(EggRenderState::get_class_type()));
833 if (render_state->_hidden && egg_suppress_hidden) {
838 sheet->set_state(render_state->_state);
842 sheet->set_use_vertex_color(
true);
843 }
else if (egg_surface->has_color()) {
845 sheet->set_attrib(ColorAttrib::make_flat(egg_surface->
get_color()));
848 parent->add_child(sheet);
860 EggTextureCollection::iterator ti;
861 for (ti = tc.begin(); ti != tc.end(); ++ti) {
862 PT_EggTexture egg_tex = (*ti);
865 if (load_texture(def, egg_tex)) {
868 _textures[egg_tex] = def;
878load_texture(TextureDef &def,
EggTexture *egg_tex) {
880 int wanted_channels = 0;
881 bool wanted_alpha =
false;
882 switch (egg_tex->get_format()) {
883 case EggTexture::F_red:
884 case EggTexture::F_green:
885 case EggTexture::F_blue:
886 case EggTexture::F_alpha:
887 case EggTexture::F_luminance:
889 wanted_alpha =
false;
892 case EggTexture::F_luminance_alpha:
893 case EggTexture::F_luminance_alphamask:
898 case EggTexture::F_rgb:
899 case EggTexture::F_rgb12:
900 case EggTexture::F_rgb8:
901 case EggTexture::F_rgb5:
902 case EggTexture::F_rgb332:
903 case EggTexture::F_srgb:
905 wanted_alpha =
false;
908 case EggTexture::F_rgba:
909 case EggTexture::F_rgbm:
910 case EggTexture::F_rgba12:
911 case EggTexture::F_rgba8:
912 case EggTexture::F_rgba4:
913 case EggTexture::F_rgba5:
914 case EggTexture::F_srgb_alpha:
919 case EggTexture::F_unspecified:
926 if (_record !=
nullptr) {
935 if (egg_preload_simple_textures) {
936 options.set_texture_flags(options.get_texture_flags() | LoaderOptions::TF_preload_simple);
939 if (!egg_ignore_filters && !egg_ignore_mipmaps) {
940 switch (egg_tex->get_minfilter()) {
941 case EggTexture::FT_nearest:
942 case EggTexture::FT_linear:
943 case EggTexture::FT_unspecified:
946 case EggTexture::FT_nearest_mipmap_nearest:
947 case EggTexture::FT_linear_mipmap_nearest:
948 case EggTexture::FT_nearest_mipmap_linear:
949 case EggTexture::FT_linear_mipmap_linear:
950 options.set_texture_flags(options.get_texture_flags() | LoaderOptions::TF_generate_mipmaps);
955 options.set_texture_flags(options.get_texture_flags() | LoaderOptions::TF_multiview);
962 if (egg_tex->get_compression_mode() == EggTexture::CM_on) {
963 options.set_texture_flags(options.get_texture_flags() | LoaderOptions::TF_allow_compression);
967 switch (egg_tex->get_texture_type()) {
968 case EggTexture::TT_unspecified:
969 case EggTexture::TT_1d_texture:
970 options.set_texture_flags(options.get_texture_flags() | LoaderOptions::TF_allow_1d);
973 case EggTexture::TT_2d_texture:
987 case EggTexture::TT_3d_texture:
992 case EggTexture::TT_cube_map:
998 if (tex ==
nullptr) {
1013 if (aux !=
nullptr &&
1014 aux->
is_of_type(EggTexture::get_class_type())) {
1017 if (aux_egg_tex->
get_alpha_mode() != EggTexture::AM_unspecified) {
1020 if (aux_egg_tex->get_format() != EggTexture::F_unspecified) {
1021 egg_tex->set_format(aux_egg_tex->get_format());
1023 if (aux_egg_tex->get_minfilter() != EggTexture::FT_unspecified) {
1024 egg_tex->set_minfilter(aux_egg_tex->get_minfilter());
1026 if (aux_egg_tex->get_magfilter() != EggTexture::FT_unspecified) {
1027 egg_tex->set_magfilter(aux_egg_tex->get_magfilter());
1034 apply_texture_attributes(tex, egg_tex);
1038 def._texture = DCAST(
TextureAttrib, TextureAttrib::make())->add_on_stage(stage, tex);
1040 def._egg_tex = egg_tex;
1051 if (egg_tex->get_compression_mode() != EggTexture::CM_default) {
1052 tex->
set_compression(convert_compression_mode(egg_tex->get_compression_mode()));
1061 if (wrap_u != EggTexture::WM_unspecified) {
1062 sampler.
set_wrap_u(convert_wrap_mode(wrap_u));
1064 if (wrap_v != EggTexture::WM_unspecified) {
1065 sampler.
set_wrap_v(convert_wrap_mode(wrap_v));
1067 if (wrap_w != EggTexture::WM_unspecified) {
1068 sampler.
set_wrap_w(convert_wrap_mode(wrap_w));
1075 switch (egg_tex->get_minfilter()) {
1076 case EggTexture::FT_nearest:
1080 case EggTexture::FT_linear:
1081 if (egg_ignore_filters) {
1082 egg2pg_cat.warning()
1083 <<
"Ignoring minfilter request\n";
1090 case EggTexture::FT_nearest_mipmap_nearest:
1091 if (egg_ignore_filters) {
1092 egg2pg_cat.warning()
1093 <<
"Ignoring minfilter request\n";
1095 }
else if (egg_ignore_mipmaps) {
1096 egg2pg_cat.warning()
1097 <<
"Ignoring mipmap request\n";
1100 sampler.
set_minfilter(SamplerState::FT_nearest_mipmap_nearest);
1104 case EggTexture::FT_linear_mipmap_nearest:
1105 if (egg_ignore_filters) {
1106 egg2pg_cat.warning()
1107 <<
"Ignoring minfilter request\n";
1109 }
else if (egg_ignore_mipmaps) {
1110 egg2pg_cat.warning()
1111 <<
"Ignoring mipmap request\n";
1114 sampler.
set_minfilter(SamplerState::FT_linear_mipmap_nearest);
1118 case EggTexture::FT_nearest_mipmap_linear:
1119 if (egg_ignore_filters) {
1120 egg2pg_cat.warning()
1121 <<
"Ignoring minfilter request\n";
1123 }
else if (egg_ignore_mipmaps) {
1124 egg2pg_cat.warning()
1125 <<
"Ignoring mipmap request\n";
1128 sampler.
set_minfilter(SamplerState::FT_nearest_mipmap_linear);
1132 case EggTexture::FT_linear_mipmap_linear:
1133 if (egg_ignore_filters) {
1134 egg2pg_cat.warning()
1135 <<
"Ignoring minfilter request\n";
1137 }
else if (egg_ignore_mipmaps) {
1138 egg2pg_cat.warning()
1139 <<
"Ignoring mipmap request\n";
1142 sampler.
set_minfilter(SamplerState::FT_linear_mipmap_linear);
1146 case EggTexture::FT_unspecified:
1150 switch (egg_tex->get_magfilter()) {
1151 case EggTexture::FT_nearest:
1152 case EggTexture::FT_nearest_mipmap_nearest:
1153 case EggTexture::FT_nearest_mipmap_linear:
1157 case EggTexture::FT_linear:
1158 case EggTexture::FT_linear_mipmap_nearest:
1159 case EggTexture::FT_linear_mipmap_linear:
1160 if (egg_ignore_filters) {
1161 egg2pg_cat.warning()
1162 <<
"Ignoring magfilter request\n";
1169 case EggTexture::FT_unspecified:
1191 bool force_srgb =
false;
1192 if (egg_force_srgb_textures) {
1193 switch (egg_tex->get_env_type()) {
1194 case EggTexture::ET_unspecified:
1195 case EggTexture::ET_modulate:
1196 case EggTexture::ET_decal:
1197 case EggTexture::ET_blend:
1198 case EggTexture::ET_replace:
1199 case EggTexture::ET_add:
1200 case EggTexture::ET_blend_color_scale:
1201 case EggTexture::ET_modulate_glow:
1202 case EggTexture::ET_modulate_gloss:
1204 if (egg2pg_cat.is_debug()) {
1206 <<
"Enabling sRGB format on texture " << egg_tex->get_name() <<
"\n";
1216 switch (egg_tex->get_format()) {
1217 case EggTexture::F_red:
1220 case EggTexture::F_green:
1223 case EggTexture::F_blue:
1226 case EggTexture::F_alpha:
1229 case EggTexture::F_luminance:
1234 egg2pg_cat.warning()
1235 <<
"Ignoring inappropriate format " << egg_tex->get_format()
1236 <<
" for 1-component texture " << egg_tex->get_name() <<
"\n";
1238 case EggTexture::F_unspecified:
1246 switch (egg_tex->get_format()) {
1247 case EggTexture::F_luminance_alpha:
1248 tex->
set_format(force_srgb ? Texture::F_sluminance_alpha :
Texture::F_luminance_alpha);
1251 case EggTexture::F_luminance_alphamask:
1252 tex->
set_format(force_srgb ? Texture::F_sluminance_alpha :
Texture::F_luminance_alphamask);
1256 egg2pg_cat.warning()
1257 <<
"Ignoring inappropriate format " << egg_tex->get_format()
1258 <<
" for 2-component texture " << egg_tex->get_name() <<
"\n";
1260 case EggTexture::F_unspecified:
1262 tex->
set_format(Texture::F_sluminance_alpha);
1268 switch (egg_tex->get_format()) {
1269 case EggTexture::F_rgb:
1272 case EggTexture::F_rgb12:
1279 egg2pg_cat.warning()
1280 <<
"Ignoring inappropriate format " << egg_tex->get_format()
1281 <<
" for 8-bit texture " << egg_tex->get_name() <<
"\n";
1284 case EggTexture::F_rgb8:
1285 case EggTexture::F_rgba8:
1290 case EggTexture::F_rgb5:
1293 case EggTexture::F_rgb332:
1296 case EggTexture::F_srgb:
1297 case EggTexture::F_srgb_alpha:
1302 egg2pg_cat.warning()
1303 <<
"Ignoring inappropriate format " << egg_tex->get_format()
1304 <<
" for 3-component texture " << egg_tex->get_name() <<
"\n";
1306 case EggTexture::F_unspecified:
1314 switch (egg_tex->get_format()) {
1315 case EggTexture::F_rgba:
1318 case EggTexture::F_rgbm:
1321 case EggTexture::F_rgba12:
1328 egg2pg_cat.warning()
1329 <<
"Ignoring inappropriate format " << egg_tex->get_format()
1330 <<
" for 8-bit texture " << egg_tex->get_name() <<
"\n";
1333 case EggTexture::F_rgba8:
1336 case EggTexture::F_rgba4:
1339 case EggTexture::F_rgba5:
1342 case EggTexture::F_srgb_alpha:
1347 egg2pg_cat.warning()
1348 <<
"Ignoring inappropriate format " << egg_tex->get_format()
1349 <<
" for 4-component texture " << egg_tex->get_name() <<
"\n";
1351 case EggTexture::F_unspecified:
1359 if (force_srgb && tex->
get_format() != Texture::F_alpha &&
1361 egg2pg_cat.warning()
1362 <<
"Unable to enable sRGB format on texture " << egg_tex->get_name()
1363 <<
" with specified format " << egg_tex->get_format() <<
"\n";
1366 switch (egg_tex->get_quality_level()) {
1367 case EggTexture::QL_unspecified:
1368 case EggTexture::QL_default:
1372 case EggTexture::QL_fastest:
1376 case EggTexture::QL_normal:
1380 case EggTexture::QL_best:
1391Texture::CompressionMode EggLoader::
1392convert_compression_mode(EggTexture::CompressionMode compression_mode)
const {
1393 switch (compression_mode) {
1394 case EggTexture::CM_off:
1395 return Texture::CM_off;
1397 case EggTexture::CM_on:
1398 return Texture::CM_on;
1400 case EggTexture::CM_fxt1:
1401 return Texture::CM_fxt1;
1403 case EggTexture::CM_dxt1:
1404 return Texture::CM_dxt1;
1406 case EggTexture::CM_dxt2:
1407 return Texture::CM_dxt2;
1409 case EggTexture::CM_dxt3:
1410 return Texture::CM_dxt3;
1412 case EggTexture::CM_dxt4:
1413 return Texture::CM_dxt4;
1415 case EggTexture::CM_dxt5:
1416 return Texture::CM_dxt5;
1418 case EggTexture::CM_default:
1419 return Texture::CM_default;
1422 egg2pg_cat.warning()
1423 <<
"Unexpected texture compression flag: " << (int)compression_mode <<
"\n";
1424 return Texture::CM_default;
1431SamplerState::WrapMode EggLoader::
1432convert_wrap_mode(EggTexture::WrapMode wrap_mode)
const {
1433 switch (wrap_mode) {
1434 case EggTexture::WM_clamp:
1435 return SamplerState::WM_clamp;
1437 case EggTexture::WM_repeat:
1438 return SamplerState::WM_repeat;
1440 case EggTexture::WM_mirror:
1441 return SamplerState::WM_mirror;
1443 case EggTexture::WM_mirror_once:
1444 return SamplerState::WM_mirror_once;
1446 case EggTexture::WM_border_color:
1447 return SamplerState::WM_border_color;
1449 case EggTexture::WM_unspecified:
1450 return SamplerState::WM_repeat;
1453 egg2pg_cat.warning()
1454 <<
"Unexpected texture wrap flag: " << (int)wrap_mode <<
"\n";
1455 return SamplerState::WM_repeat;
1462make_texture_stage(
const EggTexture *egg_tex) {
1469 (egg_tex->get_env_type() == EggTexture::ET_unspecified ||
1470 egg_tex->get_env_type() == EggTexture::ET_modulate) &&
1471 egg_tex->get_combine_mode(EggTexture::CC_rgb) == EggTexture::CM_unspecified &&
1472 egg_tex->get_combine_mode(EggTexture::CC_alpha) == EggTexture::CM_unspecified &&
1482 switch (egg_tex->get_env_type()) {
1483 case EggTexture::ET_modulate:
1484 stage->set_mode(TextureStage::M_modulate);
1487 case EggTexture::ET_decal:
1488 stage->set_mode(TextureStage::M_decal);
1491 case EggTexture::ET_blend:
1492 stage->set_mode(TextureStage::M_blend);
1495 case EggTexture::ET_replace:
1496 stage->set_mode(TextureStage::M_replace);
1499 case EggTexture::ET_add:
1500 stage->set_mode(TextureStage::M_add);
1503 case EggTexture::ET_blend_color_scale:
1504 stage->set_mode(TextureStage::M_blend_color_scale);
1507 case EggTexture::ET_modulate_glow:
1508 stage->set_mode(TextureStage::M_modulate_glow);
1511 case EggTexture::ET_modulate_gloss:
1512 stage->set_mode(TextureStage::M_modulate_gloss);
1515 case EggTexture::ET_normal:
1516 stage->set_mode(TextureStage::M_normal);
1519 case EggTexture::ET_normal_height:
1520 stage->set_mode(TextureStage::M_normal_height);
1523 case EggTexture::ET_glow:
1524 stage->set_mode(TextureStage::M_glow);
1527 case EggTexture::ET_gloss:
1528 stage->set_mode(TextureStage::M_gloss);
1531 case EggTexture::ET_height:
1532 stage->set_mode(TextureStage::M_height);
1535 case EggTexture::ET_selector:
1536 stage->set_mode(TextureStage::M_selector);
1539 case EggTexture::ET_normal_gloss:
1540 stage->set_mode(TextureStage::M_normal_gloss);
1543 case EggTexture::ET_emission:
1544 stage->set_mode(TextureStage::M_emission);
1547 case EggTexture::ET_unspecified:
1551 switch (egg_tex->get_combine_mode(EggTexture::CC_rgb)) {
1552 case EggTexture::CM_replace:
1553 stage->set_combine_rgb(get_combine_mode(egg_tex, EggTexture::CC_rgb),
1554 get_combine_source(egg_tex, EggTexture::CC_rgb, 0),
1555 get_combine_operand(egg_tex, EggTexture::CC_rgb, 0));
1558 case EggTexture::CM_modulate:
1559 case EggTexture::CM_add:
1560 case EggTexture::CM_add_signed:
1561 case EggTexture::CM_subtract:
1562 case EggTexture::CM_dot3_rgb:
1563 case EggTexture::CM_dot3_rgba:
1564 stage->set_combine_rgb(get_combine_mode(egg_tex, EggTexture::CC_rgb),
1565 get_combine_source(egg_tex, EggTexture::CC_rgb, 0),
1566 get_combine_operand(egg_tex, EggTexture::CC_rgb, 0),
1567 get_combine_source(egg_tex, EggTexture::CC_rgb, 1),
1568 get_combine_operand(egg_tex, EggTexture::CC_rgb, 1));
1571 case EggTexture::CM_interpolate:
1572 stage->set_combine_rgb(get_combine_mode(egg_tex, EggTexture::CC_rgb),
1573 get_combine_source(egg_tex, EggTexture::CC_rgb, 0),
1574 get_combine_operand(egg_tex, EggTexture::CC_rgb, 0),
1575 get_combine_source(egg_tex, EggTexture::CC_rgb, 1),
1576 get_combine_operand(egg_tex, EggTexture::CC_rgb, 1),
1577 get_combine_source(egg_tex, EggTexture::CC_rgb, 2),
1578 get_combine_operand(egg_tex, EggTexture::CC_rgb, 2));
1581 case EggTexture::CM_unspecified:
1585 switch (egg_tex->get_combine_mode(EggTexture::CC_alpha)) {
1586 case EggTexture::CM_replace:
1587 stage->set_combine_alpha(get_combine_mode(egg_tex, EggTexture::CC_alpha),
1588 get_combine_source(egg_tex, EggTexture::CC_alpha, 0),
1589 get_combine_operand(egg_tex, EggTexture::CC_alpha, 0));
1592 case EggTexture::CM_modulate:
1593 case EggTexture::CM_add:
1594 case EggTexture::CM_add_signed:
1595 case EggTexture::CM_subtract:
1596 stage->set_combine_alpha(get_combine_mode(egg_tex, EggTexture::CC_alpha),
1597 get_combine_source(egg_tex, EggTexture::CC_alpha, 0),
1598 get_combine_operand(egg_tex, EggTexture::CC_alpha, 0),
1599 get_combine_source(egg_tex, EggTexture::CC_alpha, 1),
1600 get_combine_operand(egg_tex, EggTexture::CC_alpha, 1));
1603 case EggTexture::CM_interpolate:
1604 stage->set_combine_alpha(get_combine_mode(egg_tex, EggTexture::CC_alpha),
1605 get_combine_source(egg_tex, EggTexture::CC_alpha, 0),
1606 get_combine_operand(egg_tex, EggTexture::CC_alpha, 0),
1607 get_combine_source(egg_tex, EggTexture::CC_alpha, 1),
1608 get_combine_operand(egg_tex, EggTexture::CC_alpha, 1),
1609 get_combine_source(egg_tex, EggTexture::CC_alpha, 2),
1610 get_combine_operand(egg_tex, EggTexture::CC_alpha, 2));
1613 case EggTexture::CM_unspecified:
1614 case EggTexture::CM_dot3_rgb:
1615 case EggTexture::CM_dot3_rgba:
1622 InternalName::get_texcoord_name(egg_tex->
get_uv_name());
1623 stage->set_texcoord_name(name);
1655separate_switches(
EggNode *egg_node) {
1656 bool parent_has_switch =
false;
1657 if (egg_node->
is_of_type(EggGroup::get_class_type())) {
1659 parent_has_switch = egg_group->get_switch_flag();
1662 if (egg_node->
is_of_type(EggGroupNode::get_class_type())) {
1665 EggGroupNode::iterator ci;
1666 ci = egg_group->begin();
1667 while (ci != egg_group->end()) {
1668 EggGroupNode::iterator cnext;
1673 if (parent_has_switch &&
1674 child->is_of_type(EggPrimitive::get_class_type())) {
1677 egg_group->
replace(ci, new_group.p());
1678 new_group->add_child(child);
1681 separate_switches(child);
1694emulate_bface(
EggNode *egg_node) {
1695 if (egg_node->
is_of_type(EggGroupNode::get_class_type())) {
1699 EggGroupNode::iterator ci;
1700 for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
1702 if (child->is_of_type(EggPolygon::get_class_type())) {
1708 dup_poly->reverse_vertex_ordering();
1709 if (dup_poly->has_normal()) {
1710 dup_poly->set_normal(-dup_poly->get_normal());
1714 EggPolygon::iterator vi;
1715 for (vi = dup_poly->begin(); vi != dup_poly->end(); ++vi) {
1717 if (vertex->has_normal()) {
1719 dup_vertex.set_normal(-dup_vertex.get_normal());
1721 if (new_vertex != vertex) {
1723 dup_poly->replace(vi, new_vertex);
1727 dup_prims->add_child(dup_poly);
1731 emulate_bface(child);
1745 if (egg_node->
is_of_type(EggBin::get_class_type())) {
1746 return make_node(DCAST(
EggBin, egg_node), parent);
1747 }
else if (egg_node->
is_of_type(EggGroup::get_class_type())) {
1748 return make_node(DCAST(
EggGroup, egg_node), parent);
1749 }
else if (egg_node->
is_of_type(EggTable::get_class_type())) {
1750 return make_node(DCAST(
EggTable, egg_node), parent);
1751 }
else if (egg_node->
is_of_type(EggGroupNode::get_class_type())) {
1752 return make_node(DCAST(
EggGroupNode, egg_node), parent);
1766 switch (egg_bin->get_bin_number()) {
1767 case EggBinner::BN_polyset:
1768 case EggBinner::BN_patches:
1769 make_polyset(egg_bin, parent,
nullptr, _dynamic_override, _dynamic_override_char_maker);
1772 case EggBinner::BN_lod:
1773 return make_lod(egg_bin, parent);
1775 case EggBinner::BN_nurbs_surface:
1777 nassertr(!egg_bin->empty(),
nullptr);
1780 DCAST_INTO_R(egg_nurbs, child,
nullptr);
1782 make_nurbs_surface(egg_nurbs, parent, mat);
1786 case EggBinner::BN_nurbs_curve:
1788 nassertr(!egg_bin->empty(),
nullptr);
1791 DCAST_INTO_R(egg_nurbs, child,
nullptr);
1793 make_nurbs_curve(egg_nurbs, parent, mat);
1797 case EggBinner::BN_none:
1810 PT(
LODNode) lod_node = LODNode::make_default_lod(egg_bin->get_name());
1814 EggGroup::const_iterator ci;
1815 for (ci = egg_bin->begin(); ci != egg_bin->end(); ++ci) {
1816 LODInstance instance(*ci);
1817 instances.push_back(instance);
1822 sort(instances.begin(), instances.end());
1824 if (!instances.empty()) {
1827 lod_node->set_center(LCAST(PN_stdfloat, instances[0]._d->_center));
1830 for (
size_t i = 0; i < instances.size(); i++) {
1832 const LODInstance &instance = instances[i];
1833 make_node(instance._egg_node, lod_node);
1837 nassertr(lod_node->get_center().almost_equal
1838 (LCAST(PN_stdfloat, instance._d->_center), 0.01),
nullptr);
1841 lod_node->add_switch(instance._d->_switch_in, instance._d->_switch_out);
1844 _groups[egg_bin] = lod_node;
1845 return create_group_arc(egg_bin, parent, lod_node);
1855 if (egg_group->get_dart_type() != EggGroup::DT_none) {
1857 bool structured = (egg_group->get_dart_type() == EggGroup::DT_structured);
1861 node = char_maker.make_node();
1865 _dynamic_override =
true;
1866 _dynamic_override_char_maker = &char_maker;
1867 EggGroup::const_iterator ci;
1868 for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
1869 make_node(*ci, node);
1871 _dynamic_override_char_maker =
nullptr;
1872 _dynamic_override =
false;
1875 }
else if (egg_group->get_cs_type() != EggGroup::CST_none) {
1881 node->set_transform(TransformState::make_mat(LCAST(PN_stdfloat, egg_group->
get_vertex_to_node())));
1882 make_collision_solids(egg_group, egg_group, (
CollisionNode *)node.p());
1883 node->clear_transform();
1885 if ((egg_group->get_collide_flags() & EggGroup::CF_keep) != 0) {
1890 parent->add_child(combined);
1891 combined->add_child(node);
1894 EggGroup::const_iterator ci;
1895 for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
1896 make_node(*ci, combined);
1900 node = create_group_arc(egg_group, parent, node);
1903 }
else if (egg_group->get_portal_flag()) {
1910 set_portal_polygon(egg_group, pnode);
1912 egg2pg_cat.warning()
1913 <<
"Portal " << egg_group->get_name() <<
" has no vertices!\n";
1916 }
else if (egg_group->get_occluder_flag()) {
1923 set_occluder_polygon(egg_group, pnode);
1925 egg2pg_cat.warning()
1926 <<
"Occluder " << egg_group->get_name() <<
" has no vertices!\n";
1929 }
else if (egg_group->get_polylight_flag()) {
1937 if (!make_sphere(egg_group, EggGroup::CF_none, center, radius, color)) {
1938 egg2pg_cat.warning()
1939 <<
"Polylight " << egg_group->get_name() <<
" make_sphere failed!\n";
1950 }
else if (egg_group->get_switch_flag()) {
1951 if (egg_group->get_switch_fps() != 0.0) {
1954 ((
SequenceNode *)node.p())->set_frame_rate(egg_group->get_switch_fps());
1955 _sequences.insert(node);
1958 node =
new SwitchNode(egg_group->get_name());
1961 EggGroup::const_iterator ci;
1962 for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
1963 make_node(*ci, node);
1965 }
else if (egg_group->has_scrolling_uvs()) {
1966 node =
new UvScrollNode(egg_group->get_name(), egg_group->get_scroll_u(), egg_group->get_scroll_v(), egg_group->get_scroll_w(), egg_group->get_scroll_r());
1968 EggGroup::const_iterator ci;
1969 for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
1970 make_node(*ci, node);
1973 }
else if (egg_group->get_model_flag() || egg_group->
has_dcs_type()) {
1975 node =
new ModelNode(egg_group->get_name());
1976 switch (egg_group->get_dcs_type()) {
1977 case EggGroup::DC_net:
1978 DCAST(
ModelNode, node)->set_preserve_transform(ModelNode::PT_net);
1981 case EggGroup::DC_no_touch:
1982 DCAST(
ModelNode, node)->set_preserve_transform(ModelNode::PT_no_touch);
1985 case EggGroup::DC_local:
1986 case EggGroup::DC_default:
1987 DCAST(
ModelNode, node)->set_preserve_transform(ModelNode::PT_local);
1990 case EggGroup::DC_none:
1991 case EggGroup::DC_unspecified:
1995 EggGroup::const_iterator ci;
1996 for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
1997 make_node(*ci, node);
2005 bool all_polysets =
false;
2006 bool any_hidden =
false;
2011 check_for_polysets(egg_group, all_polysets, any_hidden);
2014 if (all_polysets && !any_hidden) {
2015 node =
new GeomNode(egg_group->get_name());
2017 node =
new PandaNode(egg_group->get_name());
2020 EggGroup::const_iterator ci;
2021 for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
2022 make_node(*ci, node);
2026 if (node ==
nullptr) {
2032 for (
int gri = 0; gri < num_group_refs; ++gri) {
2034 Groups::const_iterator gi = _groups.find(group_ref);
2035 if (gi != _groups.end()) {
2037 node->add_child(node_ref);
2041 _groups[egg_group] = node;
2042 return create_group_arc(egg_group, parent, node);
2052 parent->add_child(node);
2062 switch (egg_group->get_billboard_type()) {
2063 case EggGroup::BT_point_camera_relative:
2064 node->
set_effect(BillboardEffect::make_point_eye());
2067 case EggGroup::BT_point_world_relative:
2068 node->
set_effect(BillboardEffect::make_point_world());
2071 case EggGroup::BT_axis:
2072 node->
set_effect(BillboardEffect::make_axis());
2075 case EggGroup::BT_none:
2079 if (egg_group->get_decal_flag()) {
2080 if (egg_ignore_decals) {
2082 <<
"Ignoring decal flag on " << egg_group->get_name() <<
"\n";
2089 _decals.insert(node);
2093 EggGroup::TagData::const_iterator ti;
2095 node->
set_tag((*ti).first, (*ti).second);
2098 if (egg_group->get_blend_mode() != EggGroup::BM_unspecified &&
2099 egg_group->get_blend_mode() != EggGroup::BM_none) {
2101 ColorBlendAttrib::Mode mode = get_color_blend_mode(egg_group->get_blend_mode());
2102 ColorBlendAttrib::Operand a = get_color_blend_operand(egg_group->get_blend_operand_a());
2103 ColorBlendAttrib::Operand b = get_color_blend_operand(egg_group->get_blend_operand_b());
2105 node->
set_attrib(ColorBlendAttrib::make(mode, a, b, color));
2112 if (egg_group->has_collide_mask()) {
2113 def._from_collide_mask = egg_group->get_collide_mask();
2114 def._into_collide_mask = egg_group->get_collide_mask();
2116 DeferredNodeProperty::F_has_from_collide_mask |
2117 DeferredNodeProperty::F_has_into_collide_mask;
2119 if (egg_group->has_from_collide_mask()) {
2120 def._from_collide_mask = egg_group->get_from_collide_mask();
2121 def._flags |= DeferredNodeProperty::F_has_from_collide_mask;
2123 if (egg_group->has_into_collide_mask()) {
2124 def._into_collide_mask = egg_group->get_into_collide_mask();
2125 def._flags |= DeferredNodeProperty::F_has_into_collide_mask;
2128 if (def._flags != 0) {
2129 _deferred_nodes[node] = def;
2140 if (egg_table->get_table_type() != EggTable::TT_bundle) {
2143 return make_node(DCAST(
EggGroupNode, egg_table), parent);
2149 parent->add_child(node);
2161 EggGroupNode::const_iterator ci;
2162 for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
2163 make_node(*ci, node);
2166 parent->add_child(node);
2175check_for_polysets(
EggGroup *egg_group,
bool &all_polysets,
bool &any_hidden) {
2176 all_polysets = (!egg_group->empty());
2179 EggGroup::const_iterator ci;
2180 for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
2181 if ((*ci)->is_of_type(EggBin::get_class_type())) {
2183 if (egg_bin->get_bin_number() == EggBinner::BN_polyset) {
2186 EggGroup::const_iterator bci = egg_bin->begin();
2187 nassertv(bci != egg_bin->end());
2189 DCAST_INTO_V(first_prim, (*bci));
2191 DCAST_INTO_V(render_state, first_prim->
get_user_data(EggRenderState::get_class_type()));
2193 if (render_state->_hidden) {
2197 all_polysets =
false;
2200 }
else if ((*ci)->is_of_type(EggGroup::get_class_type())) {
2204 all_polysets =
false;
2220 bool ignore_color) {
2221 VertexPoolTransform vpt;
2222 vpt._vertex_pool = vertex_pool;
2223 vpt._bake_in_uvs = render_state->_bake_in_uvs;
2224 vpt._transform = transform;
2226 VertexPoolData::iterator di;
2227 di = _vertex_pool_data.find(vpt);
2228 if (di != _vertex_pool_data.end()) {
2229 return (*di).second;
2235 Geom::NT_stdfloat, Geom::C_point);
2238 array_format->add_column
2239 (InternalName::get_normal(), 3,
2240 Geom::NT_stdfloat, Geom::C_normal);
2243 if (!ignore_color) {
2247 array_format->add_column(InternalName::get_color(), 1,
2248 Geom::NT_packed_dabc, Geom::C_color);
2250 array_format->add_column(InternalName::get_color(), 4,
2251 Geom::NT_uint8, Geom::C_color);
2255 vector_string uv_names, uvw_names, tbn_names;
2256 vertex_pool->
get_uv_names(uv_names, uvw_names, tbn_names);
2257 vector_string::const_iterator ni;
2258 for (ni = uv_names.begin(); ni != uv_names.end(); ++ni) {
2259 string name = (*ni);
2261 PT(
InternalName) iname = InternalName::get_texcoord_name(name);
2263 if (find(uvw_names.begin(), uvw_names.end(), name) != uvw_names.end()) {
2265 array_format->add_column
2266 (iname, 3, Geom::NT_stdfloat, Geom::C_texcoord);
2268 array_format->add_column
2269 (iname, 2, Geom::NT_stdfloat, Geom::C_texcoord);
2272 for (ni = tbn_names.begin(); ni != tbn_names.end(); ++ni) {
2273 string name = (*ni);
2275 PT(
InternalName) iname_t = InternalName::get_tangent_name(name);
2276 PT(
InternalName) iname_b = InternalName::get_binormal_name(name);
2278 array_format->add_column
2279 (iname_t, 3, Geom::NT_stdfloat, Geom::C_vector);
2280 array_format->add_column
2281 (iname_b, 3, Geom::NT_stdfloat, Geom::C_vector);
2284 vector_string aux_names;
2286 for (ni = aux_names.begin(); ni != aux_names.end(); ++ni) {
2287 string name = (*ni);
2289 array_format->add_column
2290 (iname, 4, Geom::NT_stdfloat, Geom::C_other);
2296 string name = _data->get_egg_filename().get_basename_wo_extension();
2307 temp_format->set_animation(animation);
2311 (InternalName::get_transform_blend(), 1,
2312 Geom::NT_uint16, Geom::C_index, 0, 2);
2313 temp_format->add_array(anim_array_format);
2317 for (vi = vertex_pool->
begin(); vi != vertex_pool->
end(); ++vi) {
2320 EggMorphVertexList::const_iterator mvi;
2321 for (mvi = vertex->_dxyzs.begin(); mvi != vertex->_dxyzs.end(); ++mvi) {
2322 slider_names[(*mvi).get_name()].set_bit(vertex->
get_index());
2323 record_morph(anim_array_format, character_maker, (*mvi).
get_name(),
2324 InternalName::get_vertex(), 3);
2326 if (vertex->has_normal()) {
2327 EggMorphNormalList::const_iterator mni;
2328 for (mni = vertex->_dnormals.begin(); mni != vertex->_dnormals.end(); ++mni) {
2329 slider_names[(*mni).get_name()].set_bit(vertex->
get_index());
2330 record_morph(anim_array_format, character_maker, (*mni).
get_name(),
2331 InternalName::get_normal(), 3);
2334 if (!ignore_color && vertex->has_color()) {
2335 EggMorphColorList::const_iterator mci;
2336 for (mci = vertex->_drgbas.begin(); mci != vertex->_drgbas.end(); ++mci) {
2337 slider_names[(*mci).get_name()].set_bit(vertex->
get_index());
2338 record_morph(anim_array_format, character_maker, (*mci).
get_name(),
2339 InternalName::get_color(), 4);
2345 string name = egg_uv->get_name();
2346 bool has_w = (find(uvw_names.begin(), uvw_names.end(), name) != uvw_names.end());
2347 PT(
InternalName) iname = InternalName::get_texcoord_name(name);
2349 EggMorphTexCoordList::const_iterator mti;
2350 for (mti = egg_uv->_duvs.begin(); mti != egg_uv->_duvs.end(); ++mti) {
2351 slider_names[(*mti).get_name()].set_bit(vertex->
get_index());
2352 record_morph(anim_array_format, character_maker, (*mti).
get_name(),
2353 iname, has_w ? 3 : 2);
2358 if (!slider_names.empty()) {
2364 for (si = slider_names.begin(); si != slider_names.end(); ++si) {
2366 slider_table->add_slider(slider, (*si).second);
2372 name = character_maker->
get_name();
2375 temp_format->maybe_align_columns_for_animation();
2378 GeomVertexFormat::register_format(temp_format);
2386 vertex_data->reserve_num_rows(vertex_pool->
size());
2388 vertex_data->set_transform_blend_table(blend_table);
2389 if (slider_table !=
nullptr) {
2390 vertex_data->set_slider_table(SliderTable::register_table(slider_table));
2395 for (vi = vertex_pool->
begin(); vi != vertex_pool->
end(); ++vi) {
2404 EggMorphVertexList::const_iterator mvi;
2405 for (mvi = vertex->_dxyzs.begin(); mvi != vertex->_dxyzs.end(); ++mvi) {
2408 InternalName::get_morph(InternalName::get_vertex(), morph.get_name());
2410 gvw.
add_data3d(morph.get_offset() * transform);
2414 if (vertex->has_normal()) {
2416 LNormald orig_normal = vertex->get_normal();
2417 LNormald transformed_normal = normalize(orig_normal * transform);
2421 EggMorphNormalList::const_iterator mni;
2422 for (mni = vertex->_dnormals.begin(); mni != vertex->_dnormals.end(); ++mni) {
2425 InternalName::get_morph(InternalName::get_normal(), morph.get_name());
2427 LNormald morphed_normal = orig_normal + morph.get_offset();
2428 LNormald transformed_morphed_normal = normalize(morphed_normal * transform);
2429 LVector3d delta = transformed_morphed_normal - transformed_normal;
2435 if (!ignore_color && vertex->has_color()) {
2440 EggMorphColorList::const_iterator mci;
2441 for (mci = vertex->_drgbas.begin(); mci != vertex->_drgbas.end(); ++mci) {
2444 InternalName::get_morph(InternalName::get_color(), morph.get_name());
2454 LTexCoord3d orig_uvw = egg_uv->
get_uvw();
2455 LTexCoord3d uvw = egg_uv->
get_uvw();
2457 string name = egg_uv->get_name();
2458 PT(
InternalName) iname = InternalName::get_texcoord_name(name);
2461 BakeInUVs::const_iterator buv = render_state->_bake_in_uvs.find(iname);
2462 if (buv != render_state->_bake_in_uvs.end()) {
2464 uvw = uvw * (*buv).second->get_transform3d();
2470 EggMorphTexCoordList::const_iterator mti;
2471 for (mti = egg_uv->_duvs.begin(); mti != egg_uv->_duvs.end(); ++mti) {
2474 InternalName::get_morph(iname, morph.get_name());
2476 LTexCoord3d duvw = morph.get_offset();
2477 if (buv != render_state->_bake_in_uvs.end()) {
2478 LTexCoord3d new_uvw = orig_uvw + duvw;
2479 duvw = (new_uvw * (*buv).second->get_transform3d()) - uvw;
2487 if (egg_uv->has_tangent() && egg_uv->has_binormal()) {
2488 PT(
InternalName) iname = InternalName::get_tangent_name(name);
2491 LVector3d tangent = egg_uv->get_tangent();
2492 LVector3d binormal = egg_uv->get_binormal();
2494 gvw.
set_column(InternalName::get_binormal_name(name));
2503 LVecBase4d aux = egg_aux->
get_aux();
2505 string name = egg_aux->get_name();
2514 gvw.
set_column(InternalName::get_transform_blend());
2519 bool inserted = _vertex_pool_data.insert
2520 (VertexPoolData::value_type(vpt, vertex_data)).second;
2521 nassertr(inserted, vertex_data);
2538 for (vi = vertex_pool->
begin(); vi != vertex_pool->
end(); ++vi) {
2547 nassertr(vt !=
nullptr,
nullptr);
2552 double quantize = egg_vertex_membership_quantize;
2553 EggVertex::GroupRef::const_iterator gri;
2557 if (quantize != 0.0) {
2558 membership = cfloor(membership / quantize + 0.5) * quantize;
2562 nassertr(vt !=
nullptr,
nullptr);
2566 if (egg_vertex_max_num_joints >= 0) {
2571 int table_index = blend_table->add_blend(blend);
2588 int num_components) {
2590 InternalName::get_morph(column_name, morph_name);
2593 (delta_name, num_components,
2594 Geom::NT_stdfloat, Geom::C_morph_delta);
2606 bool has_overall_color,
const LColor &overall_color) {
2608 if (egg_prim->
is_of_type(EggPolygon::get_class_type())) {
2609 if (egg_prim->size() == 3) {
2613 }
else if (egg_prim->
is_of_type(EggTriangleStrip::get_class_type())) {
2616 }
else if (egg_prim->
is_of_type(EggTriangleFan::get_class_type())) {
2619 }
else if (egg_prim->
is_of_type(EggLine::get_class_type())) {
2620 if (egg_prim->size() == 2) {
2621 primitive =
new GeomLines(Geom::UH_static);
2626 }
else if (egg_prim->
is_of_type(EggPoint::get_class_type())) {
2629 }
else if (egg_prim->
is_of_type(EggPatch::get_class_type())) {
2630 int num_vertices = egg_prim->size();
2631 primitive =
new GeomPatches(num_vertices, Geom::UH_static);
2634 if (primitive ==
nullptr) {
2636 egg2pg_cat.warning()
2637 <<
"Ignoring " << egg_prim->get_type() <<
"\n";
2641 if (render_state->_flat_shaded) {
2642 primitive->set_shade_model(GeomPrimitive::SM_flat_first_vertex);
2644 }
else if (egg_prim->
get_shading() == EggPrimitive::S_overall) {
2645 primitive->set_shade_model(GeomPrimitive::SM_uniform);
2648 primitive->set_shade_model(GeomPrimitive::SM_smooth);
2653 PrimitiveUnifier pu(primitive);
2654 std::pair<UniquePrimitives::iterator, bool> result =
2655 unique_primitives.insert(UniquePrimitives::value_type(pu, primitive));
2657 if (result.second) {
2659 primitives.push_back(primitive);
2661 if (egg2pg_cat.is_debug()) {
2663 <<
"First primitive of type " << primitive->get_type()
2664 <<
": " << primitive <<
"\n";
2672 if (orig_prim->
get_num_vertices() + egg_prim->size() <= (
unsigned int)egg_max_indices) {
2673 primitive = orig_prim;
2675 }
else if (orig_prim != primitive) {
2677 (*result.first).second = primitive;
2679 if (egg2pg_cat.is_debug()) {
2681 <<
"Next primitive of type " << primitive->get_type()
2682 <<
": " << primitive <<
"\n";
2684 primitives.push_back(primitive);
2688 EggPrimitive::const_iterator vi;
2689 for (vi = egg_prim->begin(); vi != egg_prim->end(); ++vi) {
2690 primitive->add_vertex((*vi)->get_index());
2692 primitive->close_primitive();
2702 PT(
EggPolygon) poly = find_first_polygon(egg_group);
2703 if (poly !=
nullptr) {
2706 EggPolygon::const_iterator vi;
2707 for (vi = poly->begin(); vi != poly->end(); ++vi) {
2708 LVertexd vert = (*vi)->
get_pos3() * mat;
2719 PT(
EggPolygon) poly = find_first_polygon(egg_group);
2720 if (poly !=
nullptr) {
2721 if (poly->size() != 4) {
2723 <<
"Invalid number of vertices for " << egg_group->get_name() <<
"\n";
2727 LPoint3d v0 = (*poly)[0]->get_pos3() * mat;
2728 LPoint3d v1 = (*poly)[1]->get_pos3() * mat;
2729 LPoint3d v2 = (*poly)[2]->get_pos3() * mat;
2730 LPoint3d v3 = (*poly)[3]->get_pos3() * mat;
2732 LCAST(PN_stdfloat, v1),
2733 LCAST(PN_stdfloat, v2),
2734 LCAST(PN_stdfloat, v3));
2747find_first_polygon(
EggGroup *egg_group) {
2749 EggGroup::const_iterator ci;
2750 for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
2751 if ((*ci)->is_of_type(EggPolygon::get_class_type())) {
2758 for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
2759 if ((*ci)->is_of_type(EggGroup::get_class_type())) {
2761 PT(
EggPolygon) found = find_first_polygon(child_group);
2762 if (found !=
nullptr) {
2778make_sphere(
EggGroup *egg_group, EggGroup::CollideFlags flags,
2779 LPoint3 ¢er, PN_stdfloat &radius, LColor &color) {
2780 EggGroup *geom_group = find_collision_geometry(egg_group, flags);
2781 if (geom_group !=
nullptr) {
2785 EggGroup::const_iterator ci;
2786 for (ci = geom_group->begin(); ci != geom_group->end(); ++ci) {
2787 if ((*ci)->is_of_type(EggPrimitive::get_class_type())) {
2789 EggPrimitive::const_iterator pi;
2790 for (pi = prim->begin(); pi != prim->end(); ++pi) {
2791 vertices.insert(*pi);
2797 int num_vertices = 0;
2798 LPoint3d d_center(0.0, 0.0, 0.0);
2801 for (vi = vertices.begin(); vi != vertices.end(); ++vi) {
2807 if (num_vertices > 0) {
2808 d_center /= (double)num_vertices;
2812 double radius2 = 0.0;
2813 for (vi = vertices.begin(); vi != vertices.end(); ++vi) {
2816 LVector3d v = p3 - d_center;
2817 radius2 = max(radius2, v.length_squared());
2820 center = LCAST(PN_stdfloat, d_center);
2821 radius = sqrtf(radius2);
2824 vi = vertices.begin();
2838make_box(
EggGroup *egg_group, EggGroup::CollideFlags flags,
2839 const LMatrix4 &xform, LPoint3 &min_p, LPoint3 &max_p) {
2840 EggGroup *geom_group = find_collision_geometry(egg_group, flags);
2841 if (geom_group !=
nullptr) {
2845 EggGroup::const_iterator ci;
2846 for (ci = geom_group->begin(); ci != geom_group->end(); ++ci) {
2847 if ((*ci)->is_of_type(EggPrimitive::get_class_type())) {
2849 EggPrimitive::const_iterator pi;
2850 for (pi = prim->begin(); pi != prim->end(); ++pi) {
2851 vertices.insert(*pi);
2858 vi = vertices.begin();
2860 if (vi == vertices.end()) {
2868 LPoint3 min_pd = LCAST(PN_stdfloat, vertex->
get_pos3()) * xform;
2869 LPoint3 max_pd = min_pd;
2871 for (++vi; vi != vertices.end(); ++vi) {
2873 LPoint3 pos = LCAST(PN_stdfloat, vertex->
get_pos3()) * xform;
2874 min_pd.set(min(min_pd[0], pos[0]),
2875 min(min_pd[1], pos[1]),
2876 min(min_pd[2], pos[2]));
2877 max_pd.set(max(max_pd[0], pos[0]),
2878 max(max_pd[1], pos[1]),
2879 max(max_pd[2], pos[2]));
2884 return (min_pd != max_pd);
2894make_box(
EggGroup *egg_group, EggGroup::CollideFlags flags,
2895 LPoint3 &min_p, LPoint3 &max_p, LColor &color) {
2897 color.set(1.0, 1.0, 1.0, 1.0);
2898 return make_box(egg_group, flags, LMatrix4::ident_mat(), min_p, max_p);
2908 if (egg_group->get_cs_type() != EggGroup::CST_none) {
2909 start_group = egg_group;
2912 switch (start_group->get_cs_type()) {
2913 case EggGroup::CST_none:
2917 case EggGroup::CST_plane:
2918 make_collision_plane(egg_group, cnode, start_group->get_collide_flags());
2921 case EggGroup::CST_polygon:
2922 make_collision_polygon(egg_group, cnode, start_group->get_collide_flags());
2925 case EggGroup::CST_polyset:
2926 make_collision_polyset(egg_group, cnode, start_group->get_collide_flags());
2929 case EggGroup::CST_sphere:
2930 make_collision_sphere(egg_group, cnode, start_group->get_collide_flags());
2933 case EggGroup::CST_box:
2934 make_collision_box(egg_group, cnode, start_group->get_collide_flags());
2937 case EggGroup::CST_inv_sphere:
2938 make_collision_inv_sphere(egg_group, cnode, start_group->get_collide_flags());
2941 case EggGroup::CST_tube:
2942 make_collision_capsule(egg_group, cnode, start_group->get_collide_flags());
2945 case EggGroup::CST_floor_mesh:
2946 make_collision_floor_mesh(egg_group, cnode, start_group->get_collide_flags());
2950 if ((start_group->get_collide_flags() & EggGroup::CF_descend) != 0) {
2952 EggGroup::const_iterator ci;
2953 for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
2954 if ((*ci)->is_of_type(EggGroup::get_class_type())) {
2955 make_collision_solids(start_group, DCAST(
EggGroup, *ci), cnode);
2959 egg2pg_cat.warning()
2960 <<
"Using <Collide> without 'descend' is deprecated. 'descend' "
2961 <<
"will become the default in a future version of Panda3D.\n";
2971 EggGroup::CollideFlags flags) {
2972 EggGroup *geom_group = find_collision_geometry(egg_group, flags);
2973 if (geom_group !=
nullptr) {
2974 EggGroup::const_iterator ci;
2975 for (ci = geom_group->begin(); ci != geom_group->end(); ++ci) {
2976 if ((*ci)->is_of_type(EggPolygon::get_class_type())) {
2978 create_collision_plane(DCAST(
EggPolygon, *ci), egg_group);
2979 if (csplane !=
nullptr) {
2980 apply_collision_flags(csplane, flags);
2981 csplane->
xform(cnode->get_transform()->get_mat());
2985 }
else if ((*ci)->is_of_type(EggCompositePrimitive::get_class_type()) &&
2986 !(*ci)->is_of_type(EggLine::get_class_type())) {
2990 make_collision_plane(temp_group, cnode, flags);
3006 EggGroup::CollideFlags flags) {
3008 EggGroup *geom_group = find_collision_geometry(egg_group, flags);
3011 if (geom_group !=
nullptr) {
3012 create_collision_floor_mesh(cnode, geom_group,flags);
3022 EggGroup::CollideFlags flags) {
3024 EggGroup *geom_group = find_collision_geometry(egg_group, flags);
3025 if (geom_group !=
nullptr) {
3026 EggGroup::const_iterator ci;
3027 for (ci = geom_group->begin(); ci != geom_group->end(); ++ci) {
3028 if ((*ci)->is_of_type(EggPolygon::get_class_type())) {
3029 create_collision_polygons(cnode, DCAST(
EggPolygon, *ci),
3031 }
else if ((*ci)->is_of_type(EggCompositePrimitive::get_class_type())) {
3035 make_collision_polygon(temp_group, cnode, flags);
3050 EggGroup::CollideFlags flags) {
3051 EggGroup *geom_group = find_collision_geometry(egg_group, flags);
3052 if (geom_group !=
nullptr) {
3053 EggGroup::const_iterator ci;
3054 for (ci = geom_group->begin(); ci != geom_group->end(); ++ci) {
3055 if ((*ci)->is_of_type(EggPolygon::get_class_type())) {
3056 create_collision_polygons(cnode, DCAST(
EggPolygon, *ci),
3058 }
else if ((*ci)->is_of_type(EggCompositePrimitive::get_class_type())) {
3062 make_collision_polyset(temp_group, cnode, flags);
3075 EggGroup::CollideFlags flags) {
3079 if (make_sphere(egg_group, flags, center, radius, dummycolor)) {
3082 apply_collision_flags(cssphere, flags);
3083 cssphere->xform(cnode->get_transform()->get_mat());
3094 EggGroup::CollideFlags flags) {
3098 if (make_box(egg_group, flags, transform->get_mat(), min_p, max_p)) {
3101 apply_collision_flags(csbox, flags);
3112 EggGroup::CollideFlags flags) {
3116 if (make_sphere(egg_group, flags, center, radius, dummycolor)) {
3119 apply_collision_flags(cssphere, flags);
3120 cssphere->xform(cnode->get_transform()->get_mat());
3131 EggGroup::CollideFlags flags) {
3132 EggGroup *geom_group = find_collision_geometry(egg_group, flags);
3133 if (geom_group !=
nullptr) {
3137 EggGroup::const_iterator ci;
3138 for (ci = geom_group->begin(); ci != geom_group->end(); ++ci) {
3139 if ((*ci)->is_of_type(EggPrimitive::get_class_type())) {
3141 EggPrimitive::const_iterator pi;
3142 for (pi = prim->begin(); pi != prim->end(); ++pi) {
3143 vertices.insert(*pi);
3150 size_t num_vertices = vertices.size();
3151 if (num_vertices != 0) {
3153 vpos.reserve(num_vertices);
3155 LPoint3d center(0.0, 0.0, 0.0);
3157 for (vi = vertices.begin(); vi != vertices.end(); ++vi) {
3159 const LPoint3d &pos = vtx->
get_pos3();
3160 vpos.push_back(pos);
3163 center /= (double)num_vertices;
3169 double radius2 = 0.0;
3170 LPoint3d far_a = center;
3171 for (i = 0; i < num_vertices; i++) {
3172 double dist2 = (vpos[i] - center).length_squared();
3173 if (dist2 > radius2) {
3183 LPoint3d far_b = center;
3184 for (i = 0; i < num_vertices; i++) {
3185 double dist2 = (vpos[i] - far_a).length_squared();
3186 if (dist2 > radius2) {
3203 LPoint3d cap_a_center(0.0, 0.0, 0.0);
3204 LPoint3d cap_b_center(0.0, 0.0, 0.0);
3210 double center_length = (far_a - far_b).length() / 4.0;
3211 double center_length2 = center_length * center_length;
3213 for (i = 0; i < num_vertices; i++) {
3214 double dist2 = (vpos[i] - center).length_squared();
3215 if (dist2 > center_length2) {
3218 double dist_a2 = (vpos[i] - far_a).length_squared();
3219 double dist_b2 = (vpos[i] - far_b).length_squared();
3220 if (dist_a2 < dist_b2) {
3222 cap_a_center += vpos[i];
3226 cap_b_center += vpos[i];
3232 if (num_a > 0 && num_b > 0) {
3233 cap_a_center /= (double)num_a;
3234 cap_b_center /= (double)num_b;
3238 LVector3d axis = cap_b_center - cap_a_center;
3243 if (IS_THRESHOLD_ZERO(axis[0], 0.01)) {
3246 if (IS_THRESHOLD_ZERO(axis[1], 0.01)) {
3249 if (IS_THRESHOLD_ZERO(axis[2], 0.01)) {
3261 look_at(mat, axis, LVector3d(0.0, 0.0, 1.0), CS_zup_right);
3262 mat.set_row(3, center);
3264 inv_mat.invert_from(mat);
3266 for (i = 0; i < num_vertices; i++) {
3267 vpos[i] = vpos[i] * inv_mat;
3270 double max_radius2 = 0.0;
3273 for (i = 0; i < num_vertices; i++) {
3274 LVector2d v(vpos[i][0], vpos[i][2]);
3275 double radius2 = v.length_squared();
3276 if (radius2 > max_radius2) {
3277 max_radius2 = radius2;
3287 for (i = 0; i < num_vertices; i++) {
3288 LVector2d v(vpos[i][0], vpos[i][2]);
3289 double radius2 = v.length_squared();
3291 if (vpos[i][1] < min_y) {
3294 double factor = sqrt(max_radius2 - radius2);
3295 min_y = min(min_y, vpos[i][1] + factor);
3297 }
else if (vpos[i][1] > max_y) {
3298 double factor = sqrt(max_radius2 - radius2);
3299 max_y = max(max_y, vpos[i][1] - factor);
3303 double length = max_y - min_y;
3304 double radius = sqrt(max_radius2);
3307 LVector3d half = axis * (length / 2.0);
3308 LPoint3d point_a = center - half;
3309 LPoint3d point_b = center + half;
3312 new CollisionCapsule(LCAST(PN_stdfloat, point_a), LCAST(PN_stdfloat, point_b),
3314 apply_collision_flags(cscapsule, flags);
3315 cscapsule->xform(cnode->get_transform()->get_mat());
3327apply_collision_flags(
CollisionSolid *solid, EggGroup::CollideFlags flags) {
3328 if ((flags & EggGroup::CF_intangible) != 0) {
3331 if ((flags & EggGroup::CF_level) != 0) {
3341find_collision_geometry(
EggGroup *egg_group, EggGroup::CollideFlags flags) {
3342 if ((flags & EggGroup::CF_descend) != 0) {
3349 EggGroup::const_iterator ci;
3350 for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
3351 if ((*ci)->is_of_type(EggPolygon::get_class_type())) {
3359 for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
3360 if ((*ci)->is_of_type(EggGroup::get_class_type())) {
3362 if (child_group->get_cs_type() == egg_group->get_cs_type()) {
3379 <<
"Ignoring degenerate collision plane in " << parent_group->get_name()
3385 egg2pg_cat.warning()
3386 <<
"Non-planar polygon defining collision plane in "
3387 << parent_group->get_name()
3392 if (!egg_poly->empty()) {
3393 EggPolygon::const_iterator vi;
3394 vi = egg_poly->begin();
3396 LVertexd vert = (*vi)->get_pos3();
3397 vertices.push_back(LCAST(PN_stdfloat, vert));
3399 LVertexd last_vert = vert;
3401 while (vi != egg_poly->end()) {
3402 vert = (*vi)->get_pos3();
3403 if (!vert.almost_equal(last_vert)) {
3404 vertices.push_back(LCAST(PN_stdfloat, vert));
3412 if (vertices.size() < 3) {
3415 LPlane plane(vertices[0], vertices[1], vertices[2]);
3426 EggGroup::CollideFlags flags) {
3432 <<
"Ignoring degenerate collision polygon in "
3433 << parent_group->get_name()
3438 if (group->size() != 1) {
3440 <<
"Triangulating concave or non-planar collision polygon in "
3441 << parent_group->get_name()
3445 EggGroup::iterator ci;
3446 for (ci = group->begin(); ci != group->end(); ++ci) {
3450 if (!poly->empty()) {
3451 EggPolygon::const_iterator vi;
3454 LVertexd vert = (*vi)->get_pos3();
3455 vertices.push_back(LCAST(PN_stdfloat, vert));
3457 LVertexd last_vert = vert;
3459 while (vi != poly->end()) {
3460 vert = (*vi)->get_pos3();
3461 if (!vert.almost_equal(last_vert)) {
3462 vertices.push_back(LCAST(PN_stdfloat, vert));
3470 if (vertices.size() >= 3) {
3471 const LVertex *vertices_begin = &vertices[0];
3472 const LVertex *vertices_end = vertices_begin + vertices.size();
3475 if (cspoly->is_valid()) {
3476 apply_collision_flags(cspoly, flags);
3477 cspoly->xform(cnode->get_transform()->get_mat());
3491 EggGroup::CollideFlags flags) {
3495 pool.local_object();
3496 EggGroup::const_iterator egi;
3497 for (egi = parent_group->begin(); egi != parent_group->end(); ++egi) {
3498 if ((*egi)->is_of_type(EggPolygon::get_class_type())) {
3502 <<
"Ignoring degenerate collision polygon in "
3503 << parent_group->get_name()
3510 if(group->size() == 0) {
3512 <<
"empty collision solid\n";
3518 EggGroup::iterator ci;
3519 for (ci = group->begin(); ci != group->end(); ++ci) {
3521 if (poly->get_num_vertices() == 3) {
3522 CollisionFloorMesh::TriangleIndices tri;
3525 tri.p1=pool.create_unique_vertex(*poly->
get_vertex(0))->get_index();
3526 tri.p2=pool.create_unique_vertex(*poly->
get_vertex(1))->get_index();
3527 tri.p3=pool.create_unique_vertex(*poly->
get_vertex(2))->get_index();
3529 triangles.push_back(tri);
3530 }
else if (poly->get_num_vertices() == 4) {
3533 CollisionFloorMesh::TriangleIndices tri;
3534 CollisionFloorMesh::TriangleIndices tri2;
3537 tri.p1=pool.create_unique_vertex(*poly->
get_vertex(0))->get_index();
3538 tri.p2=pool.create_unique_vertex(*poly->
get_vertex(1))->get_index();
3539 tri.p3=pool.create_unique_vertex(*poly->
get_vertex(2))->get_index();
3541 triangles.push_back(tri);
3546 tri2.p3=pool.create_unique_vertex(*poly->
get_vertex(3))->get_index();
3549 triangles.push_back(tri2);
3558 for (vi = pool.begin(); vi != pool.end(); vi++) {
3559 csfloor->add_vertex(LCAST(PN_stdfloat,(*vi)->get_pos3()));
3564 for (ti = triangles.begin(); ti != triangles.end(); ti++) {
3565 CollisionFloorMesh::TriangleIndices triangle = *ti;
3566 csfloor->add_triangle(triangle.p1, triangle.p2, triangle.p3);
3568 csfloor->xform(cnode->get_transform()->get_mat());
3582 DeferredNodes::const_iterator dni;
3583 dni = _deferred_nodes.find(node);
3585 if (dni != _deferred_nodes.end()) {
3591 next_prop.apply_to_node(node);
3594 for (
int i = 0; i < num_children; i++) {
3595 apply_deferred_nodes(node->
get_child(i), next_prop);
3608expand_all_object_types(
EggNode *egg_node) {
3609 if (egg_node->
is_of_type(EggGroup::get_class_type())) {
3612 if (egg_group->get_num_object_types() != 0) {
3615 if (!expand_object_types(egg_group, expanded, expanded_history)) {
3623 if (egg_node->
is_of_type(EggGroupNode::get_class_type())) {
3625 EggGroupNode::const_iterator ci;
3626 ci = egg_group_node->begin();
3627 while (ci != egg_group_node->end()) {
3628 EggGroupNode::const_iterator cnext = ci;
3631 if (!expand_all_object_types(*ci)) {
3633 egg_group_node->erase(ci);
3654 int num_object_types = egg_group->get_num_object_types();
3657 vector_string object_types;
3659 for (i = 0; i < num_object_types; i++) {
3660 object_types.push_back(egg_group->get_object_type(i));
3662 egg_group->clear_object_types();
3664 for (i = 0; i < num_object_types; i++) {
3665 string object_type = object_types[i];
3669 if (!new_expanded.insert(object_type).second) {
3671 <<
"Cycle in ObjectType expansions:\n";
3673 for (pi = expanded_history.begin();
3674 pi != expanded_history.end();
3676 egg2pg_cat.error(
false)
3679 egg2pg_cat.error(
false) << object_type <<
"\n";
3685 new_expanded_history.push_back(object_type);
3687 if (!do_expand_object_type(egg_group, new_expanded,
3688 new_expanded_history, object_type)) {
3704 const string &object_type) {
3709 (
"egg-object-type-" +
downcase(object_type),
"");
3710 string egg_syntax = egg_object_type;
3712 if (!egg_object_type.has_value()) {
3715 if (cmp_nocase_uh(object_type,
"barrier") == 0) {
3716 egg_syntax =
"<Collide> { Polyset descend }";
3718 }
else if (cmp_nocase_uh(object_type,
"solidpoly") == 0) {
3719 egg_syntax =
"<Collide> { Polyset descend solid }";
3721 }
else if (cmp_nocase_uh(object_type,
"turnstile") == 0) {
3722 egg_syntax =
"<Collide> { Polyset descend turnstile }";
3724 }
else if (cmp_nocase_uh(object_type,
"sphere") == 0) {
3725 egg_syntax =
"<Collide> { Sphere descend }";
3727 }
else if (cmp_nocase_uh(object_type,
"tube") == 0) {
3728 egg_syntax =
"<Collide> { Tube descend }";
3730 }
else if (cmp_nocase_uh(object_type,
"trigger") == 0) {
3731 egg_syntax =
"<Collide> { Polyset descend intangible }";
3733 }
else if (cmp_nocase_uh(object_type,
"trigger_sphere") == 0) {
3734 egg_syntax =
"<Collide> { Sphere descend intangible }";
3736 }
else if (cmp_nocase_uh(object_type,
"eye_trigger") == 0) {
3737 egg_syntax =
"<Collide> { Polyset descend intangible center }";
3739 }
else if (cmp_nocase_uh(object_type,
"bubble") == 0) {
3740 egg_syntax =
"<Collide> { Sphere keep descend }";
3742 }
else if (cmp_nocase_uh(object_type,
"ghost") == 0) {
3743 egg_syntax =
"<Scalar> collide-mask { 0 }";
3745 }
else if (cmp_nocase_uh(object_type,
"dcs") == 0) {
3746 egg_syntax =
"<DCS> { 1 }";
3748 }
else if (cmp_nocase_uh(object_type,
"model") == 0) {
3749 egg_syntax =
"<Model> { 1 }";
3751 }
else if (cmp_nocase_uh(object_type,
"none") == 0) {
3755 }
else if (cmp_nocase_uh(object_type,
"backstage") == 0) {
3761 <<
"Unknown ObjectType " << object_type <<
"\n";
3763 egg2pg_cat.debug() <<
"returning true\n";
3768 if (!egg_syntax.empty()) {
3769 if (!egg_group->
parse_egg(egg_syntax)) {
3771 <<
"Error while parsing definition for ObjectType "
3772 << object_type <<
"\n";
3778 if (egg_group->get_num_object_types() != 0) {
3779 if (!expand_object_types(egg_group, expanded, expanded_history)) {
3793TextureStage::CombineMode EggLoader::
3795 EggTexture::CombineChannel channel) {
3796 switch (egg_tex->get_combine_mode(channel)) {
3797 case EggTexture::CM_unspecified:
3800 case EggTexture::CM_modulate:
3801 return TextureStage::CM_modulate;
3803 case EggTexture::CM_replace:
3804 return TextureStage::CM_replace;
3806 case EggTexture::CM_add:
3807 return TextureStage::CM_add;
3809 case EggTexture::CM_add_signed:
3810 return TextureStage::CM_add_signed;
3812 case EggTexture::CM_interpolate:
3813 return TextureStage::CM_interpolate;
3815 case EggTexture::CM_subtract:
3816 return TextureStage::CM_subtract;
3818 case EggTexture::CM_dot3_rgb:
3819 return TextureStage::CM_dot3_rgb;
3821 case EggTexture::CM_dot3_rgba:
3822 return TextureStage::CM_dot3_rgba;
3825 return TextureStage::CM_undefined;
3832TextureStage::CombineSource EggLoader::
3834 EggTexture::CombineChannel channel,
int n) {
3835 switch (egg_tex->get_combine_source(channel, n)) {
3836 case EggTexture::CS_unspecified:
3841 return TextureStage::CS_previous;
3843 return TextureStage::CS_texture;
3845 return TextureStage::CS_constant;
3849 case EggTexture::CS_texture:
3850 return TextureStage::CS_texture;
3852 case EggTexture::CS_constant:
3853 return TextureStage::CS_constant;
3855 case EggTexture::CS_primary_color:
3856 return TextureStage::CS_primary_color;
3858 case EggTexture::CS_previous:
3859 return TextureStage::CS_previous;
3861 case EggTexture::CS_constant_color_scale:
3862 return TextureStage::CS_constant_color_scale;
3864 case EggTexture::CS_last_saved_result:
3865 return TextureStage::CS_last_saved_result;
3868 return TextureStage::CS_undefined;
3875TextureStage::CombineOperand EggLoader::
3876get_combine_operand(
const EggTexture *egg_tex,
3877 EggTexture::CombineChannel channel,
int n) {
3878 switch (egg_tex->get_combine_operand(channel, n)) {
3879 case EggTexture::CO_unspecified:
3880 if (channel == EggTexture::CC_rgb) {
3883 return n < 2 ? TextureStage::CO_src_color : TextureStage::CO_src_alpha;
3886 return TextureStage::CO_src_alpha;
3889 case EggTexture::CO_src_color:
3890 return TextureStage::CO_src_color;
3892 case EggTexture::CO_one_minus_src_color:
3893 return TextureStage::CO_one_minus_src_color;
3895 case EggTexture::CO_src_alpha:
3896 return TextureStage::CO_src_alpha;
3898 case EggTexture::CO_one_minus_src_alpha:
3899 return TextureStage::CO_one_minus_src_alpha;
3902 return TextureStage::CO_undefined;
3909ColorBlendAttrib::Mode EggLoader::
3910get_color_blend_mode(EggGroup::BlendMode mode) {
3912 case EggGroup::BM_unspecified:
3913 case EggGroup::BM_none:
3914 return ColorBlendAttrib::M_none;
3915 case EggGroup::BM_add:
3916 return ColorBlendAttrib::M_add;
3917 case EggGroup::BM_subtract:
3918 return ColorBlendAttrib::M_subtract;
3919 case EggGroup::BM_inv_subtract:
3920 return ColorBlendAttrib::M_inv_subtract;
3921 case EggGroup::BM_min:
3922 return ColorBlendAttrib::M_min;
3923 case EggGroup::BM_max:
3924 return ColorBlendAttrib::M_max;
3927 return ColorBlendAttrib::M_none;
3934ColorBlendAttrib::Operand EggLoader::
3935get_color_blend_operand(EggGroup::BlendOperand operand) {
3937 case EggGroup::BO_zero:
3938 return ColorBlendAttrib::O_zero;
3939 case EggGroup::BO_unspecified:
3940 case EggGroup::BO_one:
3941 return ColorBlendAttrib::O_one;
3942 case EggGroup::BO_incoming_color:
3943 return ColorBlendAttrib::O_incoming_color;
3944 case EggGroup::BO_one_minus_incoming_color:
3945 return ColorBlendAttrib::O_one_minus_incoming_color;
3946 case EggGroup::BO_fbuffer_color:
3947 return ColorBlendAttrib::O_fbuffer_color;
3948 case EggGroup::BO_one_minus_fbuffer_color:
3949 return ColorBlendAttrib::O_one_minus_fbuffer_color;
3950 case EggGroup::BO_incoming_alpha:
3951 return ColorBlendAttrib::O_incoming_alpha;
3952 case EggGroup::BO_one_minus_incoming_alpha:
3953 return ColorBlendAttrib::O_one_minus_incoming_alpha;
3954 case EggGroup::BO_fbuffer_alpha:
3955 return ColorBlendAttrib::O_fbuffer_alpha;
3956 case EggGroup::BO_one_minus_fbuffer_alpha:
3957 return ColorBlendAttrib::O_one_minus_fbuffer_alpha;
3958 case EggGroup::BO_constant_color:
3959 return ColorBlendAttrib::O_constant_color;
3960 case EggGroup::BO_one_minus_constant_color:
3961 return ColorBlendAttrib::O_one_minus_constant_color;
3962 case EggGroup::BO_constant_alpha:
3963 return ColorBlendAttrib::O_constant_alpha;
3964 case EggGroup::BO_one_minus_constant_alpha:
3965 return ColorBlendAttrib::O_one_minus_constant_alpha;
3966 case EggGroup::BO_incoming_color_saturate:
3967 return ColorBlendAttrib::O_incoming_color_saturate;
3968 case EggGroup::BO_color_scale:
3969 return ColorBlendAttrib::O_color_scale;
3970 case EggGroup::BO_one_minus_color_scale:
3971 return ColorBlendAttrib::O_one_minus_color_scale;
3972 case EggGroup::BO_alpha_scale:
3973 return ColorBlendAttrib::O_alpha_scale;
3974 case EggGroup::BO_one_minus_alpha_scale:
3975 return ColorBlendAttrib::O_one_minus_alpha_scale;
3978 return ColorBlendAttrib::O_zero;
3984bool EggLoader::VertexPoolTransform::
3985operator < (
const EggLoader::VertexPoolTransform &other)
const {
3986 if (_vertex_pool != other._vertex_pool) {
3987 return _vertex_pool < other._vertex_pool;
3989 int compare = _transform.compare_to(other._transform, 0.001);
3994 if (_bake_in_uvs.size() != other._bake_in_uvs.size()) {
3995 return _bake_in_uvs.size() < other._bake_in_uvs.size();
3998 BakeInUVs::const_iterator ai, bi;
3999 ai = _bake_in_uvs.begin();
4000 bi = other._bake_in_uvs.begin();
4001 while (ai != _bake_in_uvs.end()) {
4002 nassertr(bi != other._bake_in_uvs.end(),
false);
4003 if ((*ai) != (*bi)) {
4004 return (*ai) < (*bi);
4009 nassertr(bi == other._bake_in_uvs.end(),
false);
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Converts an EggTable hierarchy, beginning with a <Bundle> entry, into an AnimBundle hierarchy.
This is a node that contains a pointer to an AnimBundle.
void loop(bool restart)
Starts the entire animation looping.
Converts an EggGroup hierarchy, beginning with a group with <Dart> set, to a character node with join...
std::string get_name() const
Returns the name of the character.
VertexSlider * egg_to_slider(const std::string &name)
Returns the VertexSlider corresponding to the indicated egg slider name.
VertexTransform * egg_to_transform(EggNode *egg_node)
Returns a JointVertexTransform suitable for applying the animation associated with the given egg node...
A cuboid collision volume or object.
This implements a solid consisting of a cylinder with hemispherical endcaps, also known as a capsule ...
This object represents a solid made entirely of triangles, which will only be tested again z axis ali...
An inverted sphere: this is a sphere whose collision surface is the inside surface of the sphere.
A node in the scene graph that can hold any number of CollisionSolids.
size_t add_solid(const CollisionSolid *solid)
Adds the indicated solid to the node.
virtual void xform(const LMatrix4 &mat)
Transforms the solid by the indicated matrix.
The abstract base class for all things that can collide with other things in the world,...
set_tangible
Sets the current state of the 'tangible' flag.
void set_effective_normal(const LVector3 &effective_normal)
Records a false normal for this CollisionSolid that will be reported by the collision system with all...
A spherical collision volume or object.
This is a convenience class to specialize ConfigVariable as a string type.
This class keeps track of all the state we must make note of during the graph traversal,...
void compose(const DeferredNodeProperty &other)
Composes this state with the next one encountered on a lower node during the apply traversal.
LColor get_color() const
Returns the color set on this particular attribute.
A type of group node that holds related subnodes.
A special binner used only within this package to pre-process the egg tree for the loader and group t...
The base class for primitives such as triangle strips and triangle fans, which include several compon...
bool triangulate_into(EggGroupNode *container) const
Subdivides the composite primitive into triangles and adds those triangles to the indicated container...
int get_subdiv() const
Returns the requested number of subdivisions, or 0 if no particular subdivisions have been requested.
CurveType get_curve_type() const
Returns the indicated type of the curve.
This is the primary interface into all the egg data, and the root of the egg file structure.
set_coordinate_system
Changes the coordinate system of the EggData.
const Filename & get_filename() const
Returns a nonmodifiable reference to the filename.
const Filename & get_fullpath() const
Returns the full pathname to the file, if it is known; otherwise, returns the same thing as get_filen...
A base class for nodes in the hierarchy that are not leaf nodes.
int triangulate_polygons(int flags)
Replace all higher-order polygons at this point in the scene graph and below with triangles.
void apply_first_attribute(bool recurse)
Sets the first vertex of the triangle (or each component) to the primitive normal and/or color,...
void post_apply_flat_attribute(bool recurse)
Intended as a followup to apply_last_attribute(), this also sets an attribute on the first vertices o...
void mesh_triangles(int flags)
Combine triangles together into triangle strips, at this group and below.
void rebuild_vertex_pools(EggVertexPools &vertex_pools, unsigned int max_vertices, bool recurse)
Copies vertices used by the primitives at this group node (and below, if recurse is true) into one or...
EggNode * get_first_child()
Returns the first child in the group's list of children, or NULL if the list of children is empty.
void replace(iterator position, PT(EggNode) x)
Replaces the node at the indicated position with the indicated node.
void steal_children(EggGroupNode &other)
Moves all the children from the other node to this one.
The main glue of the egg hierarchy, this corresponds to the <Group>, <Instance>, and <Joint> type nod...
get_blend_color
Returns the blend color if one has been specified, or (0, 0, 0, 0) if one has not.
TagData::const_iterator tag_begin() const
Returns an iterator that can, in conjunction with tag_end(), be used to traverse the entire set of ta...
get_group_ref
Returns the nth <Ref> entry within this group.
TagData::const_iterator tag_end() const
Returns an iterator that can, in conjunction with tag_begin(), be used to traverse the entire set of ...
get_num_group_refs
Returns the number of <Ref> entries within this group.
bool has_dcs_type() const
Returns true if the specified DCS type is not DC_none and not DC_unspecified.
double get_vertex_membership(const EggVertex *vert) const
Returns the amount of membership of the indicated vertex in this group.
virtual bool determine_decal()
Walks back up the hierarchy, looking for an EggGroup at this level or above that has the "decal" flag...
void reparent_decals()
For each node representing a decal base geometry (i.e.
void make_polyset(EggBin *egg_bin, PandaNode *parent, const LMatrix4d *transform, bool is_dynamic, CharacterMaker *character_maker)
Creates a polyset–that is, a Geom–from the primitives that have already been grouped into a bin.
void start_sequences()
Starts all of the SequenceNodes we created looping.
A single <Dxyz> or <Duv> or some such entry.
A base class for things that may be directly added into the egg hierarchy.
const LMatrix4d & get_vertex_to_node() const
Returns the transformation matrix suitable for converting the vertices as read from the egg file into...
bool parse_egg(const std::string &egg_syntax)
Parses the egg syntax given in the indicate string as if it had been read from the egg file within th...
A parametric NURBS curve.
get_order
Returns the order of the curve.
get_num_knots
Returns the number of knots.
get_knot
Returns the nth knot value defined.
A parametric NURBS surface.
EggUserData * get_user_data() const
Returns the user data pointer most recently stored on this object, or NULL if nothing was previously ...
bool is_planar() const
Returns true if all of the polygon's vertices lie within the same plane, false otherwise.
bool triangulate_into(EggGroupNode *container, bool convex_also) const
Subdivides the polygon into triangles and adds each one to the indicated container.
virtual bool cleanup() override
Cleans up modeling errors in whatever context this makes sense.
A base class for any of a number of kinds of geometry primitives: polygons, point lights,...
set_bface_flag
Sets the backfacing flag of the polygon.
get_pool
Returns the vertex pool associated with the vertices of the primitive, or NULL if the primitive has n...
get_shading
Returns the shading properties apparent on this particular primitive.
get_vertex
Returns a particular index based on its index number.
get_bface_flag
Retrieves the backfacing flag of the polygon.
bool has_vertex_color() const
Returns true if any vertex on the primitive has a specific color set, false otherwise.
void set_alpha_mode(AlphaMode mode)
Specifies precisely how the transparency for this geometry should be achieved, or if it should be use...
AlphaMode get_alpha_mode() const
Returns the alpha mode that was set, or AM_unspecified if nothing was set.
This class is used within this package only to record the render state that should be assigned to eac...
void add_attrib(const RenderAttrib *attrib)
A convenience function to add the indicated render attribute to the aggregate state.
int get_v_subdiv() const
Returns the requested number of subdivisions in the U direction, or 0 if no particular subdivisions h...
int get_u_subdiv() const
Returns the requested number of subdivisions in the U direction, or 0 if no particular subdivisions h...
A SwitchCondition that switches the levels-of-detail based on distance from the camera's eyepoint.
This corresponds to a <SwitchCondition> entry within a group.
This is a collection of textures by TRef name.
int find_used_textures(EggNode *node)
Walks the egg hierarchy beginning at the indicated node, looking for textures that are referenced by ...
Defines a texture map that may be applied to geometry.
get_stage_name
Returns the stage name that has been specified for this texture, or the tref name if no texture stage...
get_read_mipmaps
Returns the current setting of the read_mipmaps flag.
WrapMode determine_wrap_u() const
Determines the appropriate wrap in the U direction.
has_uv_name
Returns true if a texcoord name has been explicitly specified for this texture, false otherwise.
get_alpha_scale
Returns the alpha_scale value that has been specified for the texture, or 1 if no alpha_scale value h...
get_uv_name
Returns the texcoord name that has been specified for this texture, or the empty string if no texcoor...
get_multiview
Returns the current setting of the multiview flag.
get_multitexture_sort
Returns an integer that represents the depth to which this texture is layered on all other textures i...
has_num_views
Returns true if the number of views has been specified for the 3-D multiview texture,...
get_lod_bias
Returns the maximum mipmap level that has been specified for this texture.
get_alpha_file_channel
Returns the particular channel that has been specified for the alpha-file image, or 0 if no channel h...
has_anisotropic_degree
Returns true if a value for the anisotropic filtering degree has been specified for this texture,...
get_border_color
Returns the border color if one has been specified, or (0, 0, 0, 1) otherwise.
get_min_lod
Returns the minimum mipmap level that has been specified for this texture.
WrapMode determine_wrap_w() const
Determines the appropriate wrap in the W direction.
set_anisotropic_degree
Sets the degree of anisotropic filtering for this texture.
has_min_lod
Returns true if a value for the minimum mipmap level has been specified for this texture,...
get_max_lod
Returns the maximum mipmap level that has been specified for this texture.
WrapMode determine_wrap_v() const
Determines the appropriate wrap in the V direction.
get_anisotropic_degree
Returns the anisotropic filtering degree that has been specified for this texture,...
has_color
Returns true if a blend color has been specified for the texture.
has_lod_bias
Returns true if a value for the maximum mipmap level has been specified for this texture,...
get_alpha_filename
Returns the separate file assigned for the alpha channel.
has_priority
Returns true if a priority value for multitexture importance has been specified for the texture,...
get_alpha_fullpath
Returns the full pathname to the alpha file, if it is known; otherwise, returns the same thing as get...
has_rgb_scale
Returns true if an rgb_scale has been specified for the texture, false otherwise.
has_alpha_scale
Returns true if an alpha_scale has been specified for the texture, false otherwise.
get_color
Returns the blend color if one has been specified, or (0, 0, 0, 1) otherwise.
has_max_lod
Returns true if a value for the maximum mipmap level has been specified for this texture,...
get_rgb_scale
Returns the rgb_scale value that has been specified for the texture, or 1 if no rgb_scale value has b...
has_border_color
Returns true if a border color has been specified for the texture.
get_priority
Returns the multitexture importance value that has been specified for the texture,...
has_stage_name
Returns true if a stage name has been explicitly specified for this texture, false otherwise.
has_alpha_filename
Returns true if a separate file for the alpha component has been applied, false otherwise.
get_num_views
Returns the specified number of views specified for the 3-D multiview texture.
get_saved_result
Returns the current setting of the saved_result flag.
The set of named auxiliary data that may or may not be assigned to a vertex.
const LVecBase4d & get_aux() const
Returns the auxiliary data quadruple.
A collection of vertices.
bool has_normals() const
Returns true if any vertex in the pool has a normal defined, false if none of them do.
int remove_unused_vertices()
Removes all vertices from the pool that are not referenced by at least one primitive.
void sort_by_external_index()
Re-orders (and re-numbers) the vertices in this vertex pool so that they appear in increasing order b...
size_type size() const
Returns the number of vertices in the pool.
iterator end() const
Returns an iterator that can be used to traverse through all the vertices in the pool.
void check_overall_color(bool &has_overall_color, LColor &overall_color) const
Scans the vertex pool for different colors on different vertices.
void get_aux_names(vector_string &aux_names) const
Returns the list of auxiliary data names that are defined by any vertices in the pool.
void get_uv_names(vector_string &uv_names, vector_string &uvw_names, vector_string &tbn_names) const
Returns the list of UV names that are defined by any vertices in the pool, as well as the subset of U...
int get_num_dimensions() const
Returns the maximum number of dimensions used by any vertex in the pool.
iterator begin() const
Returns an iterator that can be used to traverse through all the vertices in the pool.
EggVertex * create_unique_vertex(const EggVertex ©)
Creates a new vertex in the pool that is a copy of the indicated one and returns it.
The set of UV's that may or may not be assigned to a vertex.
const LTexCoord3d & get_uvw() const
Returns the texture coordinate triple, if get_num_dimensions() is 3.
Any one-, two-, three-, or four-component vertex, possibly with attributes such as a normal.
int get_index() const
Returns the index number of the vertex within its pool.
int get_external_index() const
Returns the number set by set_external_index().
EggVertexPool * get_pool() const
Returns the vertex pool this vertex belongs in.
void set_external_index(int external_index)
Sets a special index number that is associated with the EggVertex (but is not written to the egg file...
GroupRef::const_iterator gref_end() const
Returns an iterator that can, in conjunction with gref_begin(), be used to traverse the entire set of...
GroupRef::size_type gref_size() const
Returns the number of elements between gref_begin() and gref_end().
const_aux_iterator aux_begin() const
Returns an iterator that allows walking through the complete set of auxiliary data on the vertex.
const_uv_iterator uv_end() const
Returns an iterator that allows walking through the complete set of named UV's on the vertex.
void copy_grefs_from(const EggVertex &other)
Copies all the group references from the other vertex onto this one.
const_uv_iterator uv_begin() const
Returns an iterator that allows walking through the complete set of named UV's on the vertex.
GroupRef::const_iterator gref_begin() const
Returns an iterator that can, in conjunction with gref_end(), be used to traverse the entire set of g...
LVertexd get_pos3() const
Valid if get_num_dimensions() returns 3 or 4.
LPoint4d get_pos4() const
This is always valid, regardless of the value of get_num_dimensions.
const_aux_iterator aux_end() const
Returns an iterator that allows walking through the complete set of auxiliary data on the vertex.
Defines a series of disconnected line segments.
Defines a series of line strips.
A node that holds Geom objects, renderable pieces of geometry.
void add_geom(Geom *geom, const RenderState *state=RenderState::make_empty())
Adds a new Geom to the node.
Defines a series of "patches", fixed-size groupings of vertices that must be processed by a tessellat...
Defines a series of disconnected points.
This is an abstract base class for a family of classes that represent the fundamental geometry primit...
get_num_vertices
Returns the number of indices used by all the primitives in this object.
Defines a series of disconnected triangles.
Defines a series of triangle fans.
Defines a series of triangle strips.
This object describes how the vertex animation, if any, represented in a GeomVertexData is encoded.
void set_panda()
Specifies that vertex animation is to be performed by Panda.
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
This object provides a high-level interface for quickly writing a sequence of numeric values from a v...
bool set_column(int column)
Sets up the writer to use the nth data type of the GeomVertexFormat, numbering from 0.
void set_data1i(int data)
Sets the write row to a particular 1-component value, and advances the write row.
void add_data4(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z, PN_stdfloat w)
Sets the write row to a particular 4-component value, and advances the write row.
void set_row(int row)
Sets the start row to the indicated value.
void add_data3d(double x, double y, double z)
Sets the write row to a particular 3-component value, and advances the write row.
bool has_column() const
Returns true if a valid data type has been successfully set, or false if the data type does not exist...
void set_data4d(double x, double y, double z, double w)
Sets the write row to a particular 4-component value, and advances the write row.
void set_data3d(double x, double y, double z)
Sets the write row to a particular 3-component value, and advances the write row.
void add_data4d(double x, double y, double z, double w)
Sets the write row to a particular 4-component value, and advances the write row.
A container for geometry primitives.
Encodes a string name in a hash table, mapping it to a pointer.
Specifies parameters that may be passed to the loader.
set_texture_num_views
Specifies the expected number of views to load for the texture.
This node is placed at key points within the scene graph to indicate the roots of "models": subtrees ...
A node of this type is created automatically at the root of each model file that is loaded.
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
int get_num_children(Thread *current_thread=Thread::get_current_thread()) const
Returns the number of children of the referenced node.
bool is_empty() const
Returns true if the NodePath contains no nodes.
PandaNode * node() const
Returns the referenced node of the path.
void reparent_to(const NodePath &other, int sort=0, Thread *current_thread=Thread::get_current_thread())
Removes the referenced node of the NodePath from its current parent and attaches it to the referenced...
NodePath get_child(int n, Thread *current_thread=Thread::get_current_thread()) const
Returns a NodePath representing the nth child of the referenced node.
This class is an abstraction for evaluating NURBS curves.
This abstract class defines the interface only for a Nurbs-style curve, with knots and coordinates in...
A Nonuniform Rational B-Spline.
This class is an abstraction for evaluating NURBS surfaces.
A node in the scene graph that can hold an occluder polygon, which must be a rectangle.
set_double_sided
If true, the back-face will also be used to occlude.
get_num_vertices
Returns the number of vertices in the occluder polygon.
void set_vertices(const LPoint3 &v0, const LPoint3 &v1, const LPoint3 &v2, const LPoint3 &v3)
Replaces the four vertices of the occluder polygon.
A basic node of the scene graph or data graph.
virtual bool is_geom_node() const
A simple downcast check.
set_tag
Associates a user-defined value with a user-defined key which is stored on the node.
get_child
Returns the nth child node of this node.
set_transform
Sets the transform that will be applied to this node and below.
void set_effect(const RenderEffect *effect)
Adds the indicated render effect to the scene graph on this node.
void add_stashed(PandaNode *child_node, int sort=0, Thread *current_thread=Thread::get_current_thread())
Adds a new child to the node, directly as a stashed child.
void set_prev_transform(const TransformState *transform, Thread *current_thread=Thread::get_current_thread())
Sets the transform that represents this node's "previous" position, one frame ago,...
void set_attrib(const RenderAttrib *attrib, int override=0)
Adds the indicated render attribute to the scene graph on this node.
get_num_children
Returns the number of child nodes this node has.
A virtual base class for parametric curves.
void set_pos(const LPoint3 &position)
Set this light's position.
void set_radius(PN_stdfloat r)
Set radius of the spherical light volume.
void set_color(const LColor &color)
Set the light's color...
virtual void xform(const LMatrix4 &mat)
Transforms the contents of this node by the indicated matrix, if it means anything to do so.
A node in the scene graph that can hold a Portal Polygon, which is a rectangle.
void add_vertex(const LPoint3 &vertex)
Adds a new vertex to the portal polygon.
get_num_vertices
Returns the number of vertices in the portal polygon.
void clear_vertices()
Resets the vertices of the portal to the empty list.
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
This class draws a visible representation of the NURBS curve stored in its NurbsCurveEvaluator.
Represents a set of settings that indicate how a texture is sampled.
set_wrap_v
This setting determines what happens when the SamplerState is sampled with a V value outside the rang...
set_max_lod
Sets the maximum level of detail that will be used when sampling this texture.
set_anisotropic_degree
Specifies the level of anisotropic filtering to apply to the SamplerState.
set_border_color
Specifies the solid color of the SamplerState's border.
set_wrap_w
The W wrap direction is only used for 3-d SamplerStates.
set_min_lod
Sets the minimum level of detail that will be used when sampling this texture.
set_minfilter
Sets the filtering method that should be used when viewing the SamplerState from a distance.
set_wrap_u
This setting determines what happens when the SamplerState is sampled with a U value outside the rang...
set_magfilter
Sets the filtering method that should be used when viewing the SamplerState up close.
set_lod_bias
Sets the value that will be added to the level of detail when sampling the texture.
A node that automatically cycles through rendering each one of its children according to its frame ra...
This class draws a visible representation of the NURBS surface stored in its NurbsSurfaceEvaluator.
Stores the total set of VertexSliders that the vertices in a particular GeomVertexData object might d...
static SparseArray lower_on(int on_bits)
Returns a SparseArray whose lower on_bits bits are on.
A node that renders only one of its children, according to the user's indication.
Indicates the set of TextureStages and their associated Textures that should be applied to (or remove...
static Texture * load_texture(const Filename &filename, int primary_file_num_channels=0, bool read_mipmaps=false, const LoaderOptions &options=LoaderOptions())
Loads the given filename up into a texture, if it has not already been loaded, and returns the new te...
static Texture * load_cube_map(const Filename &filename_pattern, bool read_mipmaps=false, const LoaderOptions &options=LoaderOptions())
Loads a cube map texture that is specified with a series of 6 pages, numbered 0 through 5.
static Texture * load_3d_texture(const Filename &filename_pattern, bool read_mipmaps=false, const LoaderOptions &options=LoaderOptions())
Loads a 3-D texture that is specified with a series of n pages, all numbered in sequence,...
static TextureStage * get_stage(TextureStage *temp)
Returns a TextureStage pointer that represents the same TextureStage described by temp,...
Defines the properties of a named stage of the multitexture pipeline.
get_default
Returns the default TextureStage that will be used for all texturing that does not name a particular ...
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
set_compression
Requests that this particular Texture be compressed when it is loaded into texture memory.
get_format
Returns the format of the texture, which represents both the semantic meaning of the texels and,...
static bool is_srgb(Format format)
Returns true if the indicated format is in the sRGB color space, false otherwise.
set_format
Changes the format value for the texture components.
get_component_width
Returns the number of bytes stored for each color component of a texel.
set_quality_level
Sets a hint to the renderer about the desired performance / quality tradeoff for this particular text...
get_num_components
Returns the number of color components for each texel of the texture image.
set_default_sampler
This sets the default sampler state for this texture, containing the wrap and filter properties speci...
static void consider_yield()
Possibly suspends the current thread for the rest of the current epoch, if it has run for enough this...
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
A base class for things which need to inherit from both TypedObject and from ReferenceCount.
This is an abstract base class that retains some slider value, which is a linear value that typically...
This is our own Panda specialization on the default STL map.
This is our own Panda specialization on the default STL set.
This is our own Panda specialization on the default STL vector.
This is an iterator adaptor that converts any iterator that returns a pair (e.g.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
string downcase(const string &s)
Returns the input string with all uppercase letters converted to lowercase.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.