52 void MaxToEggConverter::reset() {
76 _options->_path_replace->_path_directory = fn.
get_dirname();
79 if (_egg_data->get_coordinate_system() == CS_default) {
87 Interval anim_range = _options->_max_interface->GetAnimRange();
88 int start_frame = anim_range.Start()/GetTicksPerFrame();
89 int end_frame = anim_range.End()/GetTicksPerFrame();
91 if (!_options->_export_all_frames) {
92 if (_options->_start_frame < start_frame) _options->_start_frame = start_frame;
93 if (_options->_start_frame > end_frame) _options->_start_frame = end_frame;
94 if (_options->_end_frame < start_frame) _options->_end_frame = start_frame;
95 if (_options->_end_frame > end_frame) _options->_end_frame = end_frame;
96 if (_options->_end_frame < _options->_start_frame) _options->_end_frame = _options->_start_frame;
97 start_frame = _options->_start_frame;
98 end_frame = _options->_end_frame;
102 int output_frame_rate = GetFrameRate();
106 if (_options->_export_whole_scene) {
107 _tree._export_mesh =
false;
110 _tree._export_mesh =
true;
111 all_ok = _tree.
build_complete_hierarchy(_options->_max_interface->GetRootNode(), &_options->_node_list.front(), _options->_node_list.size());
115 switch (_options->_anim_type) {
116 case MaxEggOptions::AT_pose:
123 _current_frame = start_frame;
124 all_ok = convert_hierarchy(_egg_data);
127 case MaxEggOptions::AT_model:
130 all_ok = convert_char_model();
133 case MaxEggOptions::AT_chan:
135 all_ok = convert_char_chan(start_frame, end_frame, frame_inc,
139 case MaxEggOptions::AT_both:
141 _options->_anim_type = MaxEggOptions::AT_model;
142 if (!convert_char_model()) {
145 _options->_anim_type = MaxEggOptions::AT_chan;
146 if (!convert_char_chan(start_frame, end_frame, frame_inc,
147 output_frame_rate)) {
151 _options->_anim_type = MaxEggOptions::AT_both;
158 reparent_decals(_egg_data);
162 _egg_data->recompute_tangent_binormal_auto();
163 _egg_data->remove_unused_vertices(
true);
166 _options->_successful = all_ok;
174 return _egg_data->write_egg(fn);
184 bool MaxToEggConverter::
185 convert_char_model() {
186 std::string character_name =
"character";
187 _current_frame = _options->_start_frame;
190 _egg_data->add_child(char_node);
191 char_node->set_dart_type(EggGroup::DT_default);
193 return convert_hierarchy(char_node);
200 bool MaxToEggConverter::
201 convert_char_chan(
double start_frame,
double end_frame,
double frame_inc,
202 double output_frame_rate) {
203 std::string character_name =
"character";
206 _egg_data->add_child(root_table_node);
208 bundle_node->set_table_type(EggTable::TT_bundle);
215 _tree._fps = output_frame_rate / frame_inc;
216 _tree.
clear_egg(_egg_data,
nullptr, skeleton_node);
228 TimeValue frame = start_frame;
229 TimeValue frame_stop = end_frame;
230 while (frame <= frame_stop) {
231 _current_frame = frame;
232 for (i = 0; i < num_nodes; i++) {
239 if (node_desc->_parent && node_desc->_parent->
is_joint()) {
243 get_joint_transform(max_node, node_desc->_parent->
get_max_node(),
246 get_joint_transform(max_node,
nullptr, tgroup);
263 for (i = 0; i < num_nodes; i++) {
276 bool MaxToEggConverter::
280 _tree.
clear_egg(_egg_data, egg_root,
nullptr);
282 if (!process_model_node(_tree.
get_node(i))) {
294 bool MaxToEggConverter::
311 state = max_node->EvalWorldState(_current_frame * GetTicksPerFrame());
316 if (_options->_anim_type == MaxEggOptions::AT_model) {
317 get_joint_transform(max_node, egg_group);
322 TriObject *myMaxTriObject;
325 switch( state.obj->SuperClassID() ){
327 case GEOMOBJECT_CLASS_ID:
329 get_transform(max_node, egg_group);
332 if (!state.obj->CanConvertToType(Class_ID(TRIOBJ_CLASS_ID, 0))) {
336 myMaxTriObject = (TriObject *) state.obj->ConvertToType(time, Class_ID(TRIOBJ_CLASS_ID, 0 ));
342 max_mesh = myMaxTriObject->GetMesh();
343 make_polyset(max_node, &max_mesh, egg_group);
345 if (myMaxTriObject != state.obj)
346 delete myMaxTriObject;
350 if (state.obj->ClassID() == EDITABLE_SURF_CLASS_ID) {
352 if (GetNURBSSet(state.obj, time, getSet, TRUE)) {
353 NURBSObject *nObj = getSet.GetNURBSObject(0);
354 if (nObj->GetType() == kNCVCurve) {
357 get_transform(max_node, egg_group);
358 make_nurbs_curve(max_node, (NURBSCVCurve *)nObj,
365 case CAMERA_CLASS_ID:
371 case HELPER_CLASS_ID:
374 if (state.obj->ClassID() == Class_ID(POINTHELP_CLASS_ID, 0)) {
377 get_transform(max_node, egg_group);
399 void MaxToEggConverter::
400 get_transform(INode *max_node,
EggGroup *egg_group) {
401 if (_options->_anim_type == MaxEggOptions::AT_model) {
414 Matrix3 pivot = max_node->GetNodeTM(_current_frame * GetTicksPerFrame());
417 Point3 row0 = pivot.GetRow(0);
418 Point3 row1 = pivot.GetRow(1);
419 Point3 row2 = pivot.GetRow(2);
420 Point3 row3 = pivot.GetRow(3);
422 LMatrix4d m4d(row0.x, row0.y, row0.z, 0.0f,
423 row1.x, row1.y, row1.z, 0.0f,
424 row2.x, row2.y, row2.z, 0.0f,
425 row3.x, row3.y, row3.z, 1.0f );
432 if (!m4d.almost_equal(LMatrix4d::ident_mat(), 0.0001)) {
441 LMatrix4d MaxToEggConverter::
442 get_object_transform(INode *max_node) {
447 Matrix3 pivot = max_node->GetObjectTM(_current_frame * GetTicksPerFrame());
449 Point3 row0 = pivot.GetRow(0);
450 Point3 row1 = pivot.GetRow(1);
451 Point3 row2 = pivot.GetRow(2);
452 Point3 row3 = pivot.GetRow(3);
454 LMatrix4d m4d(row0.x, row0.y, row0.z, 0.0f,
455 row1.x, row1.y, row1.z, 0.0f,
456 row2.x, row2.y, row2.z, 0.0f,
457 row3.x, row3.y, row3.z, 1.0f );
468 void MaxToEggConverter::
469 get_joint_transform(INode *max_node,
EggGroup *egg_group) {
478 Matrix3 pivot = max_node->GetNodeTM(_current_frame * GetTicksPerFrame());
479 Point3 row0 = pivot.GetRow(0);
480 Point3 row1 = pivot.GetRow(1);
481 Point3 row2 = pivot.GetRow(2);
482 Point3 row3 = pivot.GetRow(3);
484 LMatrix4d m4d(row0.x, row0.y, row0.z, 0.0f,
485 row1.x, row1.y, row1.z, 0.0f,
486 row2.x, row2.y, row2.z, 0.0f,
487 row3.x, row3.y, row3.z, 1.0f );
494 if (!m4d.almost_equal(LMatrix4d::ident_mat(), 0.0001)) {
506 void MaxToEggConverter::
507 get_joint_transform(INode *max_node, INode *parent_node,
EggGroup *egg_group) {
516 Matrix3 pivot = max_node->GetNodeTM(_current_frame * GetTicksPerFrame());
517 Point3 row0 = pivot.GetRow(0);
518 Point3 row1 = pivot.GetRow(1);
519 Point3 row2 = pivot.GetRow(2);
520 Point3 row3 = pivot.GetRow(3);
522 LMatrix4d m4d(row0.x, row0.y, row0.z, 0.0f,
523 row1.x, row1.y, row1.z, 0.0f,
524 row2.x, row2.y, row2.z, 0.0f,
525 row3.x, row3.y, row3.z, 1.0f );
528 Matrix3 parent_pivot = parent_node->GetNodeTM(_current_frame * GetTicksPerFrame());
530 row0 = parent_pivot.GetRow(0);
531 row1 = parent_pivot.GetRow(1);
532 row2 = parent_pivot.GetRow(2);
533 row3 = parent_pivot.GetRow(3);
535 LMatrix4d pi_m4d(row0.x, row0.y, row0.z, 0.0f,
536 row1.x, row1.y, row1.z, 0.0f,
537 row2.x, row2.y, row2.z, 0.0f,
538 row3.x, row3.y, row3.z, 1.0f );
544 pi_m4d.invert_in_place();
547 if (!m4d.almost_equal(LMatrix4d::ident_mat(), 0.0001)) {
557 bool MaxToEggConverter::
558 make_nurbs_curve(INode *max_node, NURBSCVCurve *curve,
559 TimeValue time,
EggGroup *egg_group)
561 int degree = curve->GetOrder();
562 int cvs = curve->GetNumCVs();
563 int knots = curve->GetNumKnots();
566 if (knots != cvs + degree) {
573 wcstombs(mbname, max_node->GetName(), 1023);
576 string name = max_node->GetName();
579 string vpool_name = name +
".cvs";
585 egg_curve->
setup(degree, knots);
587 for (i = 0; i < knots; i++)
588 egg_curve->
set_knot(i, curve->GetKnot(i));
592 for (i = 0; i < cvs; i++) {
593 NURBSControlVertex *cv = curve->GetCV(i);
596 sprintf(buf,
"Error getting CV %d", i);
600 LPoint4d p4d(0, 0, 0, 1.0);
601 cv->GetPosition(time, p4d[0], p4d[1], p4d[2]);
602 p4d = p4d * vertex_frame_inv;
615 void MaxToEggConverter::
616 make_polyset(INode *max_node, Mesh *mesh,
619 mesh->buildNormals();
621 if (mesh->getNumFaces() == 0) {
639 wcstombs(mbname, max_node->GetName(), 1023);
640 string node_name(mbname);
642 string node_name = max_node->GetName();
645 string vpool_name = node_name +
".verts";
654 LMatrix4d vertex_frame = get_object_transform(max_node) *
658 for (
int iFace=0; iFace < mesh->getNumFaces(); iFace++ ) {
664 Face face = mesh->faces[iFace];
666 const PandaMaterial &pmat = get_panda_material(max_node->GetMtl(), face.getMatID());
669 for (
int iVertex=0; iVertex < 3; iVertex++ ) {
673 Point3 vertex = mesh->getVert(face.v[iVertex]);
674 LPoint3d p3d(vertex.x, vertex.y, vertex.z);
675 p3d = p3d * vertex_frame;
679 Point3 normal = get_max_vertex_normal(mesh, iFace, iVertex);
680 LVector3d n3d(normal.x, normal.y, normal.z);
683 n3d = n3d * vertex_frame;
684 vert.set_normal(n3d);
689 VertColor vertexColor = get_max_vertex_color(mesh, iFace, iVertex);
690 LColor pVC(vertexColor.x, vertexColor.y, vertexColor.z, 1);
698 if (pmat._map_channels.size() == 0) {
701 UVVert uvw = get_max_vertex_texcoord(mesh, iFace, iVertex, 1);
702 vert.
set_uv( LTexCoordd(uvw.x, uvw.y));
707 for (
int iChan=0; iChan<pmat._map_channels.size(); iChan++) {
708 int channel = pmat._map_channels[iChan];
709 std::ostringstream uvname;
710 uvname <<
"m" << channel;
711 UVVert uvw = get_max_vertex_texcoord(mesh, iFace, iVertex, channel);
714 vert.
set_uv( LTexCoordd(uvw.x, uvw.y));
716 vert.
set_uv( uvname.str(), LTexCoordd(uvw.x, uvw.y));
731 for (
int i = 0; i < 3; i++) {
736 LVector3d realNorm = ((points[1] - points[0]).cross(points[2] - points[0]));
737 Point3 maxNormTemp = mesh->getFaceNormal(iFace);
738 LVector3d maxNorm = (LVector3d(maxNormTemp.x, maxNormTemp.y, maxNormTemp.z) *
741 if (realNorm.dot(maxNorm) < 0.0) {
746 for (
int i=0; i<pmat._texture_list.size(); i++) {
749 egg_poly->set_color(pmat._color);
758 if (_options->_anim_type == MaxEggOptions::AT_model) {
759 get_vertex_weights(max_node, vpool);
763 UVVert MaxToEggConverter::get_max_vertex_texcoord(Mesh *mesh,
int faceNo,
int vertNo,
int channel) {
766 UVVert uvVert(0,0,0);
767 if(mesh->mapSupport(channel)) {
768 TVFace *pTVFace = mesh->mapFaces(channel);
769 UVVert *pUVVert = mesh->mapVerts(channel);
770 uvVert = pUVVert[pTVFace[faceNo].t[vertNo]];
771 }
else if(mesh->numTVerts > 0) {
772 uvVert = mesh->tVerts[mesh->tvFace[faceNo].t[vertNo]];
777 VertColor MaxToEggConverter::get_max_vertex_color(Mesh *mesh,
int FaceNo,
int VertexNo,
int channel) {
780 if(mesh->mapSupport(channel))
783 TVFace& _vcface = mesh->vcFace[FaceNo];
785 int VertexColorIndex = _vcface.t[VertexNo];
787 vc =mesh->vertCol[VertexColorIndex];
791 TVFace *pTVFace = mesh->mapFaces(channel);
792 vc = mesh->vertCol[pTVFace[FaceNo].t[VertexNo]];
797 VertColor MaxToEggConverter::get_max_vertex_color(Mesh *mesh,
int FaceNo,
int VertexNo)
801 TVFace& _vcface = mesh->vcFace[FaceNo];
803 int VertexColorIndex = _vcface.t[VertexNo];
805 vc =mesh->vertCol[VertexColorIndex];
809 Point3 MaxToEggConverter::get_max_vertex_normal(Mesh *mesh,
int faceNo,
int vertNo)
811 Face f = mesh->faces[faceNo];
812 DWORD smGroup = f.smGroup;
813 int vert = f.getVert(vertNo);
814 RVertex *rv = mesh->getRVertPtr(vert);
821 if (rv->rFlags & SPECIFIED_NORMAL) {
822 vertexNormal = rv->rn.getNormal();
826 else if ((numNormals = rv->rFlags & NORCT_MASK) && smGroup) {
828 if (numNormals == 1) {
829 vertexNormal = rv->rn.getNormal();
836 for (
int i = 0; i < numNormals; i++) {
837 if (rv->ern[i].getSmGroup() & smGroup) {
838 vertexNormal = rv->ern[i].getNormal();
845 vertexNormal = mesh->getFaceNormal(faceNo);
854 void MaxToEggConverter::
857 Modifier *mod = FindSkinModifier(max_node, PHYSIQUE_CLASSID);
862 IPhysiqueExport *pPhysiqueExport = (IPhysiqueExport *)mod->GetInterface(I_PHYINTERFACE);
863 if (pPhysiqueExport) {
865 IPhyContextExport *pContextExport =
866 (IPhyContextExport *)pPhysiqueExport->GetContextInterface(max_node);
867 if (pContextExport) {
869 pContextExport->ConvertToRigid(TRUE);
870 pContextExport->AllowBlending(TRUE);
872 for (vi = vpool->
begin(); vi != vpool->
end(); ++vi) {
877 IPhyVertexExport *pVertexExport =
878 (IPhyVertexExport *)pContextExport->GetVertexInterface(max_vi);
880 int vertexType = pVertexExport->GetVertexType();
883 if(vertexType == RIGID_TYPE) {
885 IPhyRigidVertex *pTypeVertex = (IPhyRigidVertex *)pVertexExport;
886 INode *bone_node = pTypeVertex->GetNode();
888 if (joint_node_desc){
890 if (joint !=
nullptr)
894 else if(vertexType == RIGID_BLENDED_TYPE) {
896 IPhyBlendedRigidVertex *pTypeVertex = (IPhyBlendedRigidVertex *)pVertexExport;
898 for (
int ji = 0; ji < pTypeVertex->GetNumberNodes(); ++ji) {
899 PN_stdfloat weight = pTypeVertex->GetWeight(ji);
901 INode *bone_node = pTypeVertex->GetNode(ji);
903 if (joint_node_desc){
905 if (joint !=
nullptr)
912 pContextExport->ReleaseVertexInterface(pVertexExport);
916 pPhysiqueExport->ReleaseContextInterface(pContextExport);
919 mod->ReleaseInterface(I_PHYINTERFACE, pPhysiqueExport);
924 mod = FindSkinModifier(max_node, SKIN_CLASSID);
926 ISkin *skin = (ISkin*)mod->GetInterface(I_SKIN);
928 ISkinContextData *skinMC = skin->GetContextInterface(max_node);
930 for (vi = vpool->
begin(); vi != vpool->
end(); ++vi) {
934 for (
int ji = 0; ji < skinMC->GetNumAssignedBones(max_vi); ++ji) {
935 PN_stdfloat weight = skinMC->GetBoneWeight(max_vi, ji);
937 INode *bone_node = skin->GetBone(skinMC->GetAssignedBone(max_vi, ji));
939 if (joint_node_desc){
941 if (joint !=
nullptr) {
958 const MaxToEggConverter::PandaMaterial &MaxToEggConverter::
959 get_panda_material(Mtl *mtl, MtlID matID) {
961 MaterialMap::iterator it = _material_map.find(mtl);
962 if (it != _material_map.end()) {
966 PandaMaterial &pandaMat = _material_map[mtl];
967 pandaMat._color = LColor(1,1,1,1);
968 pandaMat._any_diffuse =
false;
969 pandaMat._any_opacity =
false;
970 pandaMat._any_gloss =
false;
971 pandaMat._any_normal =
false;
978 while (( mtl != 0) && (mtl->ClassID() == Class_ID(MULTI_CLASS_ID, 0 ))) {
979 if (matID < mtl->NumSubMtls()) {
980 mtl = mtl->GetSubMtl(matID);
988 if ((mtl != 0) && (mtl->ClassID() == Class_ID(DMTL_CLASS_ID, 0 ))) {
989 StdMat *maxMaterial = (StdMat*)mtl;
990 analyze_diffuse_maps(pandaMat, maxMaterial->GetSubTexmap(ID_DI));
991 analyze_opacity_maps(pandaMat, maxMaterial->GetSubTexmap(ID_OP));
992 analyze_gloss_maps(pandaMat, maxMaterial->GetSubTexmap(ID_SP));
993 if (!pandaMat._any_gloss)
994 analyze_gloss_maps(pandaMat, maxMaterial->GetSubTexmap(ID_SS));
995 if (!pandaMat._any_gloss)
996 analyze_gloss_maps(pandaMat, maxMaterial->GetSubTexmap(ID_SH));
997 analyze_glow_maps(pandaMat, maxMaterial->GetSubTexmap(ID_SI));
998 analyze_normal_maps(pandaMat, maxMaterial->GetSubTexmap(ID_BU));
999 for (
int i=0; i<pandaMat._texture_list.size(); i++) {
1001 pandaMat._texture_list[i] =
1007 if (!pandaMat._any_diffuse) {
1010 Point3 diffuseColor = Point3(maxMaterial->GetDiffuse(0));
1011 pandaMat._color[0] = diffuseColor.x;
1012 pandaMat._color[1] = diffuseColor.y;
1013 pandaMat._color[2] = diffuseColor.z;
1015 if (!pandaMat._any_opacity) {
1016 pandaMat._color[3] = (maxMaterial->GetOpacity(_current_frame * GetTicksPerFrame()));
1018 if (pandaMat._texture_list.size() < 1) {
1021 pandaMat._map_channels.push_back(1);
1032 void MaxToEggConverter::analyze_diffuse_maps(PandaMaterial &pandaMat, Texmap *mat) {
1033 if (mat == 0)
return;
1035 if (mat->ClassID() == Class_ID(RGBMULT_CLASS_ID, 0)) {
1036 for (
int i=0; i<mat->NumSubTexmaps(); i++) {
1037 analyze_diffuse_maps(pandaMat, mat->GetSubTexmap(i));
1042 if (mat->ClassID() == Class_ID(BMTEX_CLASS_ID, 0)) {
1043 pandaMat._any_diffuse =
true;
1046 BitmapTex *diffuseTex = (BitmapTex *)mat;
1054 _options->_path_replace->full_convert_path(filename, get_model_path(),
1056 tex->set_filename(outpath);
1057 tex->set_fullpath(fullpath);
1059 apply_texture_properties(*tex, diffuseTex->GetMapChannel());
1060 add_map_channel(pandaMat, diffuseTex->GetMapChannel());
1062 Bitmap *diffuseBitmap = diffuseTex->GetBitmap(0);
1063 if ( diffuseBitmap && diffuseBitmap->HasAlpha()) {
1064 tex->set_format(EggTexture::F_rgba);
1066 tex->set_format(EggTexture::F_rgb);
1068 tex->set_env_type(EggTexture::ET_modulate);
1070 pandaMat._texture_list.push_back(tex);
1077 void MaxToEggConverter::analyze_opacity_maps(PandaMaterial &pandaMat, Texmap *mat) {
1078 if (mat == 0)
return;
1080 if (mat->ClassID() == Class_ID(RGBMULT_CLASS_ID, 0)) {
1081 for (
int i=0; i<mat->NumSubTexmaps(); i++) {
1082 analyze_opacity_maps(pandaMat, mat->GetSubTexmap(i));
1087 if (mat->ClassID() == Class_ID(BMTEX_CLASS_ID, 0)) {
1088 pandaMat._any_opacity =
true;
1089 BitmapTex *transTex = (BitmapTex *)mat;
1097 _options->_path_replace->full_convert_path(filename, get_model_path(),
1101 for (
int i=0; i<pandaMat._texture_list.size(); i++) {
1103 if ((tex->get_env_type()==EggTexture::ET_modulate)&&(tex->
get_fullpath() == fullpath)) {
1104 tex->set_format(EggTexture::F_rgba);
1110 std::string uvname = get_uv_name(transTex->GetMapChannel());
1111 for (
int i=0; i<pandaMat._texture_list.size(); i++) {
1113 if ((tex->get_env_type()==EggTexture::ET_modulate)&&
1114 (tex->get_format() == EggTexture::F_rgb)&&
1116 tex->set_format(EggTexture::F_rgba);
1125 tex->set_filename(outpath);
1128 apply_texture_properties(*tex, transTex->GetMapChannel());
1129 add_map_channel(pandaMat, transTex->GetMapChannel());
1130 tex->set_format(EggTexture::F_alpha);
1132 pandaMat._texture_list.push_back(tex);
1139 void MaxToEggConverter::analyze_glow_maps(PandaMaterial &pandaMat, Texmap *mat) {
1140 if (mat == 0)
return;
1142 if (mat->ClassID() == Class_ID(BMTEX_CLASS_ID, 0)) {
1143 BitmapTex *gtex = (BitmapTex *)mat;
1151 _options->_path_replace->full_convert_path(filename, get_model_path(),
1155 std::string uvname = get_uv_name(gtex->GetMapChannel());
1156 for (
int i=0; i<pandaMat._texture_list.size(); i++) {
1158 if ((tex->get_env_type()==EggTexture::ET_modulate)&&
1159 (tex->get_format() == EggTexture::F_rgb)&&
1161 tex->set_env_type(EggTexture::ET_modulate_glow);
1162 tex->set_format(EggTexture::F_rgba);
1171 tex->set_env_type(EggTexture::ET_glow);
1172 tex->set_filename(outpath);
1174 apply_texture_properties(*tex, gtex->GetMapChannel());
1175 add_map_channel(pandaMat, gtex->GetMapChannel());
1176 tex->set_format(EggTexture::F_alpha);
1178 pandaMat._texture_list.push_back(tex);
1185 void MaxToEggConverter::analyze_gloss_maps(PandaMaterial &pandaMat, Texmap *mat) {
1186 if (mat == 0)
return;
1188 if (mat->ClassID() == Class_ID(BMTEX_CLASS_ID, 0)) {
1189 pandaMat._any_gloss =
true;
1190 BitmapTex *gtex = (BitmapTex *)mat;
1198 _options->_path_replace->full_convert_path(filename, get_model_path(),
1202 std::string uvname = get_uv_name(gtex->GetMapChannel());
1203 for (
int i=0; i<pandaMat._texture_list.size(); i++) {
1205 if ((tex->get_env_type()==EggTexture::ET_modulate)&&
1206 (tex->get_format() == EggTexture::F_rgb)&&
1208 tex->set_env_type(EggTexture::ET_modulate_gloss);
1209 tex->set_format(EggTexture::F_rgba);
1218 tex->set_env_type(EggTexture::ET_gloss);
1219 tex->set_filename(outpath);
1221 apply_texture_properties(*tex, gtex->GetMapChannel());
1222 add_map_channel(pandaMat, gtex->GetMapChannel());
1223 tex->set_format(EggTexture::F_alpha);
1225 pandaMat._texture_list.push_back(tex);
1232 void MaxToEggConverter::analyze_normal_maps(PandaMaterial &pandaMat, Texmap *mat) {
1233 if (mat == 0)
return;
1235 if (mat->ClassID() == Class_ID(BMTEX_CLASS_ID, 0)) {
1236 pandaMat._any_normal =
true;
1237 BitmapTex *ntex = (BitmapTex *)mat;
1245 _options->_path_replace->full_convert_path(filename, get_model_path(),
1249 tex->set_env_type(EggTexture::ET_normal);
1250 tex->set_filename(outpath);
1252 apply_texture_properties(*tex, ntex->GetMapChannel());
1253 add_map_channel(pandaMat, ntex->GetMapChannel());
1254 tex->set_format(EggTexture::F_rgb);
1256 pandaMat._texture_list.push_back(tex);
1264 void MaxToEggConverter::add_map_channel(PandaMaterial &pandaMat,
int chan) {
1265 for (
int i=0; i<pandaMat._map_channels.size(); i++) {
1266 if (pandaMat._map_channels[i] == chan) {
1270 pandaMat._map_channels.push_back(chan);
1276 std::string MaxToEggConverter::generate_tex_name() {
1277 std::ostringstream name_strm;
1278 name_strm <<
"Tex" << ++_cur_tref;
1279 return name_strm.str();
1285 std::string MaxToEggConverter::get_uv_name(
int channel) {
1286 std::ostringstream uvname;
1287 uvname <<
"m" << channel;
1288 return uvname.str();
1295 void MaxToEggConverter::
1296 apply_texture_properties(
EggTexture &tex,
int channel) {
1304 tex.set_minfilter(EggTexture::FT_linear_mipmap_linear);
1305 tex.set_magfilter(EggTexture::FT_linear);
1307 EggTexture::WrapMode wrap_u = EggTexture::WM_repeat;
1308 EggTexture::WrapMode wrap_v = EggTexture::WM_repeat;
1310 tex.set_wrap_u(wrap_u);
1311 tex.set_wrap_v(wrap_v);
1321 bool MaxToEggConverter::
1330 EggGroupNode::iterator ci;
1331 for (ci = egg_parent->begin(); ci != egg_parent->end(); ++ci) {
1333 if (child->
is_of_type(EggGroup::get_class_type())) {
1336 if (decal_base !=
nullptr) {
1341 decal_base = child_group;
1345 decal_children.push_back(child_group);
1350 if (decal_base ==
nullptr) {
1351 if (!decal_children.empty()) {
1356 if (decal_children.empty()) {
1365 for (di = decal_children.begin(); di != decal_children.end(); ++di) {
1371 decal_base->set_decal_flag(
true);
1376 for (ci = egg_parent->begin(); ci != egg_parent->end(); ++ci) {
1378 if (child->
is_of_type(EggGroupNode::get_class_type())) {
1380 if (!reparent_decals(child_group)) {
1389 Modifier* MaxToEggConverter::FindSkinModifier (INode* node,
const Class_ID &type)
1392 Object* pObj = node->GetObjectRef();
1393 if (!pObj)
return nullptr;
1396 while (pObj->SuperClassID() == GEN_DERIVOB_CLASS_ID) {
1398 IDerivedObject* pDerObj = static_cast<IDerivedObject*>(pObj);
1401 for (
int stackId = 0; stackId < pDerObj->NumModifiers(); ++stackId) {
1403 Modifier* mod = pDerObj->GetModifier(stackId);
1406 if (mod->ClassID() == type )
1411 pObj = pDerObj->GetObjRef();
void set_fullpath(const Filename &fullpath)
Records the full pathname to the file, for the benefit of get_fullpath().
void setup(int order, int num_knots)
Prepares a new curve definition with the indicated order and number of knots.
std::string get_dirname() const
Returns the directory part of the filename.
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.
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.
get_uv_name
Returns the texcoord name that has been specified for this texture, or the empty string if no texcoor...
const LMatrix4d & get_node_frame_inv() const
Returns the inverse of the matrix returned by get_node_frame().
bool remove_object_type(const std::string &object_type)
Removes the first instance of the indicated object type from the group if it is present.
void set_pos(double pos)
Sets the vertex position.
A base class for nodes in the hierarchy that are not leaf nodes.
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.
set_alpha_fullpath
Records the full pathname to the file, for the benefit of get_alpha_fullpath().
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.
set_bface_flag
Sets the backfacing flag of the polygon.
bool build_complete_hierarchy(INode *root, ULONG *selection_list, int len)
Walks through the complete Max hierarchy and builds up the corresponding tree.
MaxNodeDesc * find_joint(INode *max_node)
The recursive implementation of build_node().
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.
iterator end() const
Returns an iterator that can be used to traverse through all the vertices in the pool.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_vertex
Returns a particular index based on its index number.
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.
set_vertex
Replaces a particular vertex based on its index number in the list of vertices.
The main glue of the egg hierarchy, this corresponds to the <Group>, <Instance>, and <Joint> type nod...
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.
bool has_object_type(const std::string &object_type) const
Returns true if the indicated object type has been added to the group, or false otherwise.
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...
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...
set_uv_name
Specifies the named set of texture coordinates that this texture will use when it is applied to geome...
set_knot
Resets the value of the indicated knot as indicated.
INode * get_max_node() const
Returns the INode associated with this node.
EggNode * add_child(EggNode *node)
Adds the indicated child to the group and returns it.
set_coordinate_system
Changes the coordinate system of the EggData.
A base class for things that may be directly added into the egg hierarchy.
set_alpha_filename
Specifies a separate file that will be loaded in with the 1- or 3-component texture and applied as th...
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.
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.
static Filename from_os_specific_w(const std::wstring &os_specific, Type type=T_general)
The wide-string variant of from_os_specific().
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.
static Filename from_os_specific(const std::string &os_specific, Type type=T_general)
This named constructor returns a Panda-style filename (that is, using forward slashes,...
const LMatrix4d & get_vertex_frame_inv() const
Returns the inverse of the matrix returned by get_vertex_frame().