88static bool check_lod_extensions (
INodeListClass &list, INode *origin);
116 Object * obj = node->EvalWorldState(time).obj;
188 AppDataChunk * appdata = node->GetAppDataChunk(
W3DUtilityClassID,UTILITY_CLASS_ID,1);
189 if (!appdata)
return FALSE;
219 const TCHAR *filename,
220 ExpInterface *export,
222 BOOL suppressPrompts,
226 ExportInterface = export;
230 DamageRootList =
NULL;
231 HierarchyTree =
NULL;
235 CurTime = MaxInterface->GetTime();
236 FrameRate = GetFrameRate();
243 char rootname[_MAX_FNAME + 1];
244 char drivename[_MAX_DRIVE + 1];
245 char dirname[_MAX_DIR + 1];
246 _splitpath(filename, drivename, dirname, rootname,
NULL);
254 _splitpath(
max->GetCurFilePath(), drivename, dirname,
NULL,
NULL);
260 if (!get_export_options(suppressPrompts)) {
267 if ((!ExportOptions.ExportHierarchy) && (!ExportOptions.ExportAnimation) && (!ExportOptions.ExportGeometry)) {
282 MessageBox(
NULL,
"Unable to open file.",
"Error",MB_OK | MB_SETFOREGROUND);
294 if (get_origin_list())
304 if (HierarchyTree !=
NULL) {
305 delete HierarchyTree;
306 HierarchyTree =
NULL;
309 if (OriginList !=
NULL) {
314 if (DamageRootList !=
NULL) {
315 delete DamageRootList;
316 DamageRootList =
NULL;
325 MaxInterface->RedrawViews(MaxInterface->GetTime());
353 assert(damage_list !=
NULL);
358 Start_Progress_Bar();
363 steps+= OriginList->Num_Nodes();
372 bool is_base_object =
false;
374 unsigned int i, count = origin_list->
Num_Nodes();
375 INode *base_origin =
NULL;
377 for (i = 0; i < count; i++)
379 INode *node = (*origin_list)[i];
391 if (!Export_Hierarchy(rootname, csave, treemeter, base_origin))
393 MessageBox(
NULL,
"Hierarchy Export Failure!",
"Error",MB_OK | MB_SETFOREGROUND);
405 if (!Export_Animation(rootname, csave, animmeter, base_origin))
407 MessageBox(
NULL,
"Animation Export Failure!",
"Error",MB_OK | MB_SETFOREGROUND);
419 for (i = 0; i < damage_list->
Num_Nodes(); i++)
421 if (!Export_Damage_Animations(rootname, csave, damagemeter, (*damage_list)[i]))
423 MessageBox(
NULL,
"Damage Animation Export Failure!",
"Error", MB_OK | MB_SETFOREGROUND);
439 MessageBox(
NULL,
"Memory allocation failure!",
"Error", MB_OK | MB_SETFOREGROUND);
449 int idx = strlen(rootname);
450 rootname[idx+1] =
'\0';
455 if (!ExportOptions.LoadHierarchy && !ExportOptions.ExportHierarchy) {
459 for (i = 0; i < count; i++)
464 INode *origin = (*origin_list)[i];
471 if (!Export_Geometry(rootname, csave, meshmeter, origin, &meshcon))
473 MessageBox(
NULL,
"Geometry Export Failure!",
"Error", MB_OK | MB_SETFOREGROUND);
484 if (lod_level >= count || connections[count - lod_level - 1] !=
NULL)
487 sprintf(text,
"Origin Naming Error! There are %d models defined in this "
488 "scene, therefore your origin names should be\n\"Origin.00\" through "
489 "\"Origin.%02d\", 00 being the high-poly model and %02d being the "
490 "lowest detail LOD.", count, count-1, count-1);
491 MessageBox(
NULL, text,
"Error", MB_OK | MB_SETFOREGROUND);
495 connections[count - lod_level - 1] = meshcon;
501 if (ExportOptions.LoadHierarchy || ExportOptions.ExportHierarchy) {
502 rootname[idx] =
'\0';
507 if (!Export_HLod(rootname, htree->
Get_Name(), csave, hlod_meter, connections, count))
509 MessageBox(
NULL,
"HLOD Generation Failure!",
"Error", MB_OK | MB_SETFOREGROUND);
520 for (i = 0; i < count; i++)
522 if (connections[i] !=
NULL)
523 delete connections[i];
525 delete []connections;
552 if (root ==
NULL)
return false;
556 }
catch (ErrorClass err) {
561 HierarchyTree->Save(csave);
584 if (!ExportOptions.ExportAnimation)
return true;
585 HierarchySaveClass * htree = get_hierarchy_tree();
587 if ((root ==
NULL) || (htree ==
NULL)) {
591 MotionClass * motion =
NULL;
594 motion =
new MotionClass( ExportInterface->theScene,
600 MaxInterface->GetMAXHWnd(),
602 }
catch (ErrorClass err) {
627bool W3dExportClass::Export_Damage_Animations(
char *name,
ChunkSaveClass &csave,
631 if (!ExportOptions.ExportAnimation)
return true;
632 HierarchySaveClass *htree = get_hierarchy_tree();
634 if ((damage_root ==
NULL) || (htree ==
NULL))
643 Matrix3 originoffset =
Inverse(damage_root->GetNodeTM(CurTime));
649 int current_region = 0;
650 int num_damage_bones = 0;
653 DamageRegionFilterClass region_filter(current_region);
654 INodeListClass bone_list(damage_root, CurTime, ®ion_filter);
656 num_damage_bones += bone_list.Num_Nodes();
659 if (bone_list.Num_Nodes() <= 0)
664 sprintf(anim_name,
"damage%d-%d", current_region, damage_state);
667 MotionClass *motion =
NULL;
670 motion =
new MotionClass( ExportInterface->theScene,
676 MaxInterface->GetMAXHWnd(),
680 catch (ErrorClass err)
686 assert(motion !=
NULL);
692 if (num_damage_bones <= 0)
694 MessageBox(
NULL,
"Warning: Your damage bones need to be given damage region numbers. "
695 "You can do this in the W3D Tools panel.", name, MB_OK | MB_ICONINFORMATION | MB_SETFOREGROUND);
701#define TEAM_COLOR_PALETTE_SIZE 16
703{255,239,223,211,195,174,167,151,135,123,107,91,79,63,47,35};
727 assert(root !=
NULL);
728 if (!ExportOptions.ExportGeometry)
return true;
733 HierarchySaveClass * htree =
NULL;
734 if (ExportOptions.LoadHierarchy || ExportOptions.ExportHierarchy) {
735 htree = get_hierarchy_tree();
741 DynamicVectorClass<GeometryExportTaskClass *> export_tasks;
742 INodeListClass *geometry_list =
NULL;
747 GeometryFilterClass geometryfilter;
748 geometry_list =
new INodeListClass(root,CurTime,&geometryfilter);
749 if (dupe_check(*geometry_list)) {
753 MaxWorldInfoClass world_info(export_tasks);
754 world_info.Allow_Mesh_Smoothing (ExportOptions.SmoothBetweenMeshes);
755 unsigned int materialColors[16*16];
756 char materialColorFilename[_MAX_FNAME + 1];
757 memset(materialColors,0,
sizeof(materialColors));
766 GeometryExportContextClass context( name,
776 if (ExportOptions.EnableMaterialColorToTextureConversion)
777 context.materialColorTexture=materialColorFilename;
785 int geometry_count = geometry_list->
Num_Nodes();
787 geometry_count =
MIN(geometry_count,1);
788 ExportLog::printf(
"\nDiscarding extra meshes since we are not exporting a hierarchical model.\n");
791 for (i=0; i<geometry_count; i++) {
793 if (export_task !=
NULL) {
794 export_tasks.
Add(export_task);
802 if (ExportOptions.EnableOptimizeMeshData) {
810 if ((export_tasks.
Count() == 1) && (htree ==
NULL))
812 export_tasks[0]->Set_Name(name);
813 export_tasks[0]->Set_Container_Name(
"");
819 MeshConnectionsClass * meshcon =
NULL;
821 Progress_Meter_Class mcmeter(meter,meter.
Increment);
823 meshcon =
new MeshConnectionsClass(export_tasks,context);
824 }
catch (ErrorClass err) {
828 *out_connection = meshcon;
835 for (i=0; i<export_tasks.
Count(); i++) {
836 Progress_Meter_Class meshmeter(meter,meter.
Increment);
837 context.ProgressMeter = &meshmeter;
840 export_tasks[i]->Export_Geometry(context);
841 }
catch (ErrorClass err) {
842 MessageBox(MaxInterface->GetMAXHWnd(),err.
error_message,
"Error!",MB_OK | MB_SETFOREGROUND);
850 if (context.numMaterialColors || context.numHouseColors)
853 char imageBuffer[16*16*3];
855 unsigned int Diffuse;
858 memset(imageBuffer,0,
sizeof(imageBuffer));
860 for (i=0; i<(16+context.numMaterialColors); i++)
866 Diffuse=context.materialColors[i];
867 buf_index=(px+py*16)*3;
869 imageBuffer[buf_index]=(Diffuse>>16)&0xff;
870 imageBuffer[buf_index+1]=(Diffuse>>8)&0xff;
871 imageBuffer[buf_index+2]=(Diffuse)&0xff;
877 targ.
Header.PixelDepth=24;
882 if (context.numHouseColors)
891 for (i=0; i<export_tasks.
Count(); i++) {
892 delete export_tasks[i];
896 delete geometry_list;
914bool W3dExportClass::Export_HLod(
char *name,
const char *htree_name,
ChunkSaveClass &csave,
918 if (!ExportOptions.ExportGeometry)
return true;
920 HLodSaveClass hlod_save(connections, lod_count, CurTime, name, htree_name, meter, get_origin_list());
921 if (!hlod_save.Save(csave))
944 if (HierarchyTree !=
NULL)
return HierarchyTree;
950 if (!ExportOptions.ExportHierarchy) {
951 HierarchyTree = load_hierarchy_file(HierarchyFilename);
953 return HierarchyTree;
956 sprintf(buf,
"Unable to load hierarchy file: %s\nIf this Max file has been moved, please re-select the hierarchy file.",HierarchyFilename);
957 MessageBox(MaxInterface->GetMAXHWnd(),buf,
"Error",MB_OK | MB_SETFOREGROUND);
986 if (DamageRootList !=
NULL)
return DamageRootList;
991 DamageRootFilterClass nodefilter;
992 DamageRootList =
new INodeListClass(ExportInterface->theScene, CurTime, &nodefilter);
993 return DamageRootList;
1011 if (OriginList !=
NULL)
return OriginList;
1016 static OriginFilterClass originfilter;
1017 OriginList =
new INodeListClass (ExportInterface->theScene, CurTime, &originfilter);
1026 if (OriginList->Num_Nodes() == 0) {
1027 OriginList->Insert(MaxInterface->GetRootNode());
1046bool W3dExportClass::get_export_options(
BOOL suppress_prompts)
1048 int ticksperframe = GetTicksPerFrame();
1054 W3dExportOptionsStruct *options =
NULL;
1056 AppDataChunk * appdata = MaxInterface->GetScenePointer()->GetAppDataChunk(
W3D_EXPORTER_CLASS_ID,SCENE_EXPORT_CLASS_ID,0);
1059 options = &(((ExportInfoAppDataChunkStruct *)(appdata->data))->ExportOptions);
1062 ExportInfoAppDataChunkStruct *appdata_struct =
1063 (ExportInfoAppDataChunkStruct *)malloc(
sizeof(ExportInfoAppDataChunkStruct));
1087 options->
StartFrame = MaxInterface->GetAnimRange().Start() / ticksperframe;
1088 options->
EndFrame = MaxInterface->GetAnimRange().End() / ticksperframe;
1094 memset(&(appdata_struct->
Padding), 0,
sizeof(appdata_struct->
Padding));
1097 SCENE_EXPORT_CLASS_ID, 0,
sizeof(ExportInfoAppDataChunkStruct),
1106 if (suppress_prompts ==
FALSE)
1108 W3dOptionsDialogClass dialog(MaxInterface,ExportInterface);
1109 retval = dialog.Get_Export_Options(options);
1112 if (suppress_prompts || retval) {
1114 ExportOptions = *options;
1121 char curdir[_MAX_DRIVE + _MAX_DIR + 1];
1122 assert(_getcwd(curdir,
sizeof(curdir)));
1125 sizeof(HierarchyFilename)));
1126 assert(_chdir(curdir) != -1);
1131 if (ExportOptions.TranslationOnly) {
1156void W3dExportClass::Start_Progress_Bar(
void)
1158 MaxInterface->ProgressStart(
1159 "Processing Triangle Mesh",
1177void W3dExportClass::End_Progress_Bar(
void)
1179 MaxInterface->ProgressUpdate( 100);
1180 MaxInterface->ProgressEnd();
1185 for (
unsigned i=0; i<list.
Num_Nodes(); i++) {
1191 for (
unsigned j = i+1; j<list.
Num_Nodes(); j++) {
1192 if (stricmp(list[i]->GetName(),list[j]->GetName()) == 0) {
1194 sprintf(buf,
"Geometry Nodes with duplicated names found!\nDuplicated Name: %s\n",list[i]->GetName());
1195 MessageBox(
NULL,buf,
"Error",MB_OK | MB_SETFOREGROUND);
1204static bool check_lod_extensions (
INodeListClass &list, INode *origin)
1213 if (origin ==
NULL)
return true;
1214 if (origin->IsRootNode())
return true;
1216 char *extension = strrchr(origin->GetName(),
'.');
1217 int ext_len = strlen(extension);
1218 for (
unsigned i = 0; i < list.
Num_Nodes(); i++)
1220 char *this_ext = strrchr(list[i]->GetName(),
'.');
1223 if (this_ext ==
NULL)
1227 if (strcmp(this_ext, extension) != 0)
1235bool W3dExportClass::get_base_object_tm (
Matrix3 &tm)
1237 INodeListClass *origin_list = get_origin_list();
1241 unsigned int i, count = origin_list->
Num_Nodes();
1242 INode *base_origin =
NULL;
1243 for (i = 0; i < count; i++)
1245 INode *node = (*origin_list)[i];
1256 tm = base_origin->GetNodeTM(CurTime);
1260static DWORD WINAPI progress_callback(
LPVOID arg )
1287 cload.Close_Chunk();
LPVOID(__stdcall *SnmpUtilMemAllocPtr)(IN DWORD bytes)
const UnsignedShort houseColorScale[TEAM_COLOR_PALETTE_SIZE]
virtual BOOL Accept_Node(INode *node, TimeValue time)
DamageRegionFilterClass(int region_id)
virtual BOOL Accept_Node(INode *node, TimeValue time)
bool Add(T const &object)
static void Init(HWND parent)
static void Shutdown(bool wait_for_ok)
static void printf(char *,...)
static GeometryExportTaskClass * Create_Task(INode *node, GeometryExportContextClass &context)
static void Optimize_Geometry(DynamicVectorClass< GeometryExportTaskClass * > &tasks, GeometryExportContextClass &context)
virtual BOOL Accept_Node(INode *node, TimeValue time)
bool Load(ChunkLoadClass &cload)
const char * Get_Name(void) const
static void Enable_Terrain_Optimization(bool onoff)
unsigned Num_Nodes(void) const
bool Save(ChunkSaveClass &csave)
virtual BOOL Accept_Node(INode *node, TimeValue time)
void Finish_In_Steps(int number_of_steps)
virtual int Open(char const *filename, int rights=READ)
char * SetImage(char *buffer)
long Save(const char *name, long flags, bool addextension=false)
int DoExport(const TCHAR *name, ExpInterface *ei, Interface *i, BOOL suppressPrompts=FALSE, DWORD options=0)
char CurrentScenePath[_MAX_DRIVE+_MAX_DIR+1]
static char CurrentExportPath[_MAX_DRIVE+_MAX_DIR+1]
void DoOriginBasedExport(char *rootname, ChunkSaveClass &csave)
WWINLINE Quaternion Inverse(const Quaternion &a)
unsigned char Padding[89]
W3dExportOptionsStruct ExportOptions
bool EnableOptimizeMeshData
char RelativeHierarchyFilename[_MAX_PATH]
int CompressAnimationFlavor
bool EnableMaterialColorToTextureConversion
float CompressAnimationRotationError
int ReduceAnimationPercent
bool DisableExportAABTrees
char HierarchyFilename[_MAX_PATH]
float CompressAnimationTranslationError
bool Is_Base_Origin(INode *node)
int Get_Lod_Level(INode *node)
bool Is_Damage_Root(INode *node)
bool Is_Origin(INode *node)
int Get_Damage_State(INode *node)
bool Is_Geometry(INode *node)
bool Is_Aggregate(INode *node)
bool Is_Bone(INode *node)
#define MAX_DAMAGE_REGIONS
#define W3D_EXPORTER_CLASS_ID
#define TEAM_COLOR_PALETTE_SIZE
#define W3DUtilityClassID