28 #include "config_util.h"
54 void MaxToEggConverter::reset() {
81 _options->_path_replace->_path_directory = fn.
get_dirname();
84 if (_egg_data->get_coordinate_system() == CS_default) {
92 Interval anim_range = _options->_max_interface->GetAnimRange();
93 int start_frame = anim_range.Start()/GetTicksPerFrame();
94 int end_frame = anim_range.End()/GetTicksPerFrame();
96 if (!_options->_export_all_frames) {
97 if (_options->_start_frame < start_frame) _options->_start_frame = start_frame;
98 if (_options->_start_frame > end_frame) _options->_start_frame = end_frame;
99 if (_options->_end_frame < start_frame) _options->_end_frame = start_frame;
100 if (_options->_end_frame > end_frame) _options->_end_frame = end_frame;
101 if (_options->_end_frame < _options->_start_frame) _options->_end_frame = _options->_start_frame;
102 start_frame = _options->_start_frame;
103 end_frame = _options->_end_frame;
107 int output_frame_rate = GetFrameRate();
111 if (_options->_export_whole_scene) {
112 _tree._export_mesh =
false;
115 _tree._export_mesh =
true;
116 all_ok = _tree.
build_complete_hierarchy(_options->_max_interface->GetRootNode(), &_options->_node_list.front(), _options->_node_list.size());
120 switch (_options->_anim_type) {
121 case MaxEggOptions::AT_pose:
126 _current_frame = start_frame;
127 all_ok = convert_hierarchy(_egg_data);
130 case MaxEggOptions::AT_model:
133 all_ok = convert_char_model();
136 case MaxEggOptions::AT_chan:
138 all_ok = convert_char_chan(start_frame, end_frame, frame_inc,
142 case MaxEggOptions::AT_both:
144 _options->_anim_type = MaxEggOptions::AT_model;
145 if (!convert_char_model()) {
148 _options->_anim_type = MaxEggOptions::AT_chan;
149 if (!convert_char_chan(start_frame, end_frame, frame_inc,
150 output_frame_rate)) {
154 _options->_anim_type = MaxEggOptions::AT_both;
161 reparent_decals(_egg_data);
165 _egg_data->recompute_tangent_binormal_auto();
166 _egg_data->remove_unused_vertices(
true);
169 _options->_successful = all_ok;
177 return _egg_data->write_egg(fn);
189 bool MaxToEggConverter::
190 convert_char_model() {
191 std::string character_name =
"character";
192 _current_frame = _options->_start_frame;
195 _egg_data->add_child(char_node);
196 char_node->set_dart_type(EggGroup::DT_default);
198 return convert_hierarchy(char_node);
208 bool MaxToEggConverter::
209 convert_char_chan(
double start_frame,
double end_frame,
double frame_inc,
210 double output_frame_rate) {
211 std::string character_name =
"character";
214 _egg_data->add_child(root_table_node);
216 bundle_node->set_table_type(EggTable::TT_bundle);
223 _tree._fps = output_frame_rate / frame_inc;
224 _tree.
clear_egg(_egg_data, NULL, skeleton_node);
237 TimeValue frame = start_frame;
238 TimeValue frame_stop = end_frame;
239 while (frame <= frame_stop) {
240 _current_frame = frame;
241 for (i = 0; i < num_nodes; i++) {
248 if (node_desc->_parent && node_desc->_parent->
is_joint()) {
251 get_joint_transform(max_node, node_desc->_parent->
get_max_node(),
254 get_joint_transform(max_node, NULL, tgroup);
271 for (i = 0; i < num_nodes; i++) {
287 bool MaxToEggConverter::
291 _tree.
clear_egg(_egg_data, egg_root, NULL);
293 if (!process_model_node(_tree.
get_node(i))) {
308 bool MaxToEggConverter::
325 state = max_node->EvalWorldState(_current_frame * GetTicksPerFrame());
331 if (_options->_anim_type == MaxEggOptions::AT_model) {
332 get_joint_transform(max_node, egg_group);
337 TriObject *myMaxTriObject;
340 switch( state.obj->SuperClassID() ){
342 case GEOMOBJECT_CLASS_ID:
344 get_transform(max_node, egg_group);
347 if (!state.obj->CanConvertToType(Class_ID(TRIOBJ_CLASS_ID, 0))) {
351 myMaxTriObject = (TriObject *) state.obj->ConvertToType(time, Class_ID(TRIOBJ_CLASS_ID, 0 ));
357 max_mesh = myMaxTriObject->GetMesh();
358 make_polyset(max_node, &max_mesh, egg_group);
360 if (myMaxTriObject != state.obj)
361 delete myMaxTriObject;
365 if (state.obj->ClassID() == EDITABLE_SURF_CLASS_ID) {
367 if (GetNURBSSet(state.obj, time, getSet, TRUE)) {
368 NURBSObject *nObj = getSet.GetNURBSObject(0);
369 if (nObj->GetType() == kNCVCurve) {
372 get_transform(max_node, egg_group);
373 make_nurbs_curve(max_node, (NURBSCVCurve *)nObj,
380 case CAMERA_CLASS_ID:
386 case HELPER_CLASS_ID:
388 if (state.obj->ClassID() == Class_ID(POINTHELP_CLASS_ID, 0)) {
391 get_transform(max_node, egg_group);
415 void MaxToEggConverter::
416 get_transform(INode *max_node,
EggGroup *egg_group) {
417 if (_options->_anim_type == MaxEggOptions::AT_model) {
429 Matrix3 pivot = max_node->GetNodeTM(_current_frame * GetTicksPerFrame());
432 Point3 row0 = pivot.GetRow(0);
433 Point3 row1 = pivot.GetRow(1);
434 Point3 row2 = pivot.GetRow(2);
435 Point3 row3 = pivot.GetRow(3);
437 LMatrix4d m4d(row0.x, row0.y, row0.z, 0.0f,
438 row1.x, row1.y, row1.z, 0.0f,
439 row2.x, row2.y, row2.z, 0.0f,
440 row3.x, row3.y, row3.z, 1.0f );
459 get_object_transform(INode *max_node) {
463 Matrix3 pivot = max_node->GetObjectTM(_current_frame * GetTicksPerFrame());
465 Point3 row0 = pivot.GetRow(0);
466 Point3 row1 = pivot.GetRow(1);
467 Point3 row2 = pivot.GetRow(2);
468 Point3 row3 = pivot.GetRow(3);
470 LMatrix4d m4d(row0.x, row0.y, row0.z, 0.0f,
471 row1.x, row1.y, row1.z, 0.0f,
472 row2.x, row2.y, row2.z, 0.0f,
473 row3.x, row3.y, row3.z, 1.0f );
487 void MaxToEggConverter::
488 get_joint_transform(INode *max_node,
EggGroup *egg_group) {
496 Matrix3 pivot = max_node->GetNodeTM(_current_frame * GetTicksPerFrame());
497 Point3 row0 = pivot.GetRow(0);
498 Point3 row1 = pivot.GetRow(1);
499 Point3 row2 = pivot.GetRow(2);
500 Point3 row3 = pivot.GetRow(3);
502 LMatrix4d m4d(row0.x, row0.y, row0.z, 0.0f,
503 row1.x, row1.y, row1.z, 0.0f,
504 row2.x, row2.y, row2.z, 0.0f,
505 row3.x, row3.y, row3.z, 1.0f );
527 void MaxToEggConverter::
528 get_joint_transform(INode *max_node, INode *parent_node,
EggGroup *egg_group) {
536 Matrix3 pivot = max_node->GetNodeTM(_current_frame * GetTicksPerFrame());
537 Point3 row0 = pivot.GetRow(0);
538 Point3 row1 = pivot.GetRow(1);
539 Point3 row2 = pivot.GetRow(2);
540 Point3 row3 = pivot.GetRow(3);
542 LMatrix4d m4d(row0.x, row0.y, row0.z, 0.0f,
543 row1.x, row1.y, row1.z, 0.0f,
544 row2.x, row2.y, row2.z, 0.0f,
545 row3.x, row3.y, row3.z, 1.0f );
548 Matrix3 parent_pivot = parent_node->GetNodeTM(_current_frame * GetTicksPerFrame());
550 row0 = parent_pivot.GetRow(0);
551 row1 = parent_pivot.GetRow(1);
552 row2 = parent_pivot.GetRow(2);
553 row3 = parent_pivot.GetRow(3);
555 LMatrix4d pi_m4d(row0.x, row0.y, row0.z, 0.0f,
556 row1.x, row1.y, row1.z, 0.0f,
557 row2.x, row2.y, row2.z, 0.0f,
558 row3.x, row3.y, row3.z, 1.0f );
564 pi_m4d.invert_in_place();
579 bool MaxToEggConverter::
580 make_nurbs_curve(INode *max_node, NURBSCVCurve *curve,
581 TimeValue time,
EggGroup *egg_group)
583 int degree = curve->GetOrder();
584 int cvs = curve->GetNumCVs();
585 int knots = curve->GetNumKnots();
588 if (knots != cvs + degree) {
592 string name = max_node->GetName();
594 string vpool_name = name +
".cvs";
600 egg_curve->
setup(degree, knots);
602 for (i = 0; i < knots; i++)
603 egg_curve->
set_knot(i, curve->GetKnot(i));
607 for (i = 0; i < cvs; i++) {
608 NURBSControlVertex *cv = curve->GetCV(i);
611 sprintf(buf,
"Error getting CV %d", i);
616 cv->GetPosition(time, p4d[0], p4d[1], p4d[2]);
617 p4d = p4d * vertex_frame_inv;
633 void MaxToEggConverter::
634 make_polyset(INode *max_node, Mesh *mesh,
637 mesh->buildNormals();
639 if (mesh->getNumFaces() == 0) {
655 string node_name = max_node->GetName();
656 string vpool_name = node_name +
".verts";
666 LMatrix4d vertex_frame = get_object_transform(max_node) *
670 for (
int iFace=0; iFace < mesh->getNumFaces(); iFace++ ) {
676 Face face = mesh->faces[iFace];
678 const PandaMaterial &pmat = get_panda_material(max_node->GetMtl(), face.getMatID());
681 for (
int iVertex=0; iVertex < 3; iVertex++ ) {
685 Point3 vertex = mesh->getVert(face.v[iVertex]);
686 LPoint3d p3d(vertex.x, vertex.y, vertex.z);
687 p3d = p3d * vertex_frame;
691 Point3 normal = get_max_vertex_normal(mesh, iFace, iVertex);
692 LVector3d n3d(normal.x, normal.y, normal.z);
695 n3d = n3d * vertex_frame;
696 vert.set_normal(n3d);
701 VertColor vertexColor = get_max_vertex_color(mesh, iFace, iVertex);
702 LColor pVC(vertexColor.x, vertexColor.y, vertexColor.z, 1);
711 if (pmat._map_channels.size() == 0) {
714 UVVert uvw = get_max_vertex_texcoord(mesh, iFace, iVertex, 1);
720 for (
int iChan=0; iChan<pmat._map_channels.size(); iChan++) {
721 int channel = pmat._map_channels[iChan];
723 uvname <<
"m" << channel;
724 UVVert uvw = get_max_vertex_texcoord(mesh, iFace, iVertex, channel);
744 for (
int i = 0; i < 3; i++) {
749 LVector3d realNorm = ((points[1] - points[0]).cross(points[2] - points[0]));
750 Point3 maxNormTemp = mesh->getFaceNormal(iFace);
754 if (realNorm.dot(maxNorm) < 0.0) {
759 for (
int i=0; i<pmat._texture_list.size(); i++) {
762 egg_poly->set_color(pmat._color);
771 if (_options->_anim_type == MaxEggOptions::AT_model) {
772 get_vertex_weights(max_node, vpool);
776 UVVert MaxToEggConverter::get_max_vertex_texcoord(Mesh *mesh,
int faceNo,
int vertNo,
int channel) {
779 UVVert uvVert(0,0,0);
780 if(mesh->mapSupport(channel)) {
781 TVFace *pTVFace = mesh->mapFaces(channel);
782 UVVert *pUVVert = mesh->mapVerts(channel);
783 uvVert = pUVVert[pTVFace[faceNo].t[vertNo]];
784 }
else if(mesh->numTVerts > 0) {
785 uvVert = mesh->tVerts[mesh->tvFace[faceNo].t[vertNo]];
790 VertColor MaxToEggConverter::get_max_vertex_color(Mesh *mesh,
int FaceNo,
int VertexNo,
int channel) {
793 if(mesh->mapSupport(channel))
796 TVFace& _vcface = mesh->vcFace[FaceNo];
798 int VertexColorIndex = _vcface.t[VertexNo];
800 vc =mesh->vertCol[VertexColorIndex];
804 TVFace *pTVFace = mesh->mapFaces(channel);
805 vc = mesh->vertCol[pTVFace[FaceNo].t[VertexNo]];
810 VertColor MaxToEggConverter::get_max_vertex_color(Mesh *mesh,
int FaceNo,
int VertexNo)
814 TVFace& _vcface = mesh->vcFace[FaceNo];
816 int VertexColorIndex = _vcface.t[VertexNo];
818 vc =mesh->vertCol[VertexColorIndex];
822 Point3 MaxToEggConverter::get_max_vertex_normal(Mesh *mesh,
int faceNo,
int vertNo)
824 Face f = mesh->faces[faceNo];
825 DWORD smGroup = f.smGroup;
826 int vert = f.getVert(vertNo);
827 RVertex *rv = mesh->getRVertPtr(vert);
834 if (rv->rFlags & SPECIFIED_NORMAL) {
835 vertexNormal = rv->rn.getNormal();
839 else if ((numNormals = rv->rFlags & NORCT_MASK) && smGroup) {
841 if (numNormals == 1) {
842 vertexNormal = rv->rn.getNormal();
848 for (
int i = 0; i < numNormals; i++) {
849 if (rv->ern[i].getSmGroup() & smGroup) {
850 vertexNormal = rv->ern[i].getNormal();
857 vertexNormal = mesh->getFaceNormal(faceNo);
868 void MaxToEggConverter::
871 Modifier *mod = FindSkinModifier(max_node, PHYSIQUE_CLASSID);
876 IPhysiqueExport *pPhysiqueExport = (IPhysiqueExport *)mod->GetInterface(I_PHYINTERFACE);
877 if (pPhysiqueExport) {
879 IPhyContextExport *pContextExport =
880 (IPhyContextExport *)pPhysiqueExport->GetContextInterface(max_node);
881 if (pContextExport) {
883 pContextExport->ConvertToRigid(TRUE);
884 pContextExport->AllowBlending(TRUE);
886 for (vi = vpool->
begin(); vi != vpool->
end(); ++vi) {
891 IPhyVertexExport *pVertexExport =
892 (IPhyVertexExport *)pContextExport->GetVertexInterface(max_vi);
894 int vertexType = pVertexExport->GetVertexType();
897 if(vertexType == RIGID_TYPE) {
899 IPhyRigidVertex *pTypeVertex = (IPhyRigidVertex *)pVertexExport;
900 INode *bone_node = pTypeVertex->GetNode();
902 if (joint_node_desc){
908 else if(vertexType == RIGID_BLENDED_TYPE) {
910 IPhyBlendedRigidVertex *pTypeVertex = (IPhyBlendedRigidVertex *)pVertexExport;
912 for (
int ji = 0; ji < pTypeVertex->GetNumberNodes(); ++ji) {
913 PN_stdfloat weight = pTypeVertex->GetWeight(ji);
915 INode *bone_node = pTypeVertex->GetNode(ji);
917 if (joint_node_desc){
926 pContextExport->ReleaseVertexInterface(pVertexExport);
930 pPhysiqueExport->ReleaseContextInterface(pContextExport);
933 mod->ReleaseInterface(I_PHYINTERFACE, pPhysiqueExport);
938 mod = FindSkinModifier(max_node, SKIN_CLASSID);
940 ISkin *skin = (ISkin*)mod->GetInterface(I_SKIN);
942 ISkinContextData *skinMC = skin->GetContextInterface(max_node);
944 for (vi = vpool->
begin(); vi != vpool->
end(); ++vi) {
948 for (
int ji = 0; ji < skinMC->GetNumAssignedBones(max_vi); ++ji) {
949 PN_stdfloat weight = skinMC->GetBoneWeight(max_vi, ji);
951 INode *bone_node = skin->GetBone(skinMC->GetAssignedBone(max_vi, ji));
953 if (joint_node_desc){
975 const MaxToEggConverter::PandaMaterial &MaxToEggConverter::
976 get_panda_material(Mtl *mtl, MtlID matID) {
978 MaterialMap::iterator it = _material_map.find(mtl);
979 if (it != _material_map.end()) {
983 PandaMaterial &pandaMat = _material_map[mtl];
984 pandaMat._color =
LColor(1,1,1,1);
985 pandaMat._any_diffuse =
false;
986 pandaMat._any_opacity =
false;
987 pandaMat._any_gloss =
false;
988 pandaMat._any_normal =
false;
995 while (( mtl != 0) && (mtl->ClassID() == Class_ID(MULTI_CLASS_ID, 0 ))) {
996 if (matID < mtl->NumSubMtls()) {
997 mtl = mtl->GetSubMtl(matID);
1005 if ((mtl != 0) && (mtl->ClassID() == Class_ID(DMTL_CLASS_ID, 0 ))) {
1006 StdMat *maxMaterial = (StdMat*)mtl;
1007 analyze_diffuse_maps(pandaMat, maxMaterial->GetSubTexmap(ID_DI));
1008 analyze_opacity_maps(pandaMat, maxMaterial->GetSubTexmap(ID_OP));
1009 analyze_gloss_maps(pandaMat, maxMaterial->GetSubTexmap(ID_SP));
1010 if (!pandaMat._any_gloss)
1011 analyze_gloss_maps(pandaMat, maxMaterial->GetSubTexmap(ID_SS));
1012 if (!pandaMat._any_gloss)
1013 analyze_gloss_maps(pandaMat, maxMaterial->GetSubTexmap(ID_SH));
1014 analyze_glow_maps(pandaMat, maxMaterial->GetSubTexmap(ID_SI));
1015 analyze_normal_maps(pandaMat, maxMaterial->GetSubTexmap(ID_BU));
1016 for (
int i=0; i<pandaMat._texture_list.size(); i++) {
1018 pandaMat._texture_list[i] =
1024 if (!pandaMat._any_diffuse) {
1026 Point3 diffuseColor = Point3(maxMaterial->GetDiffuse(0));
1027 pandaMat._color[0] = diffuseColor.x;
1028 pandaMat._color[1] = diffuseColor.y;
1029 pandaMat._color[2] = diffuseColor.z;
1031 if (!pandaMat._any_opacity) {
1032 pandaMat._color[3] = (maxMaterial->GetOpacity(_current_frame * GetTicksPerFrame()));
1034 if (pandaMat._texture_list.size() < 1) {
1038 pandaMat._map_channels.push_back(1);
1051 void MaxToEggConverter::analyze_diffuse_maps(PandaMaterial &pandaMat, Texmap *mat) {
1052 if (mat == 0)
return;
1054 if (mat->ClassID() == Class_ID(RGBMULT_CLASS_ID, 0)) {
1055 for (
int i=0; i<mat->NumSubTexmaps(); i++) {
1056 analyze_diffuse_maps(pandaMat, mat->GetSubTexmap(i));
1061 if (mat->ClassID() == Class_ID(BMTEX_CLASS_ID, 0)) {
1062 pandaMat._any_diffuse =
true;
1065 BitmapTex *diffuseTex = (BitmapTex *)mat;
1073 _options->_path_replace->full_convert_path(filename, get_model_path(),
1075 tex->set_filename(outpath);
1076 tex->set_fullpath(fullpath);
1078 apply_texture_properties(*tex, diffuseTex->GetMapChannel());
1079 add_map_channel(pandaMat, diffuseTex->GetMapChannel());
1081 Bitmap *diffuseBitmap = diffuseTex->GetBitmap(0);
1082 if ( diffuseBitmap && diffuseBitmap->HasAlpha()) {
1083 tex->set_format(EggTexture::F_rgba);
1085 tex->set_format(EggTexture::F_rgb);
1087 tex->set_env_type(EggTexture::ET_modulate);
1089 pandaMat._texture_list.push_back(tex);
1098 void MaxToEggConverter::analyze_opacity_maps(PandaMaterial &pandaMat, Texmap *mat) {
1099 if (mat == 0)
return;
1101 if (mat->ClassID() == Class_ID(RGBMULT_CLASS_ID, 0)) {
1102 for (
int i=0; i<mat->NumSubTexmaps(); i++) {
1103 analyze_opacity_maps(pandaMat, mat->GetSubTexmap(i));
1108 if (mat->ClassID() == Class_ID(BMTEX_CLASS_ID, 0)) {
1109 pandaMat._any_opacity =
true;
1110 BitmapTex *transTex = (BitmapTex *)mat;
1118 _options->_path_replace->full_convert_path(filename, get_model_path(),
1122 for (
int i=0; i<pandaMat._texture_list.size(); i++) {
1124 if ((tex->get_env_type()==EggTexture::ET_modulate)&&(tex->
get_fullpath() == fullpath)) {
1125 tex->set_format(EggTexture::F_rgba);
1131 std::string uvname = get_uv_name(transTex->GetMapChannel());
1132 for (
int i=0; i<pandaMat._texture_list.size(); i++) {
1134 if ((tex->get_env_type()==EggTexture::ET_modulate)&&
1135 (tex->get_format() == EggTexture::F_rgb)&&
1137 tex->set_format(EggTexture::F_rgba);
1146 tex->set_filename(outpath);
1147 tex->set_fullpath(fullpath);
1149 apply_texture_properties(*tex, transTex->GetMapChannel());
1150 add_map_channel(pandaMat, transTex->GetMapChannel());
1153 pandaMat._texture_list.push_back(tex);
1162 void MaxToEggConverter::analyze_glow_maps(PandaMaterial &pandaMat, Texmap *mat) {
1163 if (mat == 0)
return;
1165 if (mat->ClassID() == Class_ID(BMTEX_CLASS_ID, 0)) {
1166 BitmapTex *gtex = (BitmapTex *)mat;
1174 _options->_path_replace->full_convert_path(filename, get_model_path(),
1178 std::string uvname = get_uv_name(gtex->GetMapChannel());
1179 for (
int i=0; i<pandaMat._texture_list.size(); i++) {
1181 if ((tex->get_env_type()==EggTexture::ET_modulate)&&
1182 (tex->get_format() == EggTexture::F_rgb)&&
1184 tex->set_env_type(EggTexture::ET_modulate_glow);
1185 tex->set_format(EggTexture::F_rgba);
1195 tex->set_filename(outpath);
1196 tex->set_fullpath(fullpath);
1197 apply_texture_properties(*tex, gtex->GetMapChannel());
1198 add_map_channel(pandaMat, gtex->GetMapChannel());
1201 pandaMat._texture_list.push_back(tex);
1210 void MaxToEggConverter::analyze_gloss_maps(PandaMaterial &pandaMat, Texmap *mat) {
1211 if (mat == 0)
return;
1213 if (mat->ClassID() == Class_ID(BMTEX_CLASS_ID, 0)) {
1214 pandaMat._any_gloss =
true;
1215 BitmapTex *gtex = (BitmapTex *)mat;
1223 _options->_path_replace->full_convert_path(filename, get_model_path(),
1227 std::string uvname = get_uv_name(gtex->GetMapChannel());
1228 for (
int i=0; i<pandaMat._texture_list.size(); i++) {
1230 if ((tex->get_env_type()==EggTexture::ET_modulate)&&
1231 (tex->get_format() == EggTexture::F_rgb)&&
1233 tex->set_env_type(EggTexture::ET_modulate_gloss);
1234 tex->set_format(EggTexture::F_rgba);
1244 tex->set_filename(outpath);
1245 tex->set_fullpath(fullpath);
1246 apply_texture_properties(*tex, gtex->GetMapChannel());
1247 add_map_channel(pandaMat, gtex->GetMapChannel());
1250 pandaMat._texture_list.push_back(tex);
1259 void MaxToEggConverter::analyze_normal_maps(PandaMaterial &pandaMat, Texmap *mat) {
1260 if (mat == 0)
return;
1262 if (mat->ClassID() == Class_ID(BMTEX_CLASS_ID, 0)) {
1263 pandaMat._any_normal =
true;
1264 BitmapTex *ntex = (BitmapTex *)mat;
1272 _options->_path_replace->full_convert_path(filename, get_model_path(),
1277 tex->set_filename(outpath);
1278 tex->set_fullpath(fullpath);
1279 apply_texture_properties(*tex, ntex->GetMapChannel());
1280 add_map_channel(pandaMat, ntex->GetMapChannel());
1283 pandaMat._texture_list.push_back(tex);
1294 for (
int i=0; i<pandaMat._map_channels.size(); i++) {
1295 if (pandaMat._map_channels[i] == chan) {
1299 pandaMat._map_channels.push_back(chan);
1307 std::string MaxToEggConverter::generate_tex_name() {
1309 name_strm <<
"Tex" << ++_cur_tref;
1310 return name_strm.str();
1318 std::string MaxToEggConverter::get_uv_name(
int channel) {
1320 uvname <<
"m" << channel;
1321 return uvname.str();
1331 void MaxToEggConverter::
1332 apply_texture_properties(
EggTexture &tex,
int channel) {
1340 tex.set_minfilter(EggTexture::FT_linear_mipmap_linear);
1341 tex.set_magfilter(EggTexture::FT_linear);
1343 EggTexture::WrapMode wrap_u = EggTexture::WM_repeat;
1344 EggTexture::WrapMode wrap_v = EggTexture::WM_repeat;
1346 tex.set_wrap_u(wrap_u);
1347 tex.set_wrap_v(wrap_v);
1361 bool MaxToEggConverter::
1370 EggGroupNode::iterator ci;
1371 for (ci = egg_parent->begin(); ci != egg_parent->end(); ++ci) {
1373 if (child->
is_of_type(EggGroup::get_class_type())) {
1376 if (decal_base != (
EggNode *)NULL) {
1381 decal_base = child_group;
1385 decal_children.push_back(child_group);
1390 if (decal_base == (
EggGroup *)NULL) {
1391 if (!decal_children.empty()) {
1396 if (decal_children.empty()) {
1405 for (di = decal_children.begin(); di != decal_children.end(); ++di) {
1411 decal_base->set_decal_flag(
true);
1416 for (ci = egg_parent->begin(); ci != egg_parent->end(); ++ci) {
1418 if (child->
is_of_type(EggGroupNode::get_class_type())) {
1420 if (!reparent_decals(child_group)) {
1429 Modifier* MaxToEggConverter::FindSkinModifier (INode* node,
const Class_ID &type)
1432 Object* pObj = node->GetObjectRef();
1433 if (!pObj)
return NULL;
1436 while (pObj->SuperClassID() == GEN_DERIVOB_CLASS_ID) {
1438 IDerivedObject* pDerObj =
static_cast<IDerivedObject*
>(pObj);
1441 for (
int stackId = 0; stackId < pDerObj->NumModifiers(); ++stackId) {
1443 Modifier* mod = pDerObj->GetModifier(stackId);
1446 if (mod->ClassID() == type )
1451 pObj = pDerObj->GetObjRef();
void setup(int order, int num_knots)
Prepares a new curve definition with the indicated order and number of knots.
bool convert(MaxEggOptions *options)
Fills up the egg_data structure according to the global Max model data.
This is an iterator adaptor that converts any iterator that returns a pair (e.g.
EggGroup * get_egg_group(MaxNodeDesc *node_desc)
Returns the EggGroupNode corresponding to the group or joint for the indicated node.
EggTexture * create_unique_texture(const EggTexture ©, int eq)
Creates a new texture if there is not already one equivalent (according to eq, see EggTexture::is_equ...
bool add_data(const LMatrix4d &mat)
Adds a new matrix to the table, by adding a new row to each of the subtables.
This is a 4-by-4 transform matrix.
void add_texture(EggTexture *texture)
Applies the indicated texture to the primitive.
void set_pos(double pos)
Sets the vertex position.
bool is_joint() const
Returns true if the node should be treated as a joint by the converter.
A base class for nodes in the hierarchy that are not leaf nodes.
This is a four-component point in space.
EggXfmSAnim * get_egg_anim(MaxNodeDesc *node_desc)
Returns the anim table corresponding to the joint for the indicated node.
Defines a texture map that may be applied to geometry.
void set_vertex(int index, EggVertex *vertex)
Replaces a particular vertex based on its index number in the list of vertices.
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
LVertexd get_pos3() const
Valid if get_num_dimensions() returns 3 or 4.
const LMatrix4d & get_vertex_frame_inv() const
Returns the inverse of the matrix returned by get_vertex_frame().
bool is_node_joint() const
Returns true if the node is the parent or ancestor of a joint.
MaxNodeDesc * get_node(int n) const
Returns the nth node in the hierarchy, in an arbitrary ordering.
void clear()
Removes all textures from the collection.
bool build_complete_hierarchy(INode *root, ULONG *selection_list, int len)
Walks through the complete Max hierarchy and builds up the corresponding tree.
void set_alpha_fullpath(const Filename &fullpath)
Records the full pathname to the file, for the benefit of get_alpha_fullpath().
MaxNodeDesc * find_joint(INode *max_node)
The recursive implementation of build_node().
This is a two-component point in space.
INode * get_max_node() const
Returns the INode associated with this node.
string get_dirname() const
Returns the directory part of the filename.
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...
This is the primary interface into all the egg data, and the root of the egg file structure...
void set_knot(int k, double value)
Resets the value of the indicated knot as indicated.
int get_external_index() const
Returns the number set by set_external_index().
void set_coordinate_system(CoordinateSystem coordsys)
Changes the coordinate system of the EggData.
bool remove_object_type(const string &object_type)
Removes the first instance of the indicated object type from the group if it is present.
This is our own Panda specialization on the default STL vector.
void set_bface_flag(bool flag)
Sets the backfacing flag of the polygon.
void set_alpha_filename(const Filename &filename)
Specifies a separate file that will be loaded in with the 1- or 3-component texture and applied as th...
The main glue of the egg hierarchy, this corresponds to the <Group>, <Instance>, and <Joint> type nod...
const string & get_uv_name() const
Returns the texcoord name that has been specified for this texture, or the empty string if no texcoor...
void clear_egg(EggData *egg_data, EggGroupNode *egg_root, EggGroupNode *skeleton_node)
Removes all of the references to generated egg structures from the tree, and prepares the tree for ge...
iterator end() const
Returns an iterator that can be used to traverse through all the vertices in the pool.
The name of a file, such as a texture file or an Egg file.
static const LMatrix4d & ident_mat()
Returns an identity matrix.
Any one-, two-, three-, or four-component vertex, possibly with attributes such as a normal...
This corresponds to an <Xfm$Anim_S$> entry, which is a collection of up to nine <S$Anim> entries that...
const Filename & get_fullpath() const
Returns the full pathname to the file, if it is known; otherwise, returns the same thing as get_filen...
void set_uv_name(const string &uv_name)
Specifies the named set of texture coordinates that this texture will use when it is applied to geome...
Describes a single instance of a node in the Max scene graph, relating it to the corresponding egg st...
int get_num_nodes() const
Returns the total number of nodes in the hierarchy, not counting the root node.
A parametric NURBS curve.
void optimize()
Optimizes the table by collapsing redundant sub-tables.
bool has_max_node() const
Returns true if a Max INode has been associated with this node, false otherwise.
bool has_object_type(const string &object_type) const
Returns true if the indicated object type has been added to the group, or false otherwise.
This is the base class for all three-component vectors and points.
This is a three-component vector distance (as opposed to a three-component point, which represents a ...
This is a three-component point in space (as opposed to a three-component vector, which represents a ...
EggNode * add_child(EggNode *node)
Adds the indicated child to the group and returns it.
This class supervises the construction of an EggData structure from a Max model.
A base class for things that may be directly added into the egg hierarchy.
void ref_vertex(EggVertex *vert, double membership=1.0)
Adds the vertex to the set of those referenced by the group, at the indicated membership level...
static Filename from_os_specific_w(const wstring &os_specific, Type type=T_general)
The wide-string variant of from_os_specific().
EggVertex * get_vertex(int index) const
Returns a particular index based on its index number.
void set_uv(const LTexCoordd &texCoord)
Replaces the unnamed UV coordinate pair on the vertex with the indicated value.
EggVertex * create_unique_vertex(const EggVertex ©)
Creates a new vertex in the pool that is a copy of the indicated one and returns it.
A collection of vertices.
EggVertex * add_vertex(EggVertex *vertex)
Adds the indicated vertex to the end of the primitive's list of vertices, and returns it...
const LMatrix4d & get_node_frame_inv() const
Returns the inverse of the matrix returned by get_node_frame().
iterator begin() const
Returns an iterator that can be used to traverse through all the vertices in the pool.
static Filename from_os_specific(const string &os_specific, Type type=T_general)
This named constructor returns a Panda-style filename (that is, using forward slashes, and no drive letter) based on the supplied filename string that describes a filename in the local system conventions (for instance, on Windows, it may use backslashes or begin with a drive letter and a colon).