111 LODInstance(EggNode *egg_node);
112 bool operator < (
const LODInstance &other)
const {
113 return _d->_switch_in < other._d->_switch_in;
117 const EggSwitchConditionDistance *_d;
121LODInstance(
EggNode *egg_node) {
122 nassertv(egg_node !=
nullptr);
123 _egg_node = egg_node;
127 EggGroup *egg_group = DCAST(EggGroup, egg_node);
128 nassertv(egg_group->has_lod());
129 const EggSwitchCondition &sw = egg_group->get_lod();
132 _d = DCAST(EggSwitchConditionDistance, &sw);
143 _data->set_coordinate_system(egg_coordinate_system);
145 _dynamic_override =
false;
146 _dynamic_override_char_maker =
nullptr;
153EggLoader(
const EggData *data) :
157 _dynamic_override =
false;
158 _dynamic_override_char_maker =
nullptr;
167 _deferred_nodes.clear();
171 if (!expand_all_object_types(_data)) {
179 _data->clear_connected_shading();
180 _data->remove_unused_vertices(
true);
181 _data->get_connected_shading();
182 _data->unify_attributes(
true, egg_flat_shading,
true);
187 _data->clear_connected_shading();
188 _data->remove_unused_vertices(
true);
189 _data->get_connected_shading();
194 separate_switches(_data);
196 if (egg_emulate_bface) {
197 emulate_bface(_data);
201 _data->remove_invalid_primitives(
true);
202 EggBinner binner(*
this);
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);
218 apply_deferred_nodes(_root, DeferredNodeProperty());
228 ExtraNodes::const_iterator di;
229 for (di = _decals.begin(); di != _decals.end(); ++di) {
230 PandaNode *node = (*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);
315 const EggRenderState *render_state;
316 DCAST_INTO_V(render_state, first_prim->get_user_data(EggRenderState::get_class_type()));
318 if (render_state->_hidden && egg_suppress_hidden) {
326 EggVertexPools vertex_pools;
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;
360 vertex_pool->check_overall_color(has_overall_color, overall_color);
361 if (!egg_flat_colors) {
365 has_overall_color =
false;
372 blend_table = make_blend_table(vertex_pool, egg_bin, character_maker);
379 vertex_pool->sort_by_external_index();
384 UniquePrimitives unique_primitives;
385 Primitives primitives;
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) {
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))) {
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;
604 PT(GeomPrimitive) primitive =
new GeomLines(Geom::UH_static);
606 PT(GeomVertexData) vertex_data =
607 new GeomVertexData(vertex_pool->get_name(), format, Geom::UH_static);
609 GeomVertexWriter vertex(vertex_data, InternalName::get_vertex());
610 GeomVertexWriter color(vertex_data, InternalName::get_color());
612 EggVertexPool::const_iterator vi;
613 for (vi = vertex_pool->begin(); vi != vertex_pool->end(); ++vi) {
614 EggVertex *vert = (*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();
627 EggVertex::const_uv_iterator uvi;
629 EggVertexUV *uv_obj = (*uvi);
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);
669 PT(NurbsCurveEvaluator) nurbs = ::make_nurbs_curve(egg_curve, mat);
670 if (nurbs ==
nullptr) {
694 PT(RopeNode) rope =
new RopeNode(egg_curve->get_name());
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));
704 const EggRenderState *render_state;
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()) {
734 const LMatrix4d &mat) {
735 assert(parent !=
nullptr);
738 PT(ParametricCurve) curve;
739 curve =
new NurbsCurve;
741 NurbsCurveInterface *nurbs = curve->get_nurbs_interface();
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";
806 const LMatrix4d &mat) {
807 assert(parent !=
nullptr);
810 PT(NurbsSurfaceEvaluator) nurbs = ::make_nurbs_surface(egg_surface, mat);
811 if (nurbs ==
nullptr) {
816 PT(SheetNode) sheet =
new SheetNode(egg_surface->get_name());
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));
831 const EggRenderState *render_state;
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()) {
857 EggTextureCollection tc;
860 EggTextureCollection::iterator ti;
861 for (ti = tc.begin(); ti != tc.end(); ++ti) {
862 PT_EggTexture egg_tex = (*ti);
865 if (load_texture(def, egg_tex)) {
868 _textures[egg_tex] = def;
878load_texture(TextureDef &def,
EggTexture *egg_tex) {
879 if (egg_tex->get_env_type() == EggTexture::ET___occlusion) {
884 int wanted_channels = 0;
885 bool wanted_alpha =
false;
886 switch (egg_tex->get_format()) {
887 case EggTexture::F_red:
888 case EggTexture::F_green:
889 case EggTexture::F_blue:
890 case EggTexture::F_alpha:
891 case EggTexture::F_luminance:
893 wanted_alpha =
false;
896 case EggTexture::F_luminance_alpha:
897 case EggTexture::F_luminance_alphamask:
902 case EggTexture::F_rgb:
903 case EggTexture::F_rgb12:
904 case EggTexture::F_rgb8:
905 case EggTexture::F_rgb5:
906 case EggTexture::F_rgb332:
907 case EggTexture::F_srgb:
909 wanted_alpha =
false;
912 case EggTexture::F_rgba:
913 case EggTexture::F_rgbm:
914 case EggTexture::F_rgba12:
915 case EggTexture::F_rgba8:
916 case EggTexture::F_rgba4:
917 case EggTexture::F_rgba5:
918 case EggTexture::F_srgb_alpha:
923 case EggTexture::F_unspecified:
930 if (_record !=
nullptr) {
938 LoaderOptions options;
939 if (egg_preload_simple_textures) {
940 options.set_texture_flags(options.get_texture_flags() | LoaderOptions::TF_preload_simple);
943 if (!egg_ignore_filters && !egg_ignore_mipmaps) {
944 switch (egg_tex->get_minfilter()) {
945 case EggTexture::FT_nearest:
946 case EggTexture::FT_linear:
947 case EggTexture::FT_unspecified:
950 case EggTexture::FT_nearest_mipmap_nearest:
951 case EggTexture::FT_linear_mipmap_nearest:
952 case EggTexture::FT_nearest_mipmap_linear:
953 case EggTexture::FT_linear_mipmap_linear:
954 options.set_texture_flags(options.get_texture_flags() | LoaderOptions::TF_generate_mipmaps);
959 options.set_texture_flags(options.get_texture_flags() | LoaderOptions::TF_multiview);
966 if (egg_tex->get_compression_mode() == EggTexture::CM_on) {
967 options.set_texture_flags(options.get_texture_flags() | LoaderOptions::TF_allow_compression);
971 switch (egg_tex->get_texture_type()) {
972 case EggTexture::TT_unspecified:
973 case EggTexture::TT_1d_texture:
974 options.set_texture_flags(options.get_texture_flags() | LoaderOptions::TF_allow_1d);
977 case EggTexture::TT_2d_texture:
991 case EggTexture::TT_3d_texture:
996 case EggTexture::TT_cube_map:
1002 if (tex ==
nullptr) {
1016 TypedReferenceCount *aux = tex->get_aux_data(
"egg");
1017 if (aux !=
nullptr &&
1018 aux->
is_of_type(EggTexture::get_class_type())) {
1019 EggTexture *aux_egg_tex = DCAST(EggTexture, aux);
1021 if (aux_egg_tex->
get_alpha_mode() != EggTexture::AM_unspecified) {
1024 if (aux_egg_tex->get_format() != EggTexture::F_unspecified) {
1025 egg_tex->set_format(aux_egg_tex->get_format());
1027 if (aux_egg_tex->get_minfilter() != EggTexture::FT_unspecified) {
1028 egg_tex->set_minfilter(aux_egg_tex->get_minfilter());
1030 if (aux_egg_tex->get_magfilter() != EggTexture::FT_unspecified) {
1031 egg_tex->set_magfilter(aux_egg_tex->get_magfilter());
1038 apply_texture_attributes(tex, egg_tex);
1041 PT(TextureStage) stage = make_texture_stage(egg_tex);
1044 def._egg_tex = egg_tex;
1055 if (egg_tex->get_compression_mode() != EggTexture::CM_default) {
1056 tex->
set_compression(convert_compression_mode(egg_tex->get_compression_mode()));
1059 SamplerState sampler;
1065 if (wrap_u != EggTexture::WM_unspecified) {
1066 sampler.
set_wrap_u(convert_wrap_mode(wrap_u));
1068 if (wrap_v != EggTexture::WM_unspecified) {
1069 sampler.
set_wrap_v(convert_wrap_mode(wrap_v));
1071 if (wrap_w != EggTexture::WM_unspecified) {
1072 sampler.
set_wrap_w(convert_wrap_mode(wrap_w));
1079 switch (egg_tex->get_minfilter()) {
1080 case EggTexture::FT_nearest:
1084 case EggTexture::FT_linear:
1085 if (egg_ignore_filters) {
1086 egg2pg_cat.warning()
1087 <<
"Ignoring minfilter request\n";
1094 case EggTexture::FT_nearest_mipmap_nearest:
1095 if (egg_ignore_filters) {
1096 egg2pg_cat.warning()
1097 <<
"Ignoring minfilter request\n";
1099 }
else if (egg_ignore_mipmaps) {
1100 egg2pg_cat.warning()
1101 <<
"Ignoring mipmap request\n";
1104 sampler.
set_minfilter(SamplerState::FT_nearest_mipmap_nearest);
1108 case EggTexture::FT_linear_mipmap_nearest:
1109 if (egg_ignore_filters) {
1110 egg2pg_cat.warning()
1111 <<
"Ignoring minfilter request\n";
1113 }
else if (egg_ignore_mipmaps) {
1114 egg2pg_cat.warning()
1115 <<
"Ignoring mipmap request\n";
1118 sampler.
set_minfilter(SamplerState::FT_linear_mipmap_nearest);
1122 case EggTexture::FT_nearest_mipmap_linear:
1123 if (egg_ignore_filters) {
1124 egg2pg_cat.warning()
1125 <<
"Ignoring minfilter request\n";
1127 }
else if (egg_ignore_mipmaps) {
1128 egg2pg_cat.warning()
1129 <<
"Ignoring mipmap request\n";
1132 sampler.
set_minfilter(SamplerState::FT_nearest_mipmap_linear);
1136 case EggTexture::FT_linear_mipmap_linear:
1137 if (egg_ignore_filters) {
1138 egg2pg_cat.warning()
1139 <<
"Ignoring minfilter request\n";
1141 }
else if (egg_ignore_mipmaps) {
1142 egg2pg_cat.warning()
1143 <<
"Ignoring mipmap request\n";
1146 sampler.
set_minfilter(SamplerState::FT_linear_mipmap_linear);
1150 case EggTexture::FT_unspecified:
1154 switch (egg_tex->get_magfilter()) {
1155 case EggTexture::FT_nearest:
1156 case EggTexture::FT_nearest_mipmap_nearest:
1157 case EggTexture::FT_nearest_mipmap_linear:
1161 case EggTexture::FT_linear:
1162 case EggTexture::FT_linear_mipmap_nearest:
1163 case EggTexture::FT_linear_mipmap_linear:
1164 if (egg_ignore_filters) {
1165 egg2pg_cat.warning()
1166 <<
"Ignoring magfilter request\n";
1173 case EggTexture::FT_unspecified:
1195 bool force_srgb =
false;
1196 if (egg_force_srgb_textures) {
1197 switch (egg_tex->get_env_type()) {
1198 case EggTexture::ET_unspecified:
1199 case EggTexture::ET_modulate:
1200 case EggTexture::ET_decal:
1201 case EggTexture::ET_blend:
1202 case EggTexture::ET_replace:
1203 case EggTexture::ET_add:
1204 case EggTexture::ET_blend_color_scale:
1205 case EggTexture::ET_modulate_glow:
1206 case EggTexture::ET_modulate_gloss:
1208 if (egg2pg_cat.is_debug()) {
1210 <<
"Enabling sRGB format on texture " << egg_tex->get_name() <<
"\n";
1220 switch (egg_tex->get_format()) {
1221 case EggTexture::F_red:
1224 case EggTexture::F_green:
1227 case EggTexture::F_blue:
1230 case EggTexture::F_alpha:
1233 case EggTexture::F_luminance:
1234 tex->
set_format(force_srgb ? Texture::F_sluminance : Texture::F_luminance);
1238 egg2pg_cat.warning()
1239 <<
"Ignoring inappropriate format " << egg_tex->get_format()
1240 <<
" for 1-component texture " << egg_tex->get_name() <<
"\n";
1242 case EggTexture::F_unspecified:
1250 switch (egg_tex->get_format()) {
1251 case EggTexture::F_luminance_alpha:
1252 tex->
set_format(force_srgb ? Texture::F_sluminance_alpha : Texture::F_luminance_alpha);
1255 case EggTexture::F_luminance_alphamask:
1256 tex->
set_format(force_srgb ? Texture::F_sluminance_alpha : Texture::F_luminance_alphamask);
1260 egg2pg_cat.warning()
1261 <<
"Ignoring inappropriate format " << egg_tex->get_format()
1262 <<
" for 2-component texture " << egg_tex->get_name() <<
"\n";
1264 case EggTexture::F_unspecified:
1266 tex->
set_format(Texture::F_sluminance_alpha);
1272 switch (egg_tex->get_format()) {
1273 case EggTexture::F_rgb:
1274 tex->
set_format(force_srgb ? Texture::F_srgb : Texture::F_rgb);
1276 case EggTexture::F_rgb12:
1283 egg2pg_cat.warning()
1284 <<
"Ignoring inappropriate format " << egg_tex->get_format()
1285 <<
" for 8-bit texture " << egg_tex->get_name() <<
"\n";
1288 case EggTexture::F_rgb8:
1289 case EggTexture::F_rgba8:
1292 tex->
set_format(force_srgb ? Texture::F_srgb : Texture::F_rgb8);
1294 case EggTexture::F_rgb5:
1295 tex->
set_format(force_srgb ? Texture::F_srgb : Texture::F_rgb5);
1297 case EggTexture::F_rgb332:
1298 tex->
set_format(force_srgb ? Texture::F_srgb : Texture::F_rgb332);
1300 case EggTexture::F_srgb:
1301 case EggTexture::F_srgb_alpha:
1306 egg2pg_cat.warning()
1307 <<
"Ignoring inappropriate format " << egg_tex->get_format()
1308 <<
" for 3-component texture " << egg_tex->get_name() <<
"\n";
1310 case EggTexture::F_unspecified:
1318 switch (egg_tex->get_format()) {
1319 case EggTexture::F_rgba:
1320 tex->
set_format(force_srgb ? Texture::F_srgb_alpha : Texture::F_rgba);
1322 case EggTexture::F_rgbm:
1323 tex->
set_format(force_srgb ? Texture::F_srgb_alpha : Texture::F_rgbm);
1325 case EggTexture::F_rgba12:
1330 tex->
set_format(force_srgb ? Texture::F_srgb_alpha : Texture::F_rgba12);
1332 egg2pg_cat.warning()
1333 <<
"Ignoring inappropriate format " << egg_tex->get_format()
1334 <<
" for 8-bit texture " << egg_tex->get_name() <<
"\n";
1337 case EggTexture::F_rgba8:
1338 tex->
set_format(force_srgb ? Texture::F_srgb_alpha : Texture::F_rgba8);
1340 case EggTexture::F_rgba4:
1341 tex->
set_format(force_srgb ? Texture::F_srgb_alpha : Texture::F_rgba4);
1343 case EggTexture::F_rgba5:
1344 tex->
set_format(force_srgb ? Texture::F_srgb_alpha : Texture::F_rgba5);
1346 case EggTexture::F_srgb_alpha:
1351 egg2pg_cat.warning()
1352 <<
"Ignoring inappropriate format " << egg_tex->get_format()
1353 <<
" for 4-component texture " << egg_tex->get_name() <<
"\n";
1355 case EggTexture::F_unspecified:
1363 if (force_srgb && tex->
get_format() != Texture::F_alpha &&
1365 egg2pg_cat.warning()
1366 <<
"Unable to enable sRGB format on texture " << egg_tex->get_name()
1367 <<
" with specified format " << egg_tex->get_format() <<
"\n";
1370 switch (egg_tex->get_quality_level()) {
1371 case EggTexture::QL_unspecified:
1372 case EggTexture::QL_default:
1376 case EggTexture::QL_fastest:
1380 case EggTexture::QL_normal:
1384 case EggTexture::QL_best:
1395Texture::CompressionMode EggLoader::
1396convert_compression_mode(EggTexture::CompressionMode compression_mode)
const {
1397 switch (compression_mode) {
1398 case EggTexture::CM_off:
1399 return Texture::CM_off;
1401 case EggTexture::CM_on:
1402 return Texture::CM_on;
1404 case EggTexture::CM_fxt1:
1405 return Texture::CM_fxt1;
1407 case EggTexture::CM_dxt1:
1408 return Texture::CM_dxt1;
1410 case EggTexture::CM_dxt2:
1411 return Texture::CM_dxt2;
1413 case EggTexture::CM_dxt3:
1414 return Texture::CM_dxt3;
1416 case EggTexture::CM_dxt4:
1417 return Texture::CM_dxt4;
1419 case EggTexture::CM_dxt5:
1420 return Texture::CM_dxt5;
1422 case EggTexture::CM_default:
1423 return Texture::CM_default;
1426 egg2pg_cat.warning()
1427 <<
"Unexpected texture compression flag: " << (int)compression_mode <<
"\n";
1428 return Texture::CM_default;
1435SamplerState::WrapMode EggLoader::
1436convert_wrap_mode(EggTexture::WrapMode wrap_mode)
const {
1437 switch (wrap_mode) {
1438 case EggTexture::WM_clamp:
1439 return SamplerState::WM_clamp;
1441 case EggTexture::WM_repeat:
1442 return SamplerState::WM_repeat;
1444 case EggTexture::WM_mirror:
1445 return SamplerState::WM_mirror;
1447 case EggTexture::WM_mirror_once:
1448 return SamplerState::WM_mirror_once;
1450 case EggTexture::WM_border_color:
1451 return SamplerState::WM_border_color;
1453 case EggTexture::WM_unspecified:
1454 return SamplerState::WM_repeat;
1457 egg2pg_cat.warning()
1458 <<
"Unexpected texture wrap flag: " << (int)wrap_mode <<
"\n";
1459 return SamplerState::WM_repeat;
1466make_texture_stage(
const EggTexture *egg_tex) {
1473 (egg_tex->get_env_type() == EggTexture::ET_unspecified ||
1474 egg_tex->get_env_type() == EggTexture::ET_modulate) &&
1475 egg_tex->get_combine_mode(EggTexture::CC_rgb) == EggTexture::CM_unspecified &&
1476 egg_tex->get_combine_mode(EggTexture::CC_alpha) == EggTexture::CM_unspecified &&
1484 PT(TextureStage) stage =
new TextureStage(egg_tex->
get_stage_name());
1486 switch (egg_tex->get_env_type()) {
1487 case EggTexture::ET_modulate:
1488 stage->set_mode(TextureStage::M_modulate);
1491 case EggTexture::ET_decal:
1492 stage->set_mode(TextureStage::M_decal);
1495 case EggTexture::ET_blend:
1496 stage->set_mode(TextureStage::M_blend);
1499 case EggTexture::ET_replace:
1500 stage->set_mode(TextureStage::M_replace);
1503 case EggTexture::ET_add:
1504 stage->set_mode(TextureStage::M_add);
1507 case EggTexture::ET_blend_color_scale:
1508 stage->set_mode(TextureStage::M_blend_color_scale);
1511 case EggTexture::ET_modulate_glow:
1512 stage->set_mode(TextureStage::M_modulate_glow);
1515 case EggTexture::ET_modulate_gloss:
1516 stage->set_mode(TextureStage::M_modulate_gloss);
1519 case EggTexture::ET_normal:
1520 stage->set_mode(TextureStage::M_normal);
1523 case EggTexture::ET_normal_height:
1524 stage->set_mode(TextureStage::M_normal_height);
1527 case EggTexture::ET_glow:
1528 stage->set_mode(TextureStage::M_glow);
1531 case EggTexture::ET_gloss:
1532 stage->set_mode(TextureStage::M_gloss);
1535 case EggTexture::ET_height:
1536 stage->set_mode(TextureStage::M_height);
1539 case EggTexture::ET_selector:
1540 case EggTexture::ET___metallic_roughness:
1541 case EggTexture::ET___occlusion_metallic_roughness:
1542 stage->set_mode(TextureStage::M_selector);
1545 case EggTexture::ET_normal_gloss:
1546 stage->set_mode(TextureStage::M_normal_gloss);
1549 case EggTexture::ET_emission:
1550 stage->set_mode(TextureStage::M_emission);
1553 case EggTexture::ET_unspecified:
1557 switch (egg_tex->get_combine_mode(EggTexture::CC_rgb)) {
1558 case EggTexture::CM_replace:
1559 stage->set_combine_rgb(get_combine_mode(egg_tex, EggTexture::CC_rgb),
1560 get_combine_source(egg_tex, EggTexture::CC_rgb, 0),
1561 get_combine_operand(egg_tex, EggTexture::CC_rgb, 0));
1564 case EggTexture::CM_modulate:
1565 case EggTexture::CM_add:
1566 case EggTexture::CM_add_signed:
1567 case EggTexture::CM_subtract:
1568 case EggTexture::CM_dot3_rgb:
1569 case EggTexture::CM_dot3_rgba:
1570 stage->set_combine_rgb(get_combine_mode(egg_tex, EggTexture::CC_rgb),
1571 get_combine_source(egg_tex, EggTexture::CC_rgb, 0),
1572 get_combine_operand(egg_tex, EggTexture::CC_rgb, 0),
1573 get_combine_source(egg_tex, EggTexture::CC_rgb, 1),
1574 get_combine_operand(egg_tex, EggTexture::CC_rgb, 1));
1577 case EggTexture::CM_interpolate:
1578 stage->set_combine_rgb(get_combine_mode(egg_tex, EggTexture::CC_rgb),
1579 get_combine_source(egg_tex, EggTexture::CC_rgb, 0),
1580 get_combine_operand(egg_tex, EggTexture::CC_rgb, 0),
1581 get_combine_source(egg_tex, EggTexture::CC_rgb, 1),
1582 get_combine_operand(egg_tex, EggTexture::CC_rgb, 1),
1583 get_combine_source(egg_tex, EggTexture::CC_rgb, 2),
1584 get_combine_operand(egg_tex, EggTexture::CC_rgb, 2));
1587 case EggTexture::CM_unspecified:
1591 switch (egg_tex->get_combine_mode(EggTexture::CC_alpha)) {
1592 case EggTexture::CM_replace:
1593 stage->set_combine_alpha(get_combine_mode(egg_tex, EggTexture::CC_alpha),
1594 get_combine_source(egg_tex, EggTexture::CC_alpha, 0),
1595 get_combine_operand(egg_tex, EggTexture::CC_alpha, 0));
1598 case EggTexture::CM_modulate:
1599 case EggTexture::CM_add:
1600 case EggTexture::CM_add_signed:
1601 case EggTexture::CM_subtract:
1602 stage->set_combine_alpha(get_combine_mode(egg_tex, EggTexture::CC_alpha),
1603 get_combine_source(egg_tex, EggTexture::CC_alpha, 0),
1604 get_combine_operand(egg_tex, EggTexture::CC_alpha, 0),
1605 get_combine_source(egg_tex, EggTexture::CC_alpha, 1),
1606 get_combine_operand(egg_tex, EggTexture::CC_alpha, 1));
1609 case EggTexture::CM_interpolate:
1610 stage->set_combine_alpha(get_combine_mode(egg_tex, EggTexture::CC_alpha),
1611 get_combine_source(egg_tex, EggTexture::CC_alpha, 0),
1612 get_combine_operand(egg_tex, EggTexture::CC_alpha, 0),
1613 get_combine_source(egg_tex, EggTexture::CC_alpha, 1),
1614 get_combine_operand(egg_tex, EggTexture::CC_alpha, 1),
1615 get_combine_source(egg_tex, EggTexture::CC_alpha, 2),
1616 get_combine_operand(egg_tex, EggTexture::CC_alpha, 2));
1619 case EggTexture::CM_unspecified:
1620 case EggTexture::CM_dot3_rgb:
1621 case EggTexture::CM_dot3_rgba:
1627 PT(InternalName) name =
1628 InternalName::get_texcoord_name(egg_tex->
get_uv_name());
1629 stage->set_texcoord_name(name);
1661separate_switches(
EggNode *egg_node) {
1662 bool parent_has_switch =
false;
1663 if (egg_node->
is_of_type(EggGroup::get_class_type())) {
1664 EggGroup *egg_group = DCAST(EggGroup, egg_node);
1665 parent_has_switch = egg_group->get_switch_flag();
1668 if (egg_node->
is_of_type(EggGroupNode::get_class_type())) {
1669 EggGroupNode *egg_group = DCAST(EggGroupNode, egg_node);
1671 EggGroupNode::iterator ci;
1672 ci = egg_group->begin();
1673 while (ci != egg_group->end()) {
1674 EggGroupNode::iterator cnext;
1678 PT(EggNode) child = (*ci);
1679 if (parent_has_switch &&
1680 child->is_of_type(EggPrimitive::get_class_type())) {
1682 PT(EggGroup) new_group =
new EggGroup(child->get_name());
1683 egg_group->
replace(ci, new_group.p());
1684 new_group->add_child(child);
1687 separate_switches(child);
1700emulate_bface(
EggNode *egg_node) {
1701 if (egg_node->
is_of_type(EggGroupNode::get_class_type())) {
1702 EggGroupNode *egg_group = DCAST(EggGroupNode, egg_node);
1703 PT(EggGroupNode) dup_prims =
new EggGroupNode;
1705 EggGroupNode::iterator ci;
1706 for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
1707 PT(EggNode) child = (*ci);
1708 if (child->is_of_type(EggPolygon::get_class_type())) {
1709 EggPolygon *poly = DCAST(EggPolygon, child);
1713 PT(EggPolygon) dup_poly =
new EggPolygon(*poly);
1714 dup_poly->reverse_vertex_ordering();
1715 if (dup_poly->has_normal()) {
1716 dup_poly->set_normal(-dup_poly->get_normal());
1720 EggPolygon::iterator vi;
1721 for (vi = dup_poly->begin(); vi != dup_poly->end(); ++vi) {
1722 EggVertex *vertex = (*vi);
1723 if (vertex->has_normal()) {
1724 EggVertex dup_vertex(*vertex);
1725 dup_vertex.set_normal(-dup_vertex.get_normal());
1727 if (new_vertex != vertex) {
1729 dup_poly->replace(vi, new_vertex);
1733 dup_prims->add_child(dup_poly);
1737 emulate_bface(child);
1751 if (egg_node->
is_of_type(EggBin::get_class_type())) {
1752 return make_node(DCAST(EggBin, egg_node), parent);
1753 }
else if (egg_node->
is_of_type(EggGroup::get_class_type())) {
1754 return make_node(DCAST(EggGroup, egg_node), parent);
1755 }
else if (egg_node->
is_of_type(EggTable::get_class_type())) {
1756 return make_node(DCAST(EggTable, egg_node), parent);
1757 }
else if (egg_node->
is_of_type(EggGroupNode::get_class_type())) {
1758 return make_node(DCAST(EggGroupNode, egg_node), parent);
1772 switch (egg_bin->get_bin_number()) {
1773 case EggBinner::BN_polyset:
1774 case EggBinner::BN_patches:
1775 make_polyset(egg_bin, parent,
nullptr, _dynamic_override, _dynamic_override_char_maker);
1778 case EggBinner::BN_lod:
1779 return make_lod(egg_bin, parent);
1781 case EggBinner::BN_nurbs_surface:
1783 nassertr(!egg_bin->empty(),
nullptr);
1785 EggNurbsSurface *egg_nurbs;
1786 DCAST_INTO_R(egg_nurbs, child,
nullptr);
1788 make_nurbs_surface(egg_nurbs, parent, mat);
1792 case EggBinner::BN_nurbs_curve:
1794 nassertr(!egg_bin->empty(),
nullptr);
1796 EggNurbsCurve *egg_nurbs;
1797 DCAST_INTO_R(egg_nurbs, child,
nullptr);
1799 make_nurbs_curve(egg_nurbs, parent, mat);
1803 case EggBinner::BN_none:
1816 PT(LODNode) lod_node = LODNode::make_default_lod(egg_bin->get_name());
1818 pvector<LODInstance> instances;
1820 EggGroup::const_iterator ci;
1821 for (ci = egg_bin->begin(); ci != egg_bin->end(); ++ci) {
1822 LODInstance instance(*ci);
1823 instances.push_back(instance);
1828 sort(instances.begin(), instances.end());
1830 if (!instances.empty()) {
1833 lod_node->set_center(LCAST(PN_stdfloat, instances[0]._d->_center));
1836 for (
size_t i = 0; i < instances.size(); i++) {
1838 const LODInstance &instance = instances[i];
1839 make_node(instance._egg_node, lod_node);
1843 nassertr(lod_node->get_center().almost_equal
1844 (LCAST(PN_stdfloat, instance._d->_center), 0.01),
nullptr);
1847 lod_node->add_switch(instance._d->_switch_in, instance._d->_switch_out);
1850 _groups[egg_bin] = lod_node;
1851 return create_group_arc(egg_bin, parent, lod_node);
1859 PT(PandaNode) node =
nullptr;
1861 if (egg_group->get_dart_type() != EggGroup::DT_none) {
1863 bool structured = (egg_group->get_dart_type() == EggGroup::DT_structured);
1865 CharacterMaker char_maker(egg_group, *
this, structured);
1867 node = char_maker.make_node();
1871 _dynamic_override =
true;
1872 _dynamic_override_char_maker = &char_maker;
1873 EggGroup::const_iterator ci;
1874 for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
1875 make_node(*ci, node);
1877 _dynamic_override_char_maker =
nullptr;
1878 _dynamic_override =
false;
1881 }
else if (egg_group->get_cs_type() != EggGroup::CST_none) {
1883 node =
new CollisionNode(egg_group->get_name());
1887 node->set_transform(TransformState::make_mat(LCAST(PN_stdfloat, egg_group->
get_vertex_to_node())));
1888 make_collision_solids(egg_group, egg_group, (CollisionNode *)node.p());
1889 node->clear_transform();
1891 if ((egg_group->get_collide_flags() & EggGroup::CF_keep) != 0) {
1895 PandaNode *combined =
new PandaNode(
"");
1900 EggGroup::const_iterator ci;
1901 for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
1902 make_node(*ci, combined);
1906 node = create_group_arc(egg_group, parent, node);
1909 }
else if (egg_group->get_portal_flag()) {
1913 PortalNode *pnode =
new PortalNode(egg_group->get_name());
1916 set_portal_polygon(egg_group, pnode);
1918 egg2pg_cat.warning()
1919 <<
"Portal " << egg_group->get_name() <<
" has no vertices!\n";
1922 }
else if (egg_group->get_occluder_flag()) {
1926 OccluderNode *pnode =
new OccluderNode(egg_group->get_name());
1929 set_occluder_polygon(egg_group, pnode);
1931 egg2pg_cat.warning()
1932 <<
"Occluder " << egg_group->get_name() <<
" has no vertices!\n";
1935 }
else if (egg_group->get_polylight_flag()) {
1943 if (!make_sphere(egg_group, EggGroup::CF_none, center, radius, color)) {
1944 egg2pg_cat.warning()
1945 <<
"Polylight " << egg_group->get_name() <<
" make_sphere failed!\n";
1947 PolylightNode *pnode =
new PolylightNode(egg_group->get_name());
1956 }
else if (egg_group->get_switch_flag()) {
1957 if (egg_group->get_switch_fps() != 0.0) {
1959 node =
new SequenceNode(egg_group->get_name());
1960 ((SequenceNode *)node.p())->set_frame_rate(egg_group->get_switch_fps());
1961 _sequences.insert(node);
1964 node =
new SwitchNode(egg_group->get_name());
1967 EggGroup::const_iterator ci;
1968 for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
1969 make_node(*ci, node);
1971 }
else if (egg_group->has_scrolling_uvs()) {
1972 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());
1974 EggGroup::const_iterator ci;
1975 for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
1976 make_node(*ci, node);
1979 }
else if (egg_group->get_model_flag() || egg_group->
has_dcs_type()) {
1981 node =
new ModelNode(egg_group->get_name());
1982 switch (egg_group->get_dcs_type()) {
1983 case EggGroup::DC_net:
1984 DCAST(ModelNode, node)->set_preserve_transform(ModelNode::PT_net);
1987 case EggGroup::DC_no_touch:
1988 DCAST(ModelNode, node)->set_preserve_transform(ModelNode::PT_no_touch);
1991 case EggGroup::DC_local:
1992 case EggGroup::DC_default:
1993 DCAST(ModelNode, node)->set_preserve_transform(ModelNode::PT_local);
1996 case EggGroup::DC_none:
1997 case EggGroup::DC_unspecified:
2001 EggGroup::const_iterator ci;
2002 for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
2003 make_node(*ci, node);
2011 bool all_polysets =
false;
2012 bool any_hidden =
false;
2017 check_for_polysets(egg_group, all_polysets, any_hidden);
2020 if (all_polysets && !any_hidden) {
2021 node =
new GeomNode(egg_group->get_name());
2023 node =
new PandaNode(egg_group->get_name());
2026 EggGroup::const_iterator ci;
2027 for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
2028 make_node(*ci, node);
2032 if (node ==
nullptr) {
2038 for (
int gri = 0; gri < num_group_refs; ++gri) {
2040 Groups::const_iterator gi = _groups.find(group_ref);
2041 if (gi != _groups.end()) {
2042 PandaNode *node_ref = (*gi).second;
2043 node->add_child(node_ref);
2047 _groups[egg_group] = node;
2048 return create_group_arc(egg_group, parent, node);
2068 switch (egg_group->get_billboard_type()) {
2069 case EggGroup::BT_point_camera_relative:
2070 node->
set_effect(BillboardEffect::make_point_eye());
2073 case EggGroup::BT_point_world_relative:
2074 node->
set_effect(BillboardEffect::make_point_world());
2077 case EggGroup::BT_axis:
2078 node->
set_effect(BillboardEffect::make_axis());
2081 case EggGroup::BT_none:
2085 if (egg_group->get_decal_flag()) {
2086 if (egg_ignore_decals) {
2088 <<
"Ignoring decal flag on " << egg_group->get_name() <<
"\n";
2095 _decals.insert(node);
2099 EggGroup::TagData::const_iterator ti;
2101 node->
set_tag((*ti).first, (*ti).second);
2104 if (egg_group->get_blend_mode() != EggGroup::BM_unspecified &&
2105 egg_group->get_blend_mode() != EggGroup::BM_none) {
2107 ColorBlendAttrib::Mode mode = get_color_blend_mode(egg_group->get_blend_mode());
2108 ColorBlendAttrib::Operand a = get_color_blend_operand(egg_group->get_blend_operand_a());
2109 ColorBlendAttrib::Operand b = get_color_blend_operand(egg_group->get_blend_operand_b());
2117 DeferredNodeProperty def;
2118 if (egg_group->has_collide_mask()) {
2119 def._from_collide_mask = egg_group->get_collide_mask();
2120 def._into_collide_mask = egg_group->get_collide_mask();
2122 DeferredNodeProperty::F_has_from_collide_mask |
2123 DeferredNodeProperty::F_has_into_collide_mask;
2125 if (egg_group->has_from_collide_mask()) {
2126 def._from_collide_mask = egg_group->get_from_collide_mask();
2127 def._flags |= DeferredNodeProperty::F_has_from_collide_mask;
2129 if (egg_group->has_into_collide_mask()) {
2130 def._into_collide_mask = egg_group->get_into_collide_mask();
2131 def._flags |= DeferredNodeProperty::F_has_into_collide_mask;
2134 if (def._flags != 0) {
2135 _deferred_nodes[node] = def;
2146 if (egg_table->get_table_type() != EggTable::TT_bundle) {
2149 return make_node(DCAST(EggGroupNode, egg_table), parent);
2153 AnimBundleMaker bundle_maker(egg_table);
2154 AnimBundleNode *node = bundle_maker.make_node();
2165 PandaNode *node =
new PandaNode(egg_group->get_name());
2167 EggGroupNode::const_iterator ci;
2168 for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
2169 make_node(*ci, node);
2181check_for_polysets(
EggGroup *egg_group,
bool &all_polysets,
bool &any_hidden) {
2182 all_polysets = (!egg_group->empty());
2185 EggGroup::const_iterator ci;
2186 for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
2187 if ((*ci)->is_of_type(EggBin::get_class_type())) {
2188 EggBin *egg_bin = DCAST(EggBin, (*ci));
2189 if (egg_bin->get_bin_number() == EggBinner::BN_polyset) {
2192 EggGroup::const_iterator bci = egg_bin->begin();
2193 nassertv(bci != egg_bin->end());
2194 const EggPrimitive *first_prim;
2195 DCAST_INTO_V(first_prim, (*bci));
2196 const EggRenderState *render_state;
2197 DCAST_INTO_V(render_state, first_prim->
get_user_data(EggRenderState::get_class_type()));
2199 if (render_state->_hidden) {
2203 all_polysets =
false;
2206 }
else if ((*ci)->is_of_type(EggGroup::get_class_type())) {
2210 all_polysets =
false;
2226 bool ignore_color) {
2227 VertexPoolTransform vpt;
2228 vpt._vertex_pool = vertex_pool;
2229 vpt._bake_in_uvs = render_state->_bake_in_uvs;
2230 vpt._transform = transform;
2232 VertexPoolData::iterator di;
2233 di = _vertex_pool_data.find(vpt);
2234 if (di != _vertex_pool_data.end()) {
2235 return (*di).second;
2238 PT(GeomVertexArrayFormat) array_format =
new GeomVertexArrayFormat;
2239 array_format->add_column
2240 (InternalName::get_vertex(), vertex_pool->get_num_dimensions(),
2241 Geom::NT_stdfloat, Geom::C_point);
2243 if (vertex_pool->has_normals()) {
2244 array_format->add_column
2245 (InternalName::get_normal(), 3,
2246 Geom::NT_stdfloat, Geom::C_normal);
2249 if (!ignore_color) {
2253 array_format->add_column(InternalName::get_color(), 1,
2254 Geom::NT_packed_dabc, Geom::C_color);
2256 array_format->add_column(InternalName::get_color(), 4,
2257 Geom::NT_uint8, Geom::C_color);
2261 vector_string uv_names, uvw_names, tbn_names;
2262 vertex_pool->get_uv_names(uv_names, uvw_names, tbn_names);
2263 vector_string::const_iterator ni;
2264 for (ni = uv_names.begin(); ni != uv_names.end(); ++ni) {
2265 string name = (*ni);
2267 PT(InternalName) iname = InternalName::get_texcoord_name(name);
2269 if (find(uvw_names.begin(), uvw_names.end(), name) != uvw_names.end()) {
2271 array_format->add_column
2272 (iname, 3, Geom::NT_stdfloat, Geom::C_texcoord);
2274 array_format->add_column
2275 (iname, 2, Geom::NT_stdfloat, Geom::C_texcoord);
2278 for (ni = tbn_names.begin(); ni != tbn_names.end(); ++ni) {
2279 string name = (*ni);
2281 PT(InternalName) iname_t = InternalName::get_tangent_name(name);
2282 PT(InternalName) iname_b = InternalName::get_binormal_name(name);
2284 array_format->add_column
2285 (iname_t, 3, Geom::NT_stdfloat, Geom::C_vector);
2286 array_format->add_column
2287 (iname_b, 3, Geom::NT_stdfloat, Geom::C_vector);
2290 vector_string aux_names;
2291 vertex_pool->get_aux_names(aux_names);
2292 for (ni = aux_names.begin(); ni != aux_names.end(); ++ni) {
2293 string name = (*ni);
2294 PT(InternalName) iname = InternalName::make(name);
2295 array_format->add_column
2296 (iname, 4, Geom::NT_stdfloat, Geom::C_other);
2299 PT(GeomVertexFormat) temp_format =
new GeomVertexFormat(array_format);
2301 PT(SliderTable) slider_table;
2302 string name = _data->get_egg_filename().get_basename_wo_extension();
2311 GeomVertexAnimationSpec animation;
2313 temp_format->set_animation(animation);
2315 PT(GeomVertexArrayFormat) anim_array_format =
new GeomVertexArrayFormat;
2316 anim_array_format->add_column
2317 (InternalName::get_transform_blend(), 1,
2318 Geom::NT_uint16, Geom::C_index, 0, 2);
2319 temp_format->add_array(anim_array_format);
2321 pmap<string, BitArray> slider_names;
2322 EggVertexPool::const_iterator vi;
2323 for (vi = vertex_pool->begin(); vi != vertex_pool->end(); ++vi) {
2324 EggVertex *vertex = (*vi);
2326 EggMorphVertexList::const_iterator mvi;
2327 for (mvi = vertex->_dxyzs.begin(); mvi != vertex->_dxyzs.end(); ++mvi) {
2328 slider_names[(*mvi).get_name()].set_bit(vertex->
get_index());
2329 record_morph(anim_array_format, character_maker, (*mvi).get_name(),
2330 InternalName::get_vertex(), 3);
2332 if (vertex->has_normal()) {
2333 EggMorphNormalList::const_iterator mni;
2334 for (mni = vertex->_dnormals.begin(); mni != vertex->_dnormals.end(); ++mni) {
2335 slider_names[(*mni).get_name()].set_bit(vertex->
get_index());
2336 record_morph(anim_array_format, character_maker, (*mni).get_name(),
2337 InternalName::get_normal(), 3);
2340 if (!ignore_color && vertex->has_color()) {
2341 EggMorphColorList::const_iterator mci;
2342 for (mci = vertex->_drgbas.begin(); mci != vertex->_drgbas.end(); ++mci) {
2343 slider_names[(*mci).get_name()].set_bit(vertex->
get_index());
2344 record_morph(anim_array_format, character_maker, (*mci).get_name(),
2345 InternalName::get_color(), 4);
2348 EggVertex::const_uv_iterator uvi;
2350 EggVertexUV *egg_uv = (*uvi);
2351 string name = egg_uv->get_name();
2352 bool has_w = (find(uvw_names.begin(), uvw_names.end(), name) != uvw_names.end());
2353 PT(InternalName) iname = InternalName::get_texcoord_name(name);
2355 EggMorphTexCoordList::const_iterator mti;
2356 for (mti = egg_uv->_duvs.begin(); mti != egg_uv->_duvs.end(); ++mti) {
2357 slider_names[(*mti).get_name()].set_bit(vertex->
get_index());
2358 record_morph(anim_array_format, character_maker, (*mti).get_name(),
2359 iname, has_w ? 3 : 2);
2364 if (!slider_names.empty()) {
2367 slider_table =
new SliderTable;
2369 pmap<string, BitArray>::iterator si;
2370 for (si = slider_names.begin(); si != slider_names.end(); ++si) {
2371 PT(VertexSlider) slider = character_maker->egg_to_slider((*si).first);
2372 slider_table->add_slider(slider, (*si).second);
2378 name = character_maker->get_name();
2381 temp_format->maybe_align_columns_for_animation();
2383 CPT(GeomVertexFormat) format =
2384 GeomVertexFormat::register_format(temp_format);
2390 PT(GeomVertexData) vertex_data =
2391 new GeomVertexData(name, format, Geom::UH_static);
2392 vertex_data->reserve_num_rows(vertex_pool->size());
2394 vertex_data->set_transform_blend_table(blend_table);
2395 if (slider_table !=
nullptr) {
2396 vertex_data->set_slider_table(SliderTable::register_table(slider_table));
2400 EggVertexPool::const_iterator vi;
2401 for (vi = vertex_pool->begin(); vi != vertex_pool->end(); ++vi) {
2402 GeomVertexWriter gvw(vertex_data);
2403 EggVertex *vertex = (*vi);
2406 gvw.set_column(InternalName::get_vertex());
2407 gvw.add_data4d(vertex->
get_pos4() * transform);
2410 EggMorphVertexList::const_iterator mvi;
2411 for (mvi = vertex->_dxyzs.begin(); mvi != vertex->_dxyzs.end(); ++mvi) {
2412 const EggMorphVertex &morph = (*mvi);
2413 CPT(InternalName) delta_name =
2414 InternalName::get_morph(InternalName::get_vertex(), morph.get_name());
2415 gvw.set_column(delta_name);
2416 gvw.add_data3d(morph.get_offset() * transform);
2420 if (vertex->has_normal()) {
2421 gvw.set_column(InternalName::get_normal());
2422 LNormald orig_normal = vertex->get_normal();
2423 LNormald transformed_normal = normalize(orig_normal * transform);
2424 gvw.add_data3d(transformed_normal);
2427 EggMorphNormalList::const_iterator mni;
2428 for (mni = vertex->_dnormals.begin(); mni != vertex->_dnormals.end(); ++mni) {
2429 const EggMorphNormal &morph = (*mni);
2430 CPT(InternalName) delta_name =
2431 InternalName::get_morph(InternalName::get_normal(), morph.get_name());
2432 gvw.set_column(delta_name);
2433 LNormald morphed_normal = orig_normal + morph.get_offset();
2434 LNormald transformed_morphed_normal = normalize(morphed_normal * transform);
2435 LVector3d delta = transformed_morphed_normal - transformed_normal;
2436 gvw.add_data3d(delta);
2441 if (!ignore_color && vertex->has_color()) {
2442 gvw.set_column(InternalName::get_color());
2446 EggMorphColorList::const_iterator mci;
2447 for (mci = vertex->_drgbas.begin(); mci != vertex->_drgbas.end(); ++mci) {
2448 const EggMorphColor &morph = (*mci);
2449 CPT(InternalName) delta_name =
2450 InternalName::get_morph(InternalName::get_color(), morph.get_name());
2451 gvw.set_column(delta_name);
2452 gvw.add_data4(morph.get_offset());
2457 EggVertex::const_uv_iterator uvi;
2459 EggVertexUV *egg_uv = (*uvi);
2460 LTexCoord3d orig_uvw = egg_uv->
get_uvw();
2461 LTexCoord3d uvw = egg_uv->
get_uvw();
2463 string name = egg_uv->get_name();
2464 PT(InternalName) iname = InternalName::get_texcoord_name(name);
2465 gvw.set_column(iname);
2467 BakeInUVs::const_iterator buv = render_state->_bake_in_uvs.find(iname);
2468 if (buv != render_state->_bake_in_uvs.end()) {
2470 uvw = uvw * (*buv).second->get_transform3d();
2473 gvw.set_data3d(uvw);
2476 EggMorphTexCoordList::const_iterator mti;
2477 for (mti = egg_uv->_duvs.begin(); mti != egg_uv->_duvs.end(); ++mti) {
2478 const EggMorphTexCoord &morph = (*mti);
2479 CPT(InternalName) delta_name =
2480 InternalName::get_morph(iname, morph.get_name());
2481 gvw.set_column(delta_name);
2482 LTexCoord3d duvw = morph.get_offset();
2483 if (buv != render_state->_bake_in_uvs.end()) {
2484 LTexCoord3d new_uvw = orig_uvw + duvw;
2485 duvw = (new_uvw * (*buv).second->get_transform3d()) - uvw;
2488 gvw.add_data3d(duvw);
2493 if (egg_uv->has_tangent() && egg_uv->has_binormal()) {
2494 PT(InternalName) iname = InternalName::get_tangent_name(name);
2495 gvw.set_column(iname);
2496 if (gvw.has_column()) {
2497 LVector3d tangent = egg_uv->get_tangent();
2498 LVector3d binormal = egg_uv->get_binormal();
2499 gvw.add_data3d(tangent);
2500 gvw.set_column(InternalName::get_binormal_name(name));
2501 gvw.add_data3d(binormal);
2506 EggVertex::const_aux_iterator auxi;
2508 EggVertexAux *egg_aux = (*auxi);
2509 LVecBase4d aux = egg_aux->
get_aux();
2511 string name = egg_aux->get_name();
2512 PT(InternalName) iname = InternalName::make(name);
2513 gvw.set_column(iname);
2515 gvw.set_data4d(aux);
2520 gvw.set_column(InternalName::get_transform_blend());
2521 gvw.set_data1i(table_index);
2525 bool inserted = _vertex_pool_data.insert
2526 (VertexPoolData::value_type(vpt, vertex_data)).second;
2527 nassertr(inserted, vertex_data);
2539 PT(TransformBlendTable) blend_table;
2540 blend_table =
new TransformBlendTable;
2543 EggVertexPool::const_iterator vi;
2544 for (vi = vertex_pool->begin(); vi != vertex_pool->end(); ++vi) {
2545 EggVertex *vertex = (*vi);
2548 TransformBlend blend;
2552 PT(VertexTransform) vt = character_maker->egg_to_transform(primitive_home);
2553 nassertr(vt !=
nullptr,
nullptr);
2558 double quantize = egg_vertex_membership_quantize;
2559 EggVertex::GroupRef::const_iterator gri;
2561 EggGroup *egg_joint = (*gri);
2563 if (quantize != 0.0) {
2564 membership = cfloor(membership / quantize + 0.5) * quantize;
2567 PT(VertexTransform) vt = character_maker->egg_to_transform(egg_joint);
2568 nassertr(vt !=
nullptr,
nullptr);
2572 if (egg_vertex_max_num_joints >= 0) {
2577 int table_index = blend_table->add_blend(blend);
2594 int num_components) {
2595 PT(InternalName) delta_name =
2596 InternalName::get_morph(column_name, morph_name);
2599 (delta_name, num_components,
2600 Geom::NT_stdfloat, Geom::C_morph_delta);
2610 EggLoader::UniquePrimitives &unique_primitives,
2611 EggLoader::Primitives &primitives,
2612 bool has_overall_color,
const LColor &overall_color) {
2613 PT(GeomPrimitive) primitive;
2614 if (egg_prim->
is_of_type(EggPolygon::get_class_type())) {
2615 if (egg_prim->size() == 3) {
2616 primitive =
new GeomTriangles(Geom::UH_static);
2619 }
else if (egg_prim->
is_of_type(EggTriangleStrip::get_class_type())) {
2620 primitive =
new GeomTristrips(Geom::UH_static);
2622 }
else if (egg_prim->
is_of_type(EggTriangleFan::get_class_type())) {
2623 primitive =
new GeomTrifans(Geom::UH_static);
2625 }
else if (egg_prim->
is_of_type(EggLine::get_class_type())) {
2626 if (egg_prim->size() == 2) {
2627 primitive =
new GeomLines(Geom::UH_static);
2629 primitive =
new GeomLinestrips(Geom::UH_static);
2632 }
else if (egg_prim->
is_of_type(EggPoint::get_class_type())) {
2633 primitive =
new GeomPoints(Geom::UH_static);
2635 }
else if (egg_prim->
is_of_type(EggPatch::get_class_type())) {
2636 int num_vertices = egg_prim->size();
2637 primitive =
new GeomPatches(num_vertices, Geom::UH_static);
2640 if (primitive ==
nullptr) {
2642 egg2pg_cat.warning()
2643 <<
"Ignoring " << egg_prim->get_type() <<
"\n";
2647 if (render_state->_flat_shaded) {
2648 primitive->set_shade_model(GeomPrimitive::SM_flat_first_vertex);
2650 }
else if (egg_prim->
get_shading() == EggPrimitive::S_overall) {
2651 primitive->set_shade_model(GeomPrimitive::SM_uniform);
2654 primitive->set_shade_model(GeomPrimitive::SM_smooth);
2659 PrimitiveUnifier pu(primitive);
2660 std::pair<UniquePrimitives::iterator, bool> result =
2661 unique_primitives.insert(UniquePrimitives::value_type(pu, primitive));
2663 if (result.second) {
2665 primitives.push_back(primitive);
2667 if (egg2pg_cat.is_debug()) {
2669 <<
"First primitive of type " << primitive->get_type()
2670 <<
": " << primitive <<
"\n";
2674 GeomPrimitive *orig_prim = (*result.first).second;
2678 if (orig_prim->
get_num_vertices() + egg_prim->size() <= (
unsigned int)egg_max_indices) {
2679 primitive = orig_prim;
2681 }
else if (orig_prim != primitive) {
2683 (*result.first).second = primitive;
2685 if (egg2pg_cat.is_debug()) {
2687 <<
"Next primitive of type " << primitive->get_type()
2688 <<
": " << primitive <<
"\n";
2690 primitives.push_back(primitive);
2694 EggPrimitive::const_iterator vi;
2695 for (vi = egg_prim->begin(); vi != egg_prim->end(); ++vi) {
2696 primitive->add_vertex((*vi)->get_index());
2698 primitive->close_primitive();
2708 PT(EggPolygon) poly = find_first_polygon(egg_group);
2709 if (poly !=
nullptr) {
2712 EggPolygon::const_iterator vi;
2713 for (vi = poly->begin(); vi != poly->end(); ++vi) {
2714 LVertexd vert = (*vi)->
get_pos3() * mat;
2725 PT(EggPolygon) poly = find_first_polygon(egg_group);
2726 if (poly !=
nullptr) {
2727 if (poly->size() != 4) {
2729 <<
"Invalid number of vertices for " << egg_group->get_name() <<
"\n";
2733 LPoint3d v0 = (*poly)[0]->get_pos3() * mat;
2734 LPoint3d v1 = (*poly)[1]->get_pos3() * mat;
2735 LPoint3d v2 = (*poly)[2]->get_pos3() * mat;
2736 LPoint3d v3 = (*poly)[3]->get_pos3() * mat;
2738 LCAST(PN_stdfloat, v1),
2739 LCAST(PN_stdfloat, v2),
2740 LCAST(PN_stdfloat, v3));
2753find_first_polygon(
EggGroup *egg_group) {
2755 EggGroup::const_iterator ci;
2756 for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
2757 if ((*ci)->is_of_type(EggPolygon::get_class_type())) {
2759 return DCAST(EggPolygon, (*ci));
2764 for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
2765 if ((*ci)->is_of_type(EggGroup::get_class_type())) {
2766 EggGroup *child_group = DCAST(EggGroup, *ci);
2767 PT(EggPolygon) found = find_first_polygon(child_group);
2768 if (found !=
nullptr) {
2784make_sphere(
EggGroup *egg_group, EggGroup::CollideFlags flags,
2785 LPoint3 ¢er, PN_stdfloat &radius, LColor &color) {
2786 EggGroup *geom_group = find_collision_geometry(egg_group, flags);
2787 if (geom_group !=
nullptr) {
2789 pset<EggVertex *> vertices;
2791 EggGroup::const_iterator ci;
2792 for (ci = geom_group->begin(); ci != geom_group->end(); ++ci) {
2793 if ((*ci)->is_of_type(EggPrimitive::get_class_type())) {
2794 EggPrimitive *prim = DCAST(EggPrimitive, *ci);
2795 EggPrimitive::const_iterator pi;
2796 for (pi = prim->begin(); pi != prim->end(); ++pi) {
2797 vertices.insert(*pi);
2803 int num_vertices = 0;
2804 LPoint3d d_center(0.0, 0.0, 0.0);
2805 pset<EggVertex *>::const_iterator vi;
2807 for (vi = vertices.begin(); vi != vertices.end(); ++vi) {
2808 EggVertex *vtx = (*vi);
2813 if (num_vertices > 0) {
2814 d_center /= (double)num_vertices;
2818 double radius2 = 0.0;
2819 for (vi = vertices.begin(); vi != vertices.end(); ++vi) {
2820 EggVertex *vtx = (*vi);
2822 LVector3d v = p3 - d_center;
2823 radius2 = max(radius2, v.length_squared());
2826 center = LCAST(PN_stdfloat, d_center);
2827 radius = sqrtf(radius2);
2830 vi = vertices.begin();
2831 EggVertex *clr_vtx = (*vi);
2844make_box(
EggGroup *egg_group, EggGroup::CollideFlags flags,
2845 const LMatrix4 &xform, LPoint3 &min_p, LPoint3 &max_p) {
2846 EggGroup *geom_group = find_collision_geometry(egg_group, flags);
2847 if (geom_group !=
nullptr) {
2849 pset<EggVertex *> vertices;
2851 EggGroup::const_iterator ci;
2852 for (ci = geom_group->begin(); ci != geom_group->end(); ++ci) {
2853 if ((*ci)->is_of_type(EggPrimitive::get_class_type())) {
2854 EggPrimitive *prim = DCAST(EggPrimitive, *ci);
2855 EggPrimitive::const_iterator pi;
2856 for (pi = prim->begin(); pi != prim->end(); ++pi) {
2857 vertices.insert(*pi);
2863 pset<EggVertex *>::const_iterator vi;
2864 vi = vertices.begin();
2866 if (vi == vertices.end()) {
2873 EggVertex *vertex = (*vi);
2874 LPoint3 min_pd = LCAST(PN_stdfloat, vertex->
get_pos3()) * xform;
2875 LPoint3 max_pd = min_pd;
2877 for (++vi; vi != vertices.end(); ++vi) {
2879 LPoint3 pos = LCAST(PN_stdfloat, vertex->
get_pos3()) * xform;
2880 min_pd.set(min(min_pd[0], pos[0]),
2881 min(min_pd[1], pos[1]),
2882 min(min_pd[2], pos[2]));
2883 max_pd.set(max(max_pd[0], pos[0]),
2884 max(max_pd[1], pos[1]),
2885 max(max_pd[2], pos[2]));
2890 return (min_pd != max_pd);
2900make_box(
EggGroup *egg_group, EggGroup::CollideFlags flags,
2901 LPoint3 &min_p, LPoint3 &max_p, LColor &color) {
2903 color.set(1.0, 1.0, 1.0, 1.0);
2904 return make_box(egg_group, flags, LMatrix4::ident_mat(), min_p, max_p);
2914 if (egg_group->get_cs_type() != EggGroup::CST_none) {
2915 start_group = egg_group;
2918 switch (start_group->get_cs_type()) {
2919 case EggGroup::CST_none:
2923 case EggGroup::CST_plane:
2924 make_collision_plane(egg_group, cnode, start_group->get_collide_flags());
2927 case EggGroup::CST_polygon:
2928 make_collision_polygon(egg_group, cnode, start_group->get_collide_flags());
2931 case EggGroup::CST_polyset:
2932 make_collision_polyset(egg_group, cnode, start_group->get_collide_flags());
2935 case EggGroup::CST_sphere:
2936 make_collision_sphere(egg_group, cnode, start_group->get_collide_flags());
2939 case EggGroup::CST_box:
2940 make_collision_box(egg_group, cnode, start_group->get_collide_flags());
2943 case EggGroup::CST_inv_sphere:
2944 make_collision_inv_sphere(egg_group, cnode, start_group->get_collide_flags());
2947 case EggGroup::CST_tube:
2948 make_collision_capsule(egg_group, cnode, start_group->get_collide_flags());
2951 case EggGroup::CST_floor_mesh:
2952 make_collision_floor_mesh(egg_group, cnode, start_group->get_collide_flags());
2956 if ((start_group->get_collide_flags() & EggGroup::CF_descend) != 0) {
2958 EggGroup::const_iterator ci;
2959 for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
2960 if ((*ci)->is_of_type(EggGroup::get_class_type())) {
2961 make_collision_solids(start_group, DCAST(EggGroup, *ci), cnode);
2965 egg2pg_cat.warning()
2966 <<
"Using <Collide> without 'descend' is deprecated. 'descend' "
2967 <<
"will become the default in a future version of Panda3D.\n";
2977 EggGroup::CollideFlags flags) {
2978 EggGroup *geom_group = find_collision_geometry(egg_group, flags);
2979 if (geom_group !=
nullptr) {
2980 EggGroup::const_iterator ci;
2981 for (ci = geom_group->begin(); ci != geom_group->end(); ++ci) {
2982 if ((*ci)->is_of_type(EggPolygon::get_class_type())) {
2983 CollisionPlane *csplane =
2984 create_collision_plane(DCAST(EggPolygon, *ci), egg_group);
2985 if (csplane !=
nullptr) {
2986 apply_collision_flags(csplane, flags);
2987 csplane->
xform(cnode->get_transform()->get_mat());
2991 }
else if ((*ci)->is_of_type(EggCompositePrimitive::get_class_type()) &&
2992 !(*ci)->is_of_type(EggLine::get_class_type())) {
2993 EggCompositePrimitive *comp = DCAST(EggCompositePrimitive, *ci);
2994 PT(EggGroup) temp_group =
new EggGroup;
2996 make_collision_plane(temp_group, cnode, flags);
3012 EggGroup::CollideFlags flags) {
3014 EggGroup *geom_group = find_collision_geometry(egg_group, flags);
3017 if (geom_group !=
nullptr) {
3018 create_collision_floor_mesh(cnode, geom_group,flags);
3028 EggGroup::CollideFlags flags) {
3030 EggGroup *geom_group = find_collision_geometry(egg_group, flags);
3031 if (geom_group !=
nullptr) {
3032 EggGroup::const_iterator ci;
3033 for (ci = geom_group->begin(); ci != geom_group->end(); ++ci) {
3034 if ((*ci)->is_of_type(EggPolygon::get_class_type())) {
3035 create_collision_polygons(cnode, DCAST(EggPolygon, *ci),
3037 }
else if ((*ci)->is_of_type(EggCompositePrimitive::get_class_type())) {
3038 EggCompositePrimitive *comp = DCAST(EggCompositePrimitive, *ci);
3039 PT(EggGroup) temp_group =
new EggGroup;
3041 make_collision_polygon(temp_group, cnode, flags);
3056 EggGroup::CollideFlags flags) {
3057 EggGroup *geom_group = find_collision_geometry(egg_group, flags);
3058 if (geom_group !=
nullptr) {
3059 EggGroup::const_iterator ci;
3060 for (ci = geom_group->begin(); ci != geom_group->end(); ++ci) {
3061 if ((*ci)->is_of_type(EggPolygon::get_class_type())) {
3062 create_collision_polygons(cnode, DCAST(EggPolygon, *ci),
3064 }
else if ((*ci)->is_of_type(EggCompositePrimitive::get_class_type())) {
3065 EggCompositePrimitive *comp = DCAST(EggCompositePrimitive, *ci);
3066 PT(EggGroup) temp_group =
new EggGroup;
3068 make_collision_polyset(temp_group, cnode, flags);
3081 EggGroup::CollideFlags flags) {
3085 if (make_sphere(egg_group, flags, center, radius, dummycolor)) {
3086 CollisionSphere *cssphere =
3087 new CollisionSphere(center, radius);
3088 apply_collision_flags(cssphere, flags);
3089 cssphere->
xform(cnode->get_transform()->get_mat());
3100 EggGroup::CollideFlags flags) {
3104 if (make_box(egg_group, flags, transform->get_mat(), min_p, max_p)) {
3105 CollisionBox *csbox =
3106 new CollisionBox(min_p, max_p);
3107 apply_collision_flags(csbox, flags);
3118 EggGroup::CollideFlags flags) {
3122 if (make_sphere(egg_group, flags, center, radius, dummycolor)) {
3123 CollisionInvSphere *cssphere =
3124 new CollisionInvSphere(center, radius);
3125 apply_collision_flags(cssphere, flags);
3126 cssphere->
xform(cnode->get_transform()->get_mat());
3137 EggGroup::CollideFlags flags) {
3138 EggGroup *geom_group = find_collision_geometry(egg_group, flags);
3139 if (geom_group !=
nullptr) {
3141 pset<EggVertex *> vertices;
3143 EggGroup::const_iterator ci;
3144 for (ci = geom_group->begin(); ci != geom_group->end(); ++ci) {
3145 if ((*ci)->is_of_type(EggPrimitive::get_class_type())) {
3146 EggPrimitive *prim = DCAST(EggPrimitive, *ci);
3147 EggPrimitive::const_iterator pi;
3148 for (pi = prim->begin(); pi != prim->end(); ++pi) {
3149 vertices.insert(*pi);
3156 size_t num_vertices = vertices.size();
3157 if (num_vertices != 0) {
3158 pvector<LPoint3d> vpos;
3159 vpos.reserve(num_vertices);
3161 LPoint3d center(0.0, 0.0, 0.0);
3162 pset<EggVertex *>::const_iterator vi;
3163 for (vi = vertices.begin(); vi != vertices.end(); ++vi) {
3164 EggVertex *vtx = (*vi);
3165 const LPoint3d &pos = vtx->
get_pos3();
3166 vpos.push_back(pos);
3169 center /= (double)num_vertices;
3175 double radius2 = 0.0;
3176 LPoint3d far_a = center;
3177 for (i = 0; i < num_vertices; i++) {
3178 double dist2 = (vpos[i] - center).length_squared();
3179 if (dist2 > radius2) {
3189 LPoint3d far_b = center;
3190 for (i = 0; i < num_vertices; i++) {
3191 double dist2 = (vpos[i] - far_a).length_squared();
3192 if (dist2 > radius2) {
3209 LPoint3d cap_a_center(0.0, 0.0, 0.0);
3210 LPoint3d cap_b_center(0.0, 0.0, 0.0);
3216 double center_length = (far_a - far_b).length() / 4.0;
3217 double center_length2 = center_length * center_length;
3219 for (i = 0; i < num_vertices; i++) {
3220 double dist2 = (vpos[i] - center).length_squared();
3221 if (dist2 > center_length2) {
3224 double dist_a2 = (vpos[i] - far_a).length_squared();
3225 double dist_b2 = (vpos[i] - far_b).length_squared();
3226 if (dist_a2 < dist_b2) {
3228 cap_a_center += vpos[i];
3232 cap_b_center += vpos[i];
3238 if (num_a > 0 && num_b > 0) {
3239 cap_a_center /= (double)num_a;
3240 cap_b_center /= (double)num_b;
3244 LVector3d axis = cap_b_center - cap_a_center;
3249 if (IS_THRESHOLD_ZERO(axis[0], 0.01)) {
3252 if (IS_THRESHOLD_ZERO(axis[1], 0.01)) {
3255 if (IS_THRESHOLD_ZERO(axis[2], 0.01)) {
3267 look_at(mat, axis, LVector3d(0.0, 0.0, 1.0), CS_zup_right);
3268 mat.set_row(3, center);
3270 inv_mat.invert_from(mat);
3272 for (i = 0; i < num_vertices; i++) {
3273 vpos[i] = vpos[i] * inv_mat;
3276 double max_radius2 = 0.0;
3279 for (i = 0; i < num_vertices; i++) {
3280 LVector2d v(vpos[i][0], vpos[i][2]);
3281 double radius2 = v.length_squared();
3282 if (radius2 > max_radius2) {
3283 max_radius2 = radius2;
3293 for (i = 0; i < num_vertices; i++) {
3294 LVector2d v(vpos[i][0], vpos[i][2]);
3295 double radius2 = v.length_squared();
3297 if (vpos[i][1] < min_y) {
3300 double factor = sqrt(max_radius2 - radius2);
3301 min_y = min(min_y, vpos[i][1] + factor);
3303 }
else if (vpos[i][1] > max_y) {
3304 double factor = sqrt(max_radius2 - radius2);
3305 max_y = max(max_y, vpos[i][1] - factor);
3309 double length = max_y - min_y;
3310 double radius = sqrt(max_radius2);
3313 LVector3d half = axis * (length / 2.0);
3314 LPoint3d point_a = center - half;
3315 LPoint3d point_b = center + half;
3317 CollisionCapsule *cscapsule =
3318 new CollisionCapsule(LCAST(PN_stdfloat, point_a), LCAST(PN_stdfloat, point_b),
3320 apply_collision_flags(cscapsule, flags);
3321 cscapsule->
xform(cnode->get_transform()->get_mat());
3333apply_collision_flags(
CollisionSolid *solid, EggGroup::CollideFlags flags) {
3334 if ((flags & EggGroup::CF_intangible) != 0) {
3337 if ((flags & EggGroup::CF_level) != 0) {
3347find_collision_geometry(
EggGroup *egg_group, EggGroup::CollideFlags flags) {
3348 if ((flags & EggGroup::CF_descend) != 0) {
3355 EggGroup::const_iterator ci;
3356 for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
3357 if ((*ci)->is_of_type(EggPolygon::get_class_type())) {
3365 for (ci = egg_group->begin(); ci != egg_group->end(); ++ci) {
3366 if ((*ci)->is_of_type(EggGroup::get_class_type())) {
3367 EggGroup *child_group = DCAST(EggGroup, *ci);
3368 if (child_group->get_cs_type() == egg_group->get_cs_type()) {
3385 <<
"Ignoring degenerate collision plane in " << parent_group->get_name()
3391 egg2pg_cat.warning()
3392 <<
"Non-planar polygon defining collision plane in "
3393 << parent_group->get_name()
3397 pvector<LVertex> vertices;
3398 if (!egg_poly->empty()) {
3399 EggPolygon::const_iterator vi;
3400 vi = egg_poly->begin();
3402 LVertexd vert = (*vi)->get_pos3();
3403 vertices.push_back(LCAST(PN_stdfloat, vert));
3405 LVertexd last_vert = vert;
3407 while (vi != egg_poly->end()) {
3408 vert = (*vi)->get_pos3();
3409 if (!vert.almost_equal(last_vert)) {
3410 vertices.push_back(LCAST(PN_stdfloat, vert));
3418 if (vertices.size() < 3) {
3421 LPlane plane(vertices[0], vertices[1], vertices[2]);
3422 return new CollisionPlane(plane);
3432 EggGroup::CollideFlags flags) {
3434 PT(EggGroup) group =
new EggGroup;
3438 <<
"Ignoring degenerate collision polygon in "
3439 << parent_group->get_name()
3444 if (group->size() != 1) {
3446 <<
"Triangulating concave or non-planar collision polygon in "
3447 << parent_group->get_name()
3451 EggGroup::iterator ci;
3452 for (ci = group->begin(); ci != group->end(); ++ci) {
3453 EggPolygon *poly = DCAST(EggPolygon, *ci);
3455 pvector<LVertex> vertices;
3456 if (!poly->empty()) {
3457 EggPolygon::const_iterator vi;
3460 LVertexd vert = (*vi)->get_pos3();
3461 vertices.push_back(LCAST(PN_stdfloat, vert));
3463 LVertexd last_vert = vert;
3465 while (vi != poly->end()) {
3466 vert = (*vi)->get_pos3();
3467 if (!vert.almost_equal(last_vert)) {
3468 vertices.push_back(LCAST(PN_stdfloat, vert));
3476 if (vertices.size() >= 3) {
3477 const LVertex *vertices_begin = &vertices[0];
3478 const LVertex *vertices_end = vertices_begin + vertices.size();
3479 PT(CollisionPolygon) cspoly =
3480 new CollisionPolygon(vertices_begin, vertices_end);
3481 if (cspoly->is_valid()) {
3482 apply_collision_flags(cspoly, flags);
3483 cspoly->xform(cnode->get_transform()->get_mat());
3497 EggGroup::CollideFlags flags) {
3499 PT(EggGroup) group =
new EggGroup;
3500 EggVertexPool pool(
"floorMesh");
3501 pool.local_object();
3502 EggGroup::const_iterator egi;
3503 for (egi = parent_group->begin(); egi != parent_group->end(); ++egi) {
3504 if ((*egi)->is_of_type(EggPolygon::get_class_type())) {
3505 EggPolygon * poly = DCAST(EggPolygon, *egi);
3508 <<
"Ignoring degenerate collision polygon in "
3509 << parent_group->get_name()
3516 if(group->size() == 0) {
3518 <<
"empty collision solid\n";
3521 PT(CollisionFloorMesh) cm =
new CollisionFloorMesh;
3522 pvector<CollisionFloorMesh::TriangleIndices> triangles;
3524 EggGroup::iterator ci;
3525 for (ci = group->begin(); ci != group->end(); ++ci) {
3526 EggPolygon *poly = DCAST(EggPolygon, *ci);
3527 if (poly->get_num_vertices() == 3) {
3528 CollisionFloorMesh::TriangleIndices tri;
3531 tri.p1=pool.create_unique_vertex(*poly->
get_vertex(0))->get_index();
3532 tri.p2=pool.create_unique_vertex(*poly->
get_vertex(1))->get_index();
3533 tri.p3=pool.create_unique_vertex(*poly->
get_vertex(2))->get_index();
3535 triangles.push_back(tri);
3536 }
else if (poly->get_num_vertices() == 4) {
3539 CollisionFloorMesh::TriangleIndices tri;
3540 CollisionFloorMesh::TriangleIndices tri2;
3543 tri.p1=pool.create_unique_vertex(*poly->
get_vertex(0))->get_index();
3544 tri.p2=pool.create_unique_vertex(*poly->
get_vertex(1))->get_index();
3545 tri.p3=pool.create_unique_vertex(*poly->
get_vertex(2))->get_index();
3547 triangles.push_back(tri);
3552 tri2.p3=pool.create_unique_vertex(*poly->
get_vertex(3))->get_index();
3555 triangles.push_back(tri2);
3560 PT(CollisionFloorMesh) csfloor =
new CollisionFloorMesh;
3563 EggVertexPool::const_iterator vi;
3564 for (vi = pool.begin(); vi != pool.end(); vi++) {
3565 csfloor->add_vertex(LCAST(PN_stdfloat,(*vi)->get_pos3()));
3568 pvector<CollisionFloorMesh::TriangleIndices>::iterator ti;
3570 for (ti = triangles.begin(); ti != triangles.end(); ti++) {
3571 CollisionFloorMesh::TriangleIndices triangle = *ti;
3572 csfloor->add_triangle(triangle.p1, triangle.p2, triangle.p3);
3574 csfloor->xform(cnode->get_transform()->get_mat());
3585 DeferredNodeProperty next_prop(prop);
3588 DeferredNodes::const_iterator dni;
3589 dni = _deferred_nodes.find(node);
3591 if (dni != _deferred_nodes.end()) {
3592 const DeferredNodeProperty &def = (*dni).second;
3597 next_prop.apply_to_node(node);
3600 for (
int i = 0; i < num_children; i++) {
3601 apply_deferred_nodes(node->
get_child(i), next_prop);
3614expand_all_object_types(
EggNode *egg_node) {
3615 if (egg_node->
is_of_type(EggGroup::get_class_type())) {
3616 EggGroup *egg_group = DCAST(EggGroup, egg_node);
3618 if (egg_group->get_num_object_types() != 0) {
3619 pset<string> expanded;
3620 pvector<string> expanded_history;
3621 if (!expand_object_types(egg_group, expanded, expanded_history)) {
3629 if (egg_node->
is_of_type(EggGroupNode::get_class_type())) {
3630 EggGroupNode *egg_group_node = DCAST(EggGroupNode, egg_node);
3631 EggGroupNode::const_iterator ci;
3632 ci = egg_group_node->begin();
3633 while (ci != egg_group_node->end()) {
3634 EggGroupNode::const_iterator cnext = ci;
3637 if (!expand_all_object_types(*ci)) {
3639 egg_group_node->erase(ci);
3658expand_object_types(
EggGroup *egg_group,
const pset<string> &expanded,
3659 const pvector<string> &expanded_history) {
3660 int num_object_types = egg_group->get_num_object_types();
3663 vector_string object_types;
3665 for (i = 0; i < num_object_types; i++) {
3666 object_types.push_back(egg_group->get_object_type(i));
3668 egg_group->clear_object_types();
3670 for (i = 0; i < num_object_types; i++) {
3671 string object_type = object_types[i];
3672 pset<string> new_expanded(expanded);
3675 if (!new_expanded.insert(object_type).second) {
3677 <<
"Cycle in ObjectType expansions:\n";
3678 pvector<string>::const_iterator pi;
3679 for (pi = expanded_history.begin();
3680 pi != expanded_history.end();
3682 egg2pg_cat.error(
false)
3685 egg2pg_cat.error(
false) << object_type <<
"\n";
3690 pvector<string> new_expanded_history(expanded_history);
3691 new_expanded_history.push_back(object_type);
3693 if (!do_expand_object_type(egg_group, new_expanded,
3694 new_expanded_history, object_type)) {
3708do_expand_object_type(
EggGroup *egg_group,
const pset<string> &expanded,
3709 const pvector<string> &expanded_history,
3710 const string &object_type) {
3714 ConfigVariableString egg_object_type
3715 (
"egg-object-type-" +
downcase(object_type),
"");
3716 string egg_syntax = egg_object_type;
3718 if (!egg_object_type.has_value()) {
3721 if (cmp_nocase_uh(object_type,
"barrier") == 0) {
3722 egg_syntax =
"<Collide> { Polyset descend }";
3724 }
else if (cmp_nocase_uh(object_type,
"solidpoly") == 0) {
3725 egg_syntax =
"<Collide> { Polyset descend solid }";
3727 }
else if (cmp_nocase_uh(object_type,
"turnstile") == 0) {
3728 egg_syntax =
"<Collide> { Polyset descend turnstile }";
3730 }
else if (cmp_nocase_uh(object_type,
"sphere") == 0) {
3731 egg_syntax =
"<Collide> { Sphere descend }";
3733 }
else if (cmp_nocase_uh(object_type,
"tube") == 0) {
3734 egg_syntax =
"<Collide> { Tube descend }";
3736 }
else if (cmp_nocase_uh(object_type,
"trigger") == 0) {
3737 egg_syntax =
"<Collide> { Polyset descend intangible }";
3739 }
else if (cmp_nocase_uh(object_type,
"trigger_sphere") == 0) {
3740 egg_syntax =
"<Collide> { Sphere descend intangible }";
3742 }
else if (cmp_nocase_uh(object_type,
"eye_trigger") == 0) {
3743 egg_syntax =
"<Collide> { Polyset descend intangible center }";
3745 }
else if (cmp_nocase_uh(object_type,
"bubble") == 0) {
3746 egg_syntax =
"<Collide> { Sphere keep descend }";
3748 }
else if (cmp_nocase_uh(object_type,
"ghost") == 0) {
3749 egg_syntax =
"<Scalar> collide-mask { 0 }";
3751 }
else if (cmp_nocase_uh(object_type,
"dcs") == 0) {
3752 egg_syntax =
"<DCS> { 1 }";
3754 }
else if (cmp_nocase_uh(object_type,
"model") == 0) {
3755 egg_syntax =
"<Model> { 1 }";
3757 }
else if (cmp_nocase_uh(object_type,
"none") == 0) {
3761 }
else if (cmp_nocase_uh(object_type,
"backstage") == 0) {
3767 <<
"Unknown ObjectType " << object_type <<
"\n";
3769 egg2pg_cat.debug() <<
"returning true\n";
3774 if (!egg_syntax.empty()) {
3775 if (!egg_group->
parse_egg(egg_syntax)) {
3777 <<
"Error while parsing definition for ObjectType "
3778 << object_type <<
"\n";
3784 if (egg_group->get_num_object_types() != 0) {
3785 if (!expand_object_types(egg_group, expanded, expanded_history)) {
3799TextureStage::CombineMode EggLoader::
3801 EggTexture::CombineChannel channel) {
3802 switch (egg_tex->get_combine_mode(channel)) {
3803 case EggTexture::CM_unspecified:
3806 case EggTexture::CM_modulate:
3807 return TextureStage::CM_modulate;
3809 case EggTexture::CM_replace:
3810 return TextureStage::CM_replace;
3812 case EggTexture::CM_add:
3813 return TextureStage::CM_add;
3815 case EggTexture::CM_add_signed:
3816 return TextureStage::CM_add_signed;
3818 case EggTexture::CM_interpolate:
3819 return TextureStage::CM_interpolate;
3821 case EggTexture::CM_subtract:
3822 return TextureStage::CM_subtract;
3824 case EggTexture::CM_dot3_rgb:
3825 return TextureStage::CM_dot3_rgb;
3827 case EggTexture::CM_dot3_rgba:
3828 return TextureStage::CM_dot3_rgba;
3831 return TextureStage::CM_undefined;
3838TextureStage::CombineSource EggLoader::
3840 EggTexture::CombineChannel channel,
int n) {
3841 switch (egg_tex->get_combine_source(channel, n)) {
3842 case EggTexture::CS_unspecified:
3847 return TextureStage::CS_previous;
3849 return TextureStage::CS_texture;
3851 return TextureStage::CS_constant;
3855 case EggTexture::CS_texture:
3856 return TextureStage::CS_texture;
3858 case EggTexture::CS_constant:
3859 return TextureStage::CS_constant;
3861 case EggTexture::CS_primary_color:
3862 return TextureStage::CS_primary_color;
3864 case EggTexture::CS_previous:
3865 return TextureStage::CS_previous;
3867 case EggTexture::CS_constant_color_scale:
3868 return TextureStage::CS_constant_color_scale;
3870 case EggTexture::CS_last_saved_result:
3871 return TextureStage::CS_last_saved_result;
3874 return TextureStage::CS_undefined;
3881TextureStage::CombineOperand EggLoader::
3882get_combine_operand(
const EggTexture *egg_tex,
3883 EggTexture::CombineChannel channel,
int n) {
3884 switch (egg_tex->get_combine_operand(channel, n)) {
3885 case EggTexture::CO_unspecified:
3886 if (channel == EggTexture::CC_rgb) {
3889 return n < 2 ? TextureStage::CO_src_color : TextureStage::CO_src_alpha;
3892 return TextureStage::CO_src_alpha;
3895 case EggTexture::CO_src_color:
3896 return TextureStage::CO_src_color;
3898 case EggTexture::CO_one_minus_src_color:
3899 return TextureStage::CO_one_minus_src_color;
3901 case EggTexture::CO_src_alpha:
3902 return TextureStage::CO_src_alpha;
3904 case EggTexture::CO_one_minus_src_alpha:
3905 return TextureStage::CO_one_minus_src_alpha;
3908 return TextureStage::CO_undefined;
3915ColorBlendAttrib::Mode EggLoader::
3916get_color_blend_mode(EggGroup::BlendMode mode) {
3918 case EggGroup::BM_unspecified:
3919 case EggGroup::BM_none:
3920 return ColorBlendAttrib::M_none;
3921 case EggGroup::BM_add:
3922 return ColorBlendAttrib::M_add;
3923 case EggGroup::BM_subtract:
3924 return ColorBlendAttrib::M_subtract;
3925 case EggGroup::BM_inv_subtract:
3926 return ColorBlendAttrib::M_inv_subtract;
3927 case EggGroup::BM_min:
3928 return ColorBlendAttrib::M_min;
3929 case EggGroup::BM_max:
3930 return ColorBlendAttrib::M_max;
3933 return ColorBlendAttrib::M_none;
3940ColorBlendAttrib::Operand EggLoader::
3941get_color_blend_operand(EggGroup::BlendOperand operand) {
3943 case EggGroup::BO_zero:
3944 return ColorBlendAttrib::O_zero;
3945 case EggGroup::BO_unspecified:
3946 case EggGroup::BO_one:
3947 return ColorBlendAttrib::O_one;
3948 case EggGroup::BO_incoming_color:
3949 return ColorBlendAttrib::O_incoming_color;
3950 case EggGroup::BO_one_minus_incoming_color:
3951 return ColorBlendAttrib::O_one_minus_incoming_color;
3952 case EggGroup::BO_fbuffer_color:
3953 return ColorBlendAttrib::O_fbuffer_color;
3954 case EggGroup::BO_one_minus_fbuffer_color:
3955 return ColorBlendAttrib::O_one_minus_fbuffer_color;
3956 case EggGroup::BO_incoming_alpha:
3957 return ColorBlendAttrib::O_incoming_alpha;
3958 case EggGroup::BO_one_minus_incoming_alpha:
3959 return ColorBlendAttrib::O_one_minus_incoming_alpha;
3960 case EggGroup::BO_fbuffer_alpha:
3961 return ColorBlendAttrib::O_fbuffer_alpha;
3962 case EggGroup::BO_one_minus_fbuffer_alpha:
3963 return ColorBlendAttrib::O_one_minus_fbuffer_alpha;
3964 case EggGroup::BO_constant_color:
3965 return ColorBlendAttrib::O_constant_color;
3966 case EggGroup::BO_one_minus_constant_color:
3967 return ColorBlendAttrib::O_one_minus_constant_color;
3968 case EggGroup::BO_constant_alpha:
3969 return ColorBlendAttrib::O_constant_alpha;
3970 case EggGroup::BO_one_minus_constant_alpha:
3971 return ColorBlendAttrib::O_one_minus_constant_alpha;
3972 case EggGroup::BO_incoming_color_saturate:
3973 return ColorBlendAttrib::O_incoming_color_saturate;
3974 case EggGroup::BO_color_scale:
3975 return ColorBlendAttrib::O_color_scale;
3976 case EggGroup::BO_one_minus_color_scale:
3977 return ColorBlendAttrib::O_one_minus_color_scale;
3978 case EggGroup::BO_alpha_scale:
3979 return ColorBlendAttrib::O_alpha_scale;
3980 case EggGroup::BO_one_minus_alpha_scale:
3981 return ColorBlendAttrib::O_one_minus_alpha_scale;
3984 return ColorBlendAttrib::O_zero;
3990bool EggLoader::VertexPoolTransform::
3991operator < (
const EggLoader::VertexPoolTransform &other)
const {
3992 if (_vertex_pool != other._vertex_pool) {
3993 return _vertex_pool < other._vertex_pool;
3995 int compare = _transform.compare_to(other._transform, 0.001);
4000 if (_bake_in_uvs.size() != other._bake_in_uvs.size()) {
4001 return _bake_in_uvs.size() < other._bake_in_uvs.size();
4004 BakeInUVs::const_iterator ai, bi;
4005 ai = _bake_in_uvs.begin();
4006 bi = other._bake_in_uvs.begin();
4007 while (ai != _bake_in_uvs.end()) {
4008 nassertr(bi != other._bake_in_uvs.end(),
false);
4009 if ((*ai) != (*bi)) {
4010 return (*ai) < (*bi);
4015 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.
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...
virtual void xform(const LMatrix4 &mat)
Transforms the solid by the indicated matrix.
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...
virtual void xform(const LMatrix4 &mat)
Transforms the solid by the indicated matrix.
static ConstPointerTo< RenderAttrib > make_vertex()
Constructs a new ColorAttrib object that indicates geometry should be rendered according to its own v...
static ConstPointerTo< RenderAttrib > make_flat(const LColor &color)
Constructs a new ColorAttrib object that indicates geometry should be rendered in the indicated color...
static ConstPointerTo< RenderAttrib > make(Mode mode)
Constructs a new ColorBlendAttrib object.
static ConstPointerTo< RenderEffect > make()
Constructs a new DecalEffect object.
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.
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.
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 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...
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...
This corresponds to a a <Bundle> entry.
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.
const LVecBase4d & get_aux() const
Returns the auxiliary data quadruple.
A collection of vertices.
int remove_unused_vertices()
Removes all vertices from the pool that are not referenced by at least one primitive.
EggVertex * create_unique_vertex(const EggVertex ©)
Creates a new vertex in the pool that is a copy of the indicated one and returns it.
const LTexCoord3d & get_uvw() const
Returns the texture coordinate triple, if get_num_dimensions() is 3.
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.
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.
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.
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...
A container for geometry primitives.
Encodes a string name in a hash table, mapping it to a pointer.
set_texture_num_views
Specifies the expected number of views to load for the texture.
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.
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 add_child(PandaNode *child_node, int sort=0, Thread *current_thread=Thread::get_current_thread())
Adds a new child to the node.
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.
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...
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...
static SparseArray lower_on(int on_bits)
Returns a SparseArray whose lower on_bits bits are on.
static ConstPointerTo< RenderAttrib > make()
Constructs a new TextureAttrib object that does nothing.
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
string downcase(const string &s)
Returns the input string with all uppercase letters converted to lowercase.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.