111 LODInstance(
EggNode *egg_node);
112 bool operator < (
const LODInstance &other)
const {
113 return _d->_switch_in < other._d->_switch_in;
121 LODInstance(
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;
153 EggLoader(
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;
878 load_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:
1230 tex->
set_format(force_srgb ? Texture::F_sluminance : Texture::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:
1270 tex->
set_format(force_srgb ? Texture::F_srgb : Texture::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:
1288 tex->
set_format(force_srgb ? Texture::F_srgb : Texture::F_rgb8);
1290 case EggTexture::F_rgb5:
1291 tex->
set_format(force_srgb ? Texture::F_srgb : Texture::F_rgb5);
1293 case EggTexture::F_rgb332:
1294 tex->
set_format(force_srgb ? Texture::F_srgb : Texture::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:
1316 tex->
set_format(force_srgb ? Texture::F_srgb_alpha : Texture::F_rgba);
1318 case EggTexture::F_rgbm:
1319 tex->
set_format(force_srgb ? Texture::F_srgb_alpha : Texture::F_rgbm);
1321 case EggTexture::F_rgba12:
1326 tex->
set_format(force_srgb ? Texture::F_srgb_alpha : Texture::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:
1334 tex->
set_format(force_srgb ? Texture::F_srgb_alpha : Texture::F_rgba8);
1336 case EggTexture::F_rgba4:
1337 tex->
set_format(force_srgb ? Texture::F_srgb_alpha : Texture::F_rgba4);
1339 case EggTexture::F_rgba5:
1340 tex->
set_format(force_srgb ? Texture::F_srgb_alpha : Texture::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:
1391 Texture::CompressionMode EggLoader::
1392 convert_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;
1431 SamplerState::WrapMode EggLoader::
1432 convert_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;
1462 make_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);
1655 separate_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);
1694 emulate_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);
2175 check_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));
2747 find_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) {
2778 make_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();
2838 make_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);
2894 make_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())) {
2989 make_collision_plane(temp_group, cnode, flags);
3005 EggGroup::CollideFlags flags) {
3007 EggGroup *geom_group = find_collision_geometry(egg_group, flags);
3010 if (geom_group !=
nullptr) {
3011 create_collision_floor_mesh(cnode, geom_group,flags);
3021 EggGroup::CollideFlags flags) {
3023 EggGroup *geom_group = find_collision_geometry(egg_group, flags);
3024 if (geom_group !=
nullptr) {
3025 EggGroup::const_iterator ci;
3026 for (ci = geom_group->begin(); ci != geom_group->end(); ++ci) {
3027 if ((*ci)->is_of_type(EggPolygon::get_class_type())) {
3028 create_collision_polygons(cnode, DCAST(
EggPolygon, *ci),
3030 }
else if ((*ci)->is_of_type(EggCompositePrimitive::get_class_type())) {
3034 make_collision_polygon(temp_group, cnode, flags);
3049 EggGroup::CollideFlags flags) {
3050 EggGroup *geom_group = find_collision_geometry(egg_group, flags);
3051 if (geom_group !=
nullptr) {
3052 EggGroup::const_iterator ci;
3053 for (ci = geom_group->begin(); ci != geom_group->end(); ++ci) {
3054 if ((*ci)->is_of_type(EggPolygon::get_class_type())) {
3055 create_collision_polygons(cnode, DCAST(
EggPolygon, *ci),
3057 }
else if ((*ci)->is_of_type(EggCompositePrimitive::get_class_type())) {
3061 make_collision_polyset(temp_group, cnode, flags);
3074 EggGroup::CollideFlags flags) {
3078 if (make_sphere(egg_group, flags, center, radius, dummycolor)) {
3081 apply_collision_flags(cssphere, flags);
3082 cssphere->xform(cnode->get_transform()->get_mat());
3093 EggGroup::CollideFlags flags) {
3097 if (make_box(egg_group, flags, transform->get_mat(), min_p, max_p)) {
3100 apply_collision_flags(csbox, flags);
3111 EggGroup::CollideFlags flags) {
3115 if (make_sphere(egg_group, flags, center, radius, dummycolor)) {
3118 apply_collision_flags(cssphere, flags);
3119 cssphere->xform(cnode->get_transform()->get_mat());
3130 EggGroup::CollideFlags flags) {
3131 EggGroup *geom_group = find_collision_geometry(egg_group, flags);
3132 if (geom_group !=
nullptr) {
3136 EggGroup::const_iterator ci;
3137 for (ci = geom_group->begin(); ci != geom_group->end(); ++ci) {
3138 if ((*ci)->is_of_type(EggPrimitive::get_class_type())) {
3140 EggPrimitive::const_iterator pi;
3141 for (pi = prim->begin(); pi != prim->end(); ++pi) {
3142 vertices.insert(*pi);
3149 size_t num_vertices = vertices.size();
3150 if (num_vertices != 0) {
3152 vpos.reserve(num_vertices);
3154 LPoint3d center(0.0, 0.0, 0.0);
3156 for (vi = vertices.begin(); vi != vertices.end(); ++vi) {
3158 const LPoint3d &pos = vtx->
get_pos3();
3159 vpos.push_back(pos);
3162 center /= (double)num_vertices;
3168 double radius2 = 0.0;
3169 LPoint3d far_a = center;
3170 for (i = 0; i < num_vertices; i++) {
3171 double dist2 = (vpos[i] - center).length_squared();
3172 if (dist2 > radius2) {
3182 LPoint3d far_b = center;
3183 for (i = 0; i < num_vertices; i++) {
3184 double dist2 = (vpos[i] - far_a).length_squared();
3185 if (dist2 > radius2) {
3202 LPoint3d cap_a_center(0.0, 0.0, 0.0);
3203 LPoint3d cap_b_center(0.0, 0.0, 0.0);
3209 double center_length = (far_a - far_b).length() / 4.0;
3210 double center_length2 = center_length * center_length;
3212 for (i = 0; i < num_vertices; i++) {
3213 double dist2 = (vpos[i] - center).length_squared();
3214 if (dist2 > center_length2) {
3217 double dist_a2 = (vpos[i] - far_a).length_squared();
3218 double dist_b2 = (vpos[i] - far_b).length_squared();
3219 if (dist_a2 < dist_b2) {
3221 cap_a_center += vpos[i];
3225 cap_b_center += vpos[i];
3231 if (num_a > 0 && num_b > 0) {
3232 cap_a_center /= (double)num_a;
3233 cap_b_center /= (double)num_b;
3237 LVector3d axis = cap_b_center - cap_a_center;
3242 if (IS_THRESHOLD_ZERO(axis[0], 0.01)) {
3245 if (IS_THRESHOLD_ZERO(axis[1], 0.01)) {
3248 if (IS_THRESHOLD_ZERO(axis[2], 0.01)) {
3260 look_at(mat, axis, LVector3d(0.0, 0.0, 1.0), CS_zup_right);
3261 mat.set_row(3, center);
3263 inv_mat.invert_from(mat);
3265 for (i = 0; i < num_vertices; i++) {
3266 vpos[i] = vpos[i] * inv_mat;
3269 double max_radius2 = 0.0;
3272 for (i = 0; i < num_vertices; i++) {
3273 LVector2d v(vpos[i][0], vpos[i][2]);
3274 double radius2 = v.length_squared();
3275 if (radius2 > max_radius2) {
3276 max_radius2 = radius2;
3286 for (i = 0; i < num_vertices; i++) {
3287 LVector2d v(vpos[i][0], vpos[i][2]);
3288 double radius2 = v.length_squared();
3290 if (vpos[i][1] < min_y) {
3293 double factor = sqrt(max_radius2 - radius2);
3294 min_y = min(min_y, vpos[i][1] + factor);
3296 }
else if (vpos[i][1] > max_y) {
3297 double factor = sqrt(max_radius2 - radius2);
3298 max_y = max(max_y, vpos[i][1] - factor);
3302 double length = max_y - min_y;
3303 double radius = sqrt(max_radius2);
3306 LVector3d half = axis * (length / 2.0);
3307 LPoint3d point_a = center - half;
3308 LPoint3d point_b = center + half;
3311 new CollisionCapsule(LCAST(PN_stdfloat, point_a), LCAST(PN_stdfloat, point_b),
3313 apply_collision_flags(cscapsule, flags);
3314 cscapsule->xform(cnode->get_transform()->get_mat());
3326 apply_collision_flags(
CollisionSolid *solid, EggGroup::CollideFlags flags) {
3327 if ((flags & EggGroup::CF_intangible) != 0) {
3330 if ((flags & EggGroup::CF_level) != 0) {
3340 find_collision_geometry(
EggGroup *egg_group, EggGroup::CollideFlags flags) {
3341 if ((flags & EggGroup::CF_descend) != 0) {
3348 EggGroup::const_iterator ci;
3349 for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
3350 if ((*ci)->is_of_type(EggPolygon::get_class_type())) {
3358 for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
3359 if ((*ci)->is_of_type(EggGroup::get_class_type())) {
3361 if (child_group->get_cs_type() == egg_group->get_cs_type()) {
3378 <<
"Ignoring degenerate collision plane in " << parent_group->get_name()
3384 egg2pg_cat.warning()
3385 <<
"Non-planar polygon defining collision plane in "
3386 << parent_group->get_name()
3391 if (!egg_poly->empty()) {
3392 EggPolygon::const_iterator vi;
3393 vi = egg_poly->begin();
3395 LVertexd vert = (*vi)->get_pos3();
3396 vertices.push_back(LCAST(PN_stdfloat, vert));
3398 LVertexd last_vert = vert;
3400 while (vi != egg_poly->end()) {
3401 vert = (*vi)->get_pos3();
3402 if (!vert.almost_equal(last_vert)) {
3403 vertices.push_back(LCAST(PN_stdfloat, vert));
3411 if (vertices.size() < 3) {
3414 LPlane plane(vertices[0], vertices[1], vertices[2]);
3425 EggGroup::CollideFlags flags) {
3431 <<
"Ignoring degenerate collision polygon in "
3432 << parent_group->get_name()
3437 if (group->size() != 1) {
3439 <<
"Triangulating concave or non-planar collision polygon in "
3440 << parent_group->get_name()
3444 EggGroup::iterator ci;
3445 for (ci = group->begin(); ci != group->end(); ++ci) {
3449 if (!poly->empty()) {
3450 EggPolygon::const_iterator vi;
3453 LVertexd vert = (*vi)->get_pos3();
3454 vertices.push_back(LCAST(PN_stdfloat, vert));
3456 LVertexd last_vert = vert;
3458 while (vi != poly->end()) {
3459 vert = (*vi)->get_pos3();
3460 if (!vert.almost_equal(last_vert)) {
3461 vertices.push_back(LCAST(PN_stdfloat, vert));
3469 if (vertices.size() >= 3) {
3470 const LVertex *vertices_begin = &vertices[0];
3471 const LVertex *vertices_end = vertices_begin + vertices.size();
3474 if (cspoly->is_valid()) {
3475 apply_collision_flags(cspoly, flags);
3476 cspoly->xform(cnode->get_transform()->get_mat());
3490 EggGroup::CollideFlags flags) {
3494 pool.local_object();
3495 EggGroup::const_iterator egi;
3496 for (egi = parent_group->begin(); egi != parent_group->end(); ++egi) {
3497 if ((*egi)->is_of_type(EggPolygon::get_class_type())) {
3501 <<
"Ignoring degenerate collision polygon in "
3502 << parent_group->get_name()
3509 if(group->size() == 0) {
3511 <<
"empty collision solid\n";
3517 EggGroup::iterator ci;
3518 for (ci = group->begin(); ci != group->end(); ++ci) {
3520 if (poly->get_num_vertices() == 3) {
3521 CollisionFloorMesh::TriangleIndices tri;
3524 tri.p1=pool.create_unique_vertex(*poly->
get_vertex(0))->get_index();
3525 tri.p2=pool.create_unique_vertex(*poly->
get_vertex(1))->get_index();
3526 tri.p3=pool.create_unique_vertex(*poly->
get_vertex(2))->get_index();
3528 triangles.push_back(tri);
3529 }
else if (poly->get_num_vertices() == 4) {
3532 CollisionFloorMesh::TriangleIndices tri;
3533 CollisionFloorMesh::TriangleIndices tri2;
3536 tri.p1=pool.create_unique_vertex(*poly->
get_vertex(0))->get_index();
3537 tri.p2=pool.create_unique_vertex(*poly->
get_vertex(1))->get_index();
3538 tri.p3=pool.create_unique_vertex(*poly->
get_vertex(2))->get_index();
3540 triangles.push_back(tri);
3545 tri2.p3=pool.create_unique_vertex(*poly->
get_vertex(3))->get_index();
3548 triangles.push_back(tri2);
3557 for (vi = pool.begin(); vi != pool.end(); vi++) {
3558 csfloor->add_vertex(LCAST(PN_stdfloat,(*vi)->get_pos3()));
3563 for (ti = triangles.begin(); ti != triangles.end(); ti++) {
3564 CollisionFloorMesh::TriangleIndices triangle = *ti;
3565 csfloor->add_triangle(triangle.p1, triangle.p2, triangle.p3);
3567 csfloor->xform(cnode->get_transform()->get_mat());
3581 DeferredNodes::const_iterator dni;
3582 dni = _deferred_nodes.find(node);
3584 if (dni != _deferred_nodes.end()) {
3590 next_prop.apply_to_node(node);
3593 for (
int i = 0; i < num_children; i++) {
3594 apply_deferred_nodes(node->
get_child(i), next_prop);
3607 expand_all_object_types(
EggNode *egg_node) {
3608 if (egg_node->
is_of_type(EggGroup::get_class_type())) {
3611 if (egg_group->get_num_object_types() != 0) {
3614 if (!expand_object_types(egg_group, expanded, expanded_history)) {
3622 if (egg_node->
is_of_type(EggGroupNode::get_class_type())) {
3624 EggGroupNode::const_iterator ci;
3625 ci = egg_group_node->begin();
3626 while (ci != egg_group_node->end()) {
3627 EggGroupNode::const_iterator cnext = ci;
3630 if (!expand_all_object_types(*ci)) {
3632 egg_group_node->erase(ci);
3653 int num_object_types = egg_group->get_num_object_types();
3656 vector_string object_types;
3658 for (i = 0; i < num_object_types; i++) {
3659 object_types.push_back(egg_group->get_object_type(i));
3661 egg_group->clear_object_types();
3663 for (i = 0; i < num_object_types; i++) {
3664 string object_type = object_types[i];
3668 if (!new_expanded.insert(object_type).second) {
3670 <<
"Cycle in ObjectType expansions:\n";
3672 for (pi = expanded_history.begin();
3673 pi != expanded_history.end();
3675 egg2pg_cat.error(
false)
3678 egg2pg_cat.error(
false) << object_type <<
"\n";
3684 new_expanded_history.push_back(object_type);
3686 if (!do_expand_object_type(egg_group, new_expanded,
3687 new_expanded_history, object_type)) {
3703 const string &object_type) {
3708 (
"egg-object-type-" +
downcase(object_type),
"");
3709 string egg_syntax = egg_object_type;
3711 if (!egg_object_type.has_value()) {
3714 if (cmp_nocase_uh(object_type,
"barrier") == 0) {
3715 egg_syntax =
"<Collide> { Polyset descend }";
3717 }
else if (cmp_nocase_uh(object_type,
"solidpoly") == 0) {
3718 egg_syntax =
"<Collide> { Polyset descend solid }";
3720 }
else if (cmp_nocase_uh(object_type,
"turnstile") == 0) {
3721 egg_syntax =
"<Collide> { Polyset descend turnstile }";
3723 }
else if (cmp_nocase_uh(object_type,
"sphere") == 0) {
3724 egg_syntax =
"<Collide> { Sphere descend }";
3726 }
else if (cmp_nocase_uh(object_type,
"tube") == 0) {
3727 egg_syntax =
"<Collide> { Tube descend }";
3729 }
else if (cmp_nocase_uh(object_type,
"trigger") == 0) {
3730 egg_syntax =
"<Collide> { Polyset descend intangible }";
3732 }
else if (cmp_nocase_uh(object_type,
"trigger_sphere") == 0) {
3733 egg_syntax =
"<Collide> { Sphere descend intangible }";
3735 }
else if (cmp_nocase_uh(object_type,
"eye_trigger") == 0) {
3736 egg_syntax =
"<Collide> { Polyset descend intangible center }";
3738 }
else if (cmp_nocase_uh(object_type,
"bubble") == 0) {
3739 egg_syntax =
"<Collide> { Sphere keep descend }";
3741 }
else if (cmp_nocase_uh(object_type,
"ghost") == 0) {
3742 egg_syntax =
"<Scalar> collide-mask { 0 }";
3744 }
else if (cmp_nocase_uh(object_type,
"dcs") == 0) {
3745 egg_syntax =
"<DCS> { 1 }";
3747 }
else if (cmp_nocase_uh(object_type,
"model") == 0) {
3748 egg_syntax =
"<Model> { 1 }";
3750 }
else if (cmp_nocase_uh(object_type,
"none") == 0) {
3754 }
else if (cmp_nocase_uh(object_type,
"backstage") == 0) {
3760 <<
"Unknown ObjectType " << object_type <<
"\n";
3762 egg2pg_cat.debug() <<
"returning true\n";
3767 if (!egg_syntax.empty()) {
3768 if (!egg_group->
parse_egg(egg_syntax)) {
3770 <<
"Error while parsing definition for ObjectType "
3771 << object_type <<
"\n";
3777 if (egg_group->get_num_object_types() != 0) {
3778 if (!expand_object_types(egg_group, expanded, expanded_history)) {
3792 TextureStage::CombineMode EggLoader::
3794 EggTexture::CombineChannel channel) {
3795 switch (egg_tex->get_combine_mode(channel)) {
3796 case EggTexture::CM_unspecified:
3799 case EggTexture::CM_modulate:
3800 return TextureStage::CM_modulate;
3802 case EggTexture::CM_replace:
3803 return TextureStage::CM_replace;
3805 case EggTexture::CM_add:
3806 return TextureStage::CM_add;
3808 case EggTexture::CM_add_signed:
3809 return TextureStage::CM_add_signed;
3811 case EggTexture::CM_interpolate:
3812 return TextureStage::CM_interpolate;
3814 case EggTexture::CM_subtract:
3815 return TextureStage::CM_subtract;
3817 case EggTexture::CM_dot3_rgb:
3818 return TextureStage::CM_dot3_rgb;
3820 case EggTexture::CM_dot3_rgba:
3821 return TextureStage::CM_dot3_rgba;
3824 return TextureStage::CM_undefined;
3831 TextureStage::CombineSource EggLoader::
3832 get_combine_source(
const EggTexture *egg_tex,
3833 EggTexture::CombineChannel channel,
int n) {
3834 switch (egg_tex->get_combine_source(channel, n)) {
3835 case EggTexture::CS_unspecified:
3840 return TextureStage::CS_previous;
3842 return TextureStage::CS_texture;
3844 return TextureStage::CS_constant;
3848 case EggTexture::CS_texture:
3849 return TextureStage::CS_texture;
3851 case EggTexture::CS_constant:
3852 return TextureStage::CS_constant;
3854 case EggTexture::CS_primary_color:
3855 return TextureStage::CS_primary_color;
3857 case EggTexture::CS_previous:
3858 return TextureStage::CS_previous;
3860 case EggTexture::CS_constant_color_scale:
3861 return TextureStage::CS_constant_color_scale;
3863 case EggTexture::CS_last_saved_result:
3864 return TextureStage::CS_last_saved_result;
3867 return TextureStage::CS_undefined;
3874 TextureStage::CombineOperand EggLoader::
3875 get_combine_operand(
const EggTexture *egg_tex,
3876 EggTexture::CombineChannel channel,
int n) {
3877 switch (egg_tex->get_combine_operand(channel, n)) {
3878 case EggTexture::CO_unspecified:
3879 if (channel == EggTexture::CC_rgb) {
3882 return n < 2 ? TextureStage::CO_src_color : TextureStage::CO_src_alpha;
3885 return TextureStage::CO_src_alpha;
3888 case EggTexture::CO_src_color:
3889 return TextureStage::CO_src_color;
3891 case EggTexture::CO_one_minus_src_color:
3892 return TextureStage::CO_one_minus_src_color;
3894 case EggTexture::CO_src_alpha:
3895 return TextureStage::CO_src_alpha;
3897 case EggTexture::CO_one_minus_src_alpha:
3898 return TextureStage::CO_one_minus_src_alpha;
3901 return TextureStage::CO_undefined;
3908 ColorBlendAttrib::Mode EggLoader::
3909 get_color_blend_mode(EggGroup::BlendMode mode) {
3911 case EggGroup::BM_unspecified:
3912 case EggGroup::BM_none:
3913 return ColorBlendAttrib::M_none;
3914 case EggGroup::BM_add:
3915 return ColorBlendAttrib::M_add;
3916 case EggGroup::BM_subtract:
3917 return ColorBlendAttrib::M_subtract;
3918 case EggGroup::BM_inv_subtract:
3919 return ColorBlendAttrib::M_inv_subtract;
3920 case EggGroup::BM_min:
3921 return ColorBlendAttrib::M_min;
3922 case EggGroup::BM_max:
3923 return ColorBlendAttrib::M_max;
3926 return ColorBlendAttrib::M_none;
3933 ColorBlendAttrib::Operand EggLoader::
3934 get_color_blend_operand(EggGroup::BlendOperand operand) {
3936 case EggGroup::BO_zero:
3937 return ColorBlendAttrib::O_zero;
3938 case EggGroup::BO_unspecified:
3939 case EggGroup::BO_one:
3940 return ColorBlendAttrib::O_one;
3941 case EggGroup::BO_incoming_color:
3942 return ColorBlendAttrib::O_incoming_color;
3943 case EggGroup::BO_one_minus_incoming_color:
3944 return ColorBlendAttrib::O_one_minus_incoming_color;
3945 case EggGroup::BO_fbuffer_color:
3946 return ColorBlendAttrib::O_fbuffer_color;
3947 case EggGroup::BO_one_minus_fbuffer_color:
3948 return ColorBlendAttrib::O_one_minus_fbuffer_color;
3949 case EggGroup::BO_incoming_alpha:
3950 return ColorBlendAttrib::O_incoming_alpha;
3951 case EggGroup::BO_one_minus_incoming_alpha:
3952 return ColorBlendAttrib::O_one_minus_incoming_alpha;
3953 case EggGroup::BO_fbuffer_alpha:
3954 return ColorBlendAttrib::O_fbuffer_alpha;
3955 case EggGroup::BO_one_minus_fbuffer_alpha:
3956 return ColorBlendAttrib::O_one_minus_fbuffer_alpha;
3957 case EggGroup::BO_constant_color:
3958 return ColorBlendAttrib::O_constant_color;
3959 case EggGroup::BO_one_minus_constant_color:
3960 return ColorBlendAttrib::O_one_minus_constant_color;
3961 case EggGroup::BO_constant_alpha:
3962 return ColorBlendAttrib::O_constant_alpha;
3963 case EggGroup::BO_one_minus_constant_alpha:
3964 return ColorBlendAttrib::O_one_minus_constant_alpha;
3965 case EggGroup::BO_incoming_color_saturate:
3966 return ColorBlendAttrib::O_incoming_color_saturate;
3967 case EggGroup::BO_color_scale:
3968 return ColorBlendAttrib::O_color_scale;
3969 case EggGroup::BO_one_minus_color_scale:
3970 return ColorBlendAttrib::O_one_minus_color_scale;
3971 case EggGroup::BO_alpha_scale:
3972 return ColorBlendAttrib::O_alpha_scale;
3973 case EggGroup::BO_one_minus_alpha_scale:
3974 return ColorBlendAttrib::O_one_minus_alpha_scale;
3977 return ColorBlendAttrib::O_zero;
3983 bool EggLoader::VertexPoolTransform::
3984 operator < (
const EggLoader::VertexPoolTransform &other)
const {
3985 if (_vertex_pool != other._vertex_pool) {
3986 return _vertex_pool < other._vertex_pool;
3988 int compare = _transform.compare_to(other._transform, 0.001);
3993 if (_bake_in_uvs.size() != other._bake_in_uvs.size()) {
3994 return _bake_in_uvs.size() < other._bake_in_uvs.size();
3997 BakeInUVs::const_iterator ai, bi;
3998 ai = _bake_in_uvs.begin();
3999 bi = other._bake_in_uvs.begin();
4000 while (ai != _bake_in_uvs.end()) {
4001 nassertr(bi != other._bake_in_uvs.end(),
false);
4002 if ((*ai) != (*bi)) {
4003 return (*ai) < (*bi);
4008 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.
PT(TextureStage) EggLoader
Creates a TextureStage object suitable for rendering the indicated texture.
CPT(TransformState) EggLoader
Creates a TransformState object corresponding to the indicated EggTransform.
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.