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 );
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) {
595 wcstombs(mbname, max_node->GetName(), 1023);
598 string name = max_node->GetName();
601 string vpool_name = name +
".cvs";
607 egg_curve->
setup(degree, knots);
609 for (i = 0; i < knots; i++)
610 egg_curve->
set_knot(i, curve->GetKnot(i));
614 for (i = 0; i < cvs; i++) {
615 NURBSControlVertex *cv = curve->GetCV(i);
618 sprintf(buf,
"Error getting CV %d", i);
623 cv->GetPosition(time, p4d[0], p4d[1], p4d[2]);
624 p4d = p4d * vertex_frame_inv;
640 void MaxToEggConverter::
641 make_polyset(INode *max_node, Mesh *mesh,
644 mesh->buildNormals();
646 if (mesh->getNumFaces() == 0) {
665 wcstombs(mbname, max_node->GetName(), 1023);
666 string node_name(mbname);
668 string node_name = max_node->GetName();
671 string vpool_name = node_name +
".verts";
681 LMatrix4d vertex_frame = get_object_transform(max_node) *
685 for (
int iFace=0; iFace < mesh->getNumFaces(); iFace++ ) {
691 Face face = mesh->faces[iFace];
693 const PandaMaterial &pmat = get_panda_material(max_node->GetMtl(), face.getMatID());
696 for (
int iVertex=0; iVertex < 3; iVertex++ ) {
700 Point3 vertex = mesh->getVert(face.v[iVertex]);
701 LPoint3d p3d(vertex.x, vertex.y, vertex.z);
702 p3d = p3d * vertex_frame;
706 Point3 normal = get_max_vertex_normal(mesh, iFace, iVertex);
707 LVector3d n3d(normal.x, normal.y, normal.z);
710 n3d = n3d * vertex_frame;
711 vert.set_normal(n3d);
716 VertColor vertexColor = get_max_vertex_color(mesh, iFace, iVertex);
717 LColor pVC(vertexColor.x, vertexColor.y, vertexColor.z, 1);
726 if (pmat._map_channels.size() == 0) {
729 UVVert uvw = get_max_vertex_texcoord(mesh, iFace, iVertex, 1);
735 for (
int iChan=0; iChan<pmat._map_channels.size(); iChan++) {
736 int channel = pmat._map_channels[iChan];
738 uvname <<
"m" << channel;
739 UVVert uvw = get_max_vertex_texcoord(mesh, iFace, iVertex, channel);
759 for (
int i = 0; i < 3; i++) {
764 LVector3d realNorm = ((points[1] - points[0]).cross(points[2] - points[0]));
765 Point3 maxNormTemp = mesh->getFaceNormal(iFace);
769 if (realNorm.dot(maxNorm) < 0.0) {
774 for (
int i=0; i<pmat._texture_list.size(); i++) {
777 egg_poly->set_color(pmat._color);
786 if (_options->_anim_type == MaxEggOptions::AT_model) {
787 get_vertex_weights(max_node, vpool);
791 UVVert MaxToEggConverter::get_max_vertex_texcoord(Mesh *mesh,
int faceNo,
int vertNo,
int channel) {
794 UVVert uvVert(0,0,0);
795 if(mesh->mapSupport(channel)) {
796 TVFace *pTVFace = mesh->mapFaces(channel);
797 UVVert *pUVVert = mesh->mapVerts(channel);
798 uvVert = pUVVert[pTVFace[faceNo].t[vertNo]];
799 }
else if(mesh->numTVerts > 0) {
800 uvVert = mesh->tVerts[mesh->tvFace[faceNo].t[vertNo]];
805 VertColor MaxToEggConverter::get_max_vertex_color(Mesh *mesh,
int FaceNo,
int VertexNo,
int channel) {
808 if(mesh->mapSupport(channel))
811 TVFace& _vcface = mesh->vcFace[FaceNo];
813 int VertexColorIndex = _vcface.t[VertexNo];
815 vc =mesh->vertCol[VertexColorIndex];
819 TVFace *pTVFace = mesh->mapFaces(channel);
820 vc = mesh->vertCol[pTVFace[FaceNo].t[VertexNo]];
825 VertColor MaxToEggConverter::get_max_vertex_color(Mesh *mesh,
int FaceNo,
int VertexNo)
829 TVFace& _vcface = mesh->vcFace[FaceNo];
831 int VertexColorIndex = _vcface.t[VertexNo];
833 vc =mesh->vertCol[VertexColorIndex];
837 Point3 MaxToEggConverter::get_max_vertex_normal(Mesh *mesh,
int faceNo,
int vertNo)
839 Face f = mesh->faces[faceNo];
840 DWORD smGroup = f.smGroup;
841 int vert = f.getVert(vertNo);
842 RVertex *rv = mesh->getRVertPtr(vert);
849 if (rv->rFlags & SPECIFIED_NORMAL) {
850 vertexNormal = rv->rn.getNormal();
854 else if ((numNormals = rv->rFlags & NORCT_MASK) && smGroup) {
856 if (numNormals == 1) {
857 vertexNormal = rv->rn.getNormal();
863 for (
int i = 0; i < numNormals; i++) {
864 if (rv->ern[i].getSmGroup() & smGroup) {
865 vertexNormal = rv->ern[i].getNormal();
872 vertexNormal = mesh->getFaceNormal(faceNo);
883 void MaxToEggConverter::
886 Modifier *mod = FindSkinModifier(max_node, PHYSIQUE_CLASSID);
891 IPhysiqueExport *pPhysiqueExport = (IPhysiqueExport *)mod->GetInterface(I_PHYINTERFACE);
892 if (pPhysiqueExport) {
894 IPhyContextExport *pContextExport =
895 (IPhyContextExport *)pPhysiqueExport->GetContextInterface(max_node);
896 if (pContextExport) {
898 pContextExport->ConvertToRigid(TRUE);
899 pContextExport->AllowBlending(TRUE);
901 for (vi = vpool->
begin(); vi != vpool->
end(); ++vi) {
906 IPhyVertexExport *pVertexExport =
907 (IPhyVertexExport *)pContextExport->GetVertexInterface(max_vi);
909 int vertexType = pVertexExport->GetVertexType();
912 if(vertexType == RIGID_TYPE) {
914 IPhyRigidVertex *pTypeVertex = (IPhyRigidVertex *)pVertexExport;
915 INode *bone_node = pTypeVertex->GetNode();
917 if (joint_node_desc){
923 else if(vertexType == RIGID_BLENDED_TYPE) {
925 IPhyBlendedRigidVertex *pTypeVertex = (IPhyBlendedRigidVertex *)pVertexExport;
927 for (
int ji = 0; ji < pTypeVertex->GetNumberNodes(); ++ji) {
928 PN_stdfloat weight = pTypeVertex->GetWeight(ji);
930 INode *bone_node = pTypeVertex->GetNode(ji);
932 if (joint_node_desc){
941 pContextExport->ReleaseVertexInterface(pVertexExport);
945 pPhysiqueExport->ReleaseContextInterface(pContextExport);
948 mod->ReleaseInterface(I_PHYINTERFACE, pPhysiqueExport);
953 mod = FindSkinModifier(max_node, SKIN_CLASSID);
955 ISkin *skin = (ISkin*)mod->GetInterface(I_SKIN);
957 ISkinContextData *skinMC = skin->GetContextInterface(max_node);
959 for (vi = vpool->
begin(); vi != vpool->
end(); ++vi) {
963 for (
int ji = 0; ji < skinMC->GetNumAssignedBones(max_vi); ++ji) {
964 PN_stdfloat weight = skinMC->GetBoneWeight(max_vi, ji);
966 INode *bone_node = skin->GetBone(skinMC->GetAssignedBone(max_vi, ji));
968 if (joint_node_desc){
990 const MaxToEggConverter::PandaMaterial &MaxToEggConverter::
991 get_panda_material(Mtl *mtl, MtlID matID) {
993 MaterialMap::iterator it = _material_map.find(mtl);
994 if (it != _material_map.end()) {
998 PandaMaterial &pandaMat = _material_map[mtl];
999 pandaMat._color =
LColor(1,1,1,1);
1000 pandaMat._any_diffuse =
false;
1001 pandaMat._any_opacity =
false;
1002 pandaMat._any_gloss =
false;
1003 pandaMat._any_normal =
false;
1010 while (( mtl != 0) && (mtl->ClassID() == Class_ID(MULTI_CLASS_ID, 0 ))) {
1011 if (matID < mtl->NumSubMtls()) {
1012 mtl = mtl->GetSubMtl(matID);
1020 if ((mtl != 0) && (mtl->ClassID() == Class_ID(DMTL_CLASS_ID, 0 ))) {
1021 StdMat *maxMaterial = (StdMat*)mtl;
1022 analyze_diffuse_maps(pandaMat, maxMaterial->GetSubTexmap(ID_DI));
1023 analyze_opacity_maps(pandaMat, maxMaterial->GetSubTexmap(ID_OP));
1024 analyze_gloss_maps(pandaMat, maxMaterial->GetSubTexmap(ID_SP));
1025 if (!pandaMat._any_gloss)
1026 analyze_gloss_maps(pandaMat, maxMaterial->GetSubTexmap(ID_SS));
1027 if (!pandaMat._any_gloss)
1028 analyze_gloss_maps(pandaMat, maxMaterial->GetSubTexmap(ID_SH));
1029 analyze_glow_maps(pandaMat, maxMaterial->GetSubTexmap(ID_SI));
1030 analyze_normal_maps(pandaMat, maxMaterial->GetSubTexmap(ID_BU));
1031 for (
int i=0; i<pandaMat._texture_list.size(); i++) {
1033 pandaMat._texture_list[i] =
1039 if (!pandaMat._any_diffuse) {
1041 Point3 diffuseColor = Point3(maxMaterial->GetDiffuse(0));
1042 pandaMat._color[0] = diffuseColor.x;
1043 pandaMat._color[1] = diffuseColor.y;
1044 pandaMat._color[2] = diffuseColor.z;
1046 if (!pandaMat._any_opacity) {
1047 pandaMat._color[3] = (maxMaterial->GetOpacity(_current_frame * GetTicksPerFrame()));
1049 if (pandaMat._texture_list.size() < 1) {
1053 pandaMat._map_channels.push_back(1);
1066 void MaxToEggConverter::analyze_diffuse_maps(PandaMaterial &pandaMat, Texmap *mat) {
1067 if (mat == 0)
return;
1069 if (mat->ClassID() == Class_ID(RGBMULT_CLASS_ID, 0)) {
1070 for (
int i=0; i<mat->NumSubTexmaps(); i++) {
1071 analyze_diffuse_maps(pandaMat, mat->GetSubTexmap(i));
1076 if (mat->ClassID() == Class_ID(BMTEX_CLASS_ID, 0)) {
1077 pandaMat._any_diffuse =
true;
1080 BitmapTex *diffuseTex = (BitmapTex *)mat;
1088 _options->_path_replace->full_convert_path(filename, get_model_path(),
1090 tex->set_filename(outpath);
1093 apply_texture_properties(*tex, diffuseTex->GetMapChannel());
1094 add_map_channel(pandaMat, diffuseTex->GetMapChannel());
1096 Bitmap *diffuseBitmap = diffuseTex->GetBitmap(0);
1097 if ( diffuseBitmap && diffuseBitmap->HasAlpha()) {
1098 tex->set_format(EggTexture::F_rgba);
1100 tex->set_format(EggTexture::F_rgb);
1102 tex->set_env_type(EggTexture::ET_modulate);
1104 pandaMat._texture_list.push_back(tex);
1113 void MaxToEggConverter::analyze_opacity_maps(PandaMaterial &pandaMat, Texmap *mat) {
1114 if (mat == 0)
return;
1116 if (mat->ClassID() == Class_ID(RGBMULT_CLASS_ID, 0)) {
1117 for (
int i=0; i<mat->NumSubTexmaps(); i++) {
1118 analyze_opacity_maps(pandaMat, mat->GetSubTexmap(i));
1123 if (mat->ClassID() == Class_ID(BMTEX_CLASS_ID, 0)) {
1124 pandaMat._any_opacity =
true;
1125 BitmapTex *transTex = (BitmapTex *)mat;
1133 _options->_path_replace->full_convert_path(filename, get_model_path(),
1137 for (
int i=0; i<pandaMat._texture_list.size(); i++) {
1139 if ((tex->get_env_type()==EggTexture::ET_modulate)&&(tex->
get_fullpath() == fullpath)) {
1140 tex->set_format(EggTexture::F_rgba);
1146 std::string uvname = get_uv_name(transTex->GetMapChannel());
1147 for (
int i=0; i<pandaMat._texture_list.size(); i++) {
1149 if ((tex->get_env_type()==EggTexture::ET_modulate)&&
1150 (tex->get_format() == EggTexture::F_rgb)&&
1152 tex->set_format(EggTexture::F_rgba);
1161 tex->set_filename(outpath);
1164 apply_texture_properties(*tex, transTex->GetMapChannel());
1165 add_map_channel(pandaMat, transTex->GetMapChannel());
1166 tex->set_format(EggTexture::F_alpha);
1168 pandaMat._texture_list.push_back(tex);
1177 void MaxToEggConverter::analyze_glow_maps(PandaMaterial &pandaMat, Texmap *mat) {
1178 if (mat == 0)
return;
1180 if (mat->ClassID() == Class_ID(BMTEX_CLASS_ID, 0)) {
1181 BitmapTex *gtex = (BitmapTex *)mat;
1189 _options->_path_replace->full_convert_path(filename, get_model_path(),
1193 std::string uvname = get_uv_name(gtex->GetMapChannel());
1194 for (
int i=0; i<pandaMat._texture_list.size(); i++) {
1196 if ((tex->get_env_type()==EggTexture::ET_modulate)&&
1197 (tex->get_format() == EggTexture::F_rgb)&&
1199 tex->set_env_type(EggTexture::ET_modulate_glow);
1200 tex->set_format(EggTexture::F_rgba);
1209 tex->set_env_type(EggTexture::ET_glow);
1210 tex->set_filename(outpath);
1212 apply_texture_properties(*tex, gtex->GetMapChannel());
1213 add_map_channel(pandaMat, gtex->GetMapChannel());
1214 tex->set_format(EggTexture::F_alpha);
1216 pandaMat._texture_list.push_back(tex);
1225 void MaxToEggConverter::analyze_gloss_maps(PandaMaterial &pandaMat, Texmap *mat) {
1226 if (mat == 0)
return;
1228 if (mat->ClassID() == Class_ID(BMTEX_CLASS_ID, 0)) {
1229 pandaMat._any_gloss =
true;
1230 BitmapTex *gtex = (BitmapTex *)mat;
1238 _options->_path_replace->full_convert_path(filename, get_model_path(),
1242 std::string uvname = get_uv_name(gtex->GetMapChannel());
1243 for (
int i=0; i<pandaMat._texture_list.size(); i++) {
1245 if ((tex->get_env_type()==EggTexture::ET_modulate)&&
1246 (tex->get_format() == EggTexture::F_rgb)&&
1248 tex->set_env_type(EggTexture::ET_modulate_gloss);
1249 tex->set_format(EggTexture::F_rgba);
1258 tex->set_env_type(EggTexture::ET_gloss);
1259 tex->set_filename(outpath);
1261 apply_texture_properties(*tex, gtex->GetMapChannel());
1262 add_map_channel(pandaMat, gtex->GetMapChannel());
1263 tex->set_format(EggTexture::F_alpha);
1265 pandaMat._texture_list.push_back(tex);
1274 void MaxToEggConverter::analyze_normal_maps(PandaMaterial &pandaMat, Texmap *mat) {
1275 if (mat == 0)
return;
1277 if (mat->ClassID() == Class_ID(BMTEX_CLASS_ID, 0)) {
1278 pandaMat._any_normal =
true;
1279 BitmapTex *ntex = (BitmapTex *)mat;
1287 _options->_path_replace->full_convert_path(filename, get_model_path(),
1291 tex->set_env_type(EggTexture::ET_normal);
1292 tex->set_filename(outpath);
1294 apply_texture_properties(*tex, ntex->GetMapChannel());
1295 add_map_channel(pandaMat, ntex->GetMapChannel());
1296 tex->set_format(EggTexture::F_rgb);
1298 pandaMat._texture_list.push_back(tex);
1308 void MaxToEggConverter::add_map_channel(PandaMaterial &pandaMat,
int chan) {
1309 for (
int i=0; i<pandaMat._map_channels.size(); i++) {
1310 if (pandaMat._map_channels[i] == chan) {
1314 pandaMat._map_channels.push_back(chan);
1322 std::string MaxToEggConverter::generate_tex_name() {
1324 name_strm <<
"Tex" << ++_cur_tref;
1325 return name_strm.str();
1333 std::string MaxToEggConverter::get_uv_name(
int channel) {
1335 uvname <<
"m" << channel;
1336 return uvname.str();
1346 void MaxToEggConverter::
1347 apply_texture_properties(
EggTexture &tex,
int channel) {
1355 tex.set_minfilter(EggTexture::FT_linear_mipmap_linear);
1356 tex.set_magfilter(EggTexture::FT_linear);
1358 EggTexture::WrapMode wrap_u = EggTexture::WM_repeat;
1359 EggTexture::WrapMode wrap_v = EggTexture::WM_repeat;
1361 tex.set_wrap_u(wrap_u);
1362 tex.set_wrap_v(wrap_v);
1376 bool MaxToEggConverter::
1385 EggGroupNode::iterator ci;
1386 for (ci = egg_parent->begin(); ci != egg_parent->end(); ++ci) {
1388 if (child->
is_of_type(EggGroup::get_class_type())) {
1391 if (decal_base != (
EggNode *)NULL) {
1396 decal_base = child_group;
1400 decal_children.push_back(child_group);
1405 if (decal_base == (
EggGroup *)NULL) {
1406 if (!decal_children.empty()) {
1411 if (decal_children.empty()) {
1420 for (di = decal_children.begin(); di != decal_children.end(); ++di) {
1426 decal_base->set_decal_flag(
true);
1431 for (ci = egg_parent->begin(); ci != egg_parent->end(); ++ci) {
1433 if (child->
is_of_type(EggGroupNode::get_class_type())) {
1435 if (!reparent_decals(child_group)) {
1444 Modifier* MaxToEggConverter::FindSkinModifier (INode* node,
const Class_ID &type)
1447 Object* pObj = node->GetObjectRef();
1448 if (!pObj)
return NULL;
1451 while (pObj->SuperClassID() == GEN_DERIVOB_CLASS_ID) {
1453 IDerivedObject* pDerObj =
static_cast<IDerivedObject*
>(pObj);
1456 for (
int stackId = 0; stackId < pDerObj->NumModifiers(); ++stackId) {
1458 Modifier* mod = pDerObj->GetModifier(stackId);
1461 if (mod->ClassID() == type )
1466 pObj = pDerObj->GetObjRef();
void set_fullpath(const Filename &fullpath)
Records the full pathname to the file, for the benefit of get_fullpath().
string get_dirname() const
Returns the directory part of the filename.
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.
bool is_joint() const
Returns true if the node should be treated as a joint by the converter.
const LMatrix4d & get_node_frame_inv() const
Returns the inverse of the matrix returned by get_node_frame().
void set_pos(double pos)
Sets the vertex position.
bool almost_equal(const LMatrix4d &other, double threshold) const
Returns true if two matrices are memberwise equal within a specified tolerance.
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.
A base class for nodes in the hierarchy that are not leaf nodes.
This is a four-component point in space.
int get_num_nodes() const
Returns the total number of nodes in the hierarchy, not counting the root node.
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_node_joint() const
Returns true if the node is the parent or ancestor of a joint.
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.
LVertexd get_pos3() const
Valid if get_num_dimensions() returns 3 or 4.
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.
iterator end() const
Returns an iterator that can be used to traverse through all the vertices in the pool.
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.
iterator begin() const
Returns an iterator that can be used to traverse through all the vertices in the pool.
MaxNodeDesc * get_node(int n) const
Returns the nth node in the hierarchy, in an arbitrary ordering.
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...
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...
bool invert_in_place()
Inverts the current matrix.
This corresponds to an <Xfm$Anim_S$> entry, which is a collection of up to nine <S$Anim> entries that...
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...
A parametric NURBS curve.
void optimize()
Optimizes the table by collapsing redundant sub-tables.
const Filename & get_fullpath() const
Returns the full pathname to the file, if it is known; otherwise, returns the same thing as get_filen...
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 ...
INode * get_max_node() const
Returns the INode associated with this node.
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.
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...
bool has_max_node() const
Returns true if a Max INode has been associated with this node, false otherwise.
static Filename from_os_specific_w(const wstring &os_specific, Type type=T_general)
The wide-string variant of from_os_specific().
int get_external_index() const
Returns the number set by set_external_index().
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
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...
EggVertex * get_vertex(int index) const
Returns a particular index based on its index number.
const LMatrix4d & get_vertex_frame_inv() const
Returns the inverse of the matrix returned by get_vertex_frame().
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).