Changed: #1092 Reliability improvements for 3dsmax nel export

This commit is contained in:
kaetemi 2010-09-21 00:44:02 +02:00
parent 998e5b4c17
commit 7f739bed8a
4 changed files with 115 additions and 22 deletions

View file

@ -36,11 +36,18 @@ bool CNelExport::exportMesh (const char *sPath, INode& node, TimeValue time)
{ {
// Result to return // Result to return
bool bRet = false; bool bRet = false;
char tempName[L_tmpnam]; char tempFileName[MAX_PATH] = { 0 };
tmpnam(tempName); char tempPathBuffer[MAX_PATH] = { 0 };
try try
{ {
DWORD dwRetVal = GetTempPathA(MAX_PATH, tempPathBuffer);
if (dwRetVal > MAX_PATH || (dwRetVal == 0))
nlerror("GetTempPath failed");
UINT uRetVal = GetTempFileNameA(tempPathBuffer, TEXT("_nel_export_mesh_"), 0, tempFileName);
if (uRetVal == 0)
nlerror("GetTempFileName failed");
// Eval the object a time // Eval the object a time
ObjectState os = node.EvalWorldState(time); ObjectState os = node.EvalWorldState(time);
@ -48,7 +55,7 @@ bool CNelExport::exportMesh (const char *sPath, INode& node, TimeValue time)
if (os.obj) if (os.obj)
{ {
// Skeleton shape // Skeleton shape
CSmartPtr<CSkeletonShape> skeletonShape = NULL; CSkeletonShape * skeletonShape = NULL;
TInodePtrInt *mapIdPtr=NULL; TInodePtrInt *mapIdPtr=NULL;
TInodePtrInt mapId; TInodePtrInt mapId;
@ -69,7 +76,7 @@ bool CNelExport::exportMesh (const char *sPath, INode& node, TimeValue time)
CExportNel::addSkeletonBindPos (node, boneBindPos); CExportNel::addSkeletonBindPos (node, boneBindPos);
// Build the skeleton based on the bind pos information // Build the skeleton based on the bind pos information
_ExportNel->buildSkeletonShape(*skeletonShape.getPtr(), *skeletonRoot, &boneBindPos, mapId, time); _ExportNel->buildSkeletonShape(*skeletonShape, *skeletonRoot, &boneBindPos, mapId, time);
// Set the pointer to not NULL // Set the pointer to not NULL
mapIdPtr=&mapId; mapIdPtr=&mapId;
@ -83,16 +90,16 @@ bool CNelExport::exportMesh (const char *sPath, INode& node, TimeValue time)
if (InfoLog) if (InfoLog)
InfoLog->display("Beg buildShape %s \n", node.GetName()); InfoLog->display("Beg buildShape %s \n", node.GetName());
// Export in mesh format // Export in mesh format
CSmartPtr<IShape> pShape = _ExportNel->buildShape(node, time, mapIdPtr, true); IShape *pShape = _ExportNel->buildShape(node, time, mapIdPtr, true);
if (InfoLog) if (InfoLog)
InfoLog->display("End buildShape in %d ms \n", timeGetTime()-t); InfoLog->display("End buildShape in %d ms \n", timeGetTime()-t);
// Conversion success ? // Conversion success ?
if (pShape.getPtr()) if (pShape)
{ {
// Open a file // Open a file
COFile file; COFile file;
if (file.open(tempName)) if (file.open(tempFileName))
{ {
try try
{ {
@ -102,6 +109,9 @@ bool CNelExport::exportMesh (const char *sPath, INode& node, TimeValue time)
// Serial the shape // Serial the shape
shapeStream.serial(file); shapeStream.serial(file);
// Close the file
file.close();
// All is good // All is good
bRet = true; bRet = true;
} }
@ -116,29 +126,61 @@ bool CNelExport::exportMesh (const char *sPath, INode& node, TimeValue time)
{ {
} }
remove(tempName); remove(tempFileName);
} }
} }
else else
{ {
nlwarning("Failed to create file %s", tempName); nlwarning("Failed to create file %s", tempFileName);
} }
// Delete the pointer // Delete the pointer
nldebug ("Delete the pointer"); nldebug("Delete the pointer");
try try
{ {
bool tempBRet = bRet; bool tempBRet = bRet;
bRet = false; bRet = false;
pShape = NULL; // delete pShape; // FIXME: there is a delete bug with CMeshMultiLod exported from max!!!
bRet = tempBRet; bRet = tempBRet;
} }
catch (...) catch (...)
{ {
nlwarning("Failed to delete pShape pointer! Something might be wrong."); nlwarning("Failed to delete pShape pointer! Something might be wrong.");
remove(tempName); remove(tempFileName);
bRet = false; bRet = false;
} }
// Verify the file
nldebug("Verify exported shape file");
try
{
bool tempBRet = bRet;
bRet = false;
CIFile vf;
if (vf.open(tempFileName))
{
nldebug("File opened, size: %u", vf.getFileSize());
CShapeStream s;
s.serial(vf);
nldebug("Shape serialized");
vf.close();
nldebug("File closed");
delete s.getShapePointer();
nldebug("Shape deleted");
bRet = tempBRet;
}
else
{
nlwarning("Failed to open file: %s", tempFileName);
}
}
catch (...)
{
nlwarning("Failed to verify shape. Must crash now.");
remove(tempFileName);
bRet = false;
}
} }
} }
} }
@ -158,8 +200,8 @@ bool CNelExport::exportMesh (const char *sPath, INode& node, TimeValue time)
{ {
} }
CFile::moveFile(sPath, tempName); CFile::moveFile(sPath, tempFileName);
nlinfo("MOVE %s -> %s", tempName, sPath); nlinfo("MOVE %s -> %s", tempFileName, sPath);
} }
return bRet; return bRet;

View file

@ -55,6 +55,9 @@ def_visible_primitive ( mirror_physique, "NelMirrorPhysique" );
def_visible_primitive ( get_file_modification_date, "NeLGetFileModificationDate" ); def_visible_primitive ( get_file_modification_date, "NeLGetFileModificationDate" );
def_visible_primitive ( set_file_modification_date, "NeLSetFileModificationDate" ); def_visible_primitive ( set_file_modification_date, "NeLSetFileModificationDate" );
def_visible_primitive ( force_quit_on_msg_displayer, "NelForceQuitOnMsgDisplayer");
def_visible_primitive ( force_quit_right_now, "NelForceQuitRightNow");
char *sExportShapeErrorMsg = "NeLExportShape [Object] [Filename.shape]"; char *sExportShapeErrorMsg = "NeLExportShape [Object] [Filename.shape]";
char *sExportShapeExErrorMsg = "NeLExportShapeEx [Object] [Filename.shape] [bShadow] [bExportLighting] [sLightmapPath] [nLightingLimit] [fLumelSize] [nOverSampling] [bExcludeNonSelected] [bShowLumel]"; char *sExportShapeExErrorMsg = "NeLExportShapeEx [Object] [Filename.shape] [bShadow] [bExportLighting] [sLightmapPath] [nLightingLimit] [fLumelSize] [nOverSampling] [bExcludeNonSelected] [bShowLumel]";
char *sExportAnimationErrorMsg = "NelExportAnimation [node array] [Filename.anim] [bool_scene_animation]"; char *sExportAnimationErrorMsg = "NelExportAnimation [node array] [Filename.anim] [bool_scene_animation]";
@ -933,6 +936,55 @@ Value* set_file_modification_date_cf (Value** arg_list, int count)
return &false_value; return &false_value;
} }
class CSuicideMsgBoxDisplayer : public CMsgBoxDisplayer
{
public:
CSuicideMsgBoxDisplayer (const char *displayerName = "") : CMsgBoxDisplayer(displayerName) { }
protected:
/// Put the string into the file.
virtual void doDisplay( const CLog::TDisplayInfo& args, const char *message )
{
DWORD ec = 0;
HANDLE h = OpenProcess(PROCESS_ALL_ACCESS, 0, GetCurrentProcessId());
GetExitCodeProcess(h, &ec);
TerminateProcess(h, ec);
}
};
Value* force_quit_on_msg_displayer_cf(Value** arg_list, int count)
{
nlwarning("Enable force quit on NeL report msg displayer");
// disable the Windows popup telling that the application aborted and disable the dr watson report.
_set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
putenv("NEL_IGNORE_ASSERT=1");
if (NLMISC::DefaultMsgBoxDisplayer || INelContext::getInstance().getDefaultMsgBoxDisplayer())
{
if (!NLMISC::DefaultMsgBoxDisplayer)
NLMISC::DefaultMsgBoxDisplayer = INelContext::getInstance().getDefaultMsgBoxDisplayer();
nldebug("Disable NeL report msg displayer");
INelContext::getInstance().getAssertLog()->removeDisplayer(NLMISC::DefaultMsgBoxDisplayer);
INelContext::getInstance().getErrorLog()->removeDisplayer(NLMISC::DefaultMsgBoxDisplayer);
// TODO: Delete original NLMISC::DefaultMsgBoxDisplayer?
}
NLMISC::DefaultMsgBoxDisplayer = new CSuicideMsgBoxDisplayer("FORCEQUIT_MDB");
INelContext::getInstance().setDefaultMsgBoxDisplayer(NLMISC::DefaultMsgBoxDisplayer);
INelContext::getInstance().getAssertLog()->addDisplayer(NLMISC::DefaultMsgBoxDisplayer);
INelContext::getInstance().getErrorLog()->addDisplayer(NLMISC::DefaultMsgBoxDisplayer);
return &true_value;
}
Value* force_quit_right_now_cf(Value** arg_list, int count)
{
// because quitMAX can fail
nlwarning("Force quit");
DWORD ec = 0;
HANDLE h = OpenProcess(PROCESS_ALL_ACCESS, 0, GetCurrentProcessId());
GetExitCodeProcess(h, &ec);
TerminateProcess(h, ec);
return &true_value;
}
/*===========================================================================*\ /*===========================================================================*\
| MAXScript Plugin Initialization | MAXScript Plugin Initialization
\*===========================================================================*/ \*===========================================================================*/

View file

@ -131,7 +131,7 @@ static void copyMultiLodMeshBaseLod0Infos(CMeshBase::CMeshBaseBuild &dst, const
// *************************************************************************** // ***************************************************************************
// Export a mesh // Export a mesh
NLMISC::CSmartPtr<NL3D::IShape> CExportNel::buildShape (INode& node, TimeValue time, const TInodePtrInt *nodeMap, bool buildLods) NL3D::IShape *CExportNel::buildShape (INode& node, TimeValue time, const TInodePtrInt *nodeMap, bool buildLods)
{ {
// Is this a multi lod object ? // Is this a multi lod object ?
@ -139,7 +139,7 @@ NLMISC::CSmartPtr<NL3D::IShape> CExportNel::buildShape (INode& node, TimeValue t
// Here, we must check what kind of node we can build with this mesh. // Here, we must check what kind of node we can build with this mesh.
// For the time, just Triobj is supported. // For the time, just Triobj is supported.
CSmartPtr<IShape> retShape = NULL; NL3D::IShape *retShape = NULL;
// If skinning, disable skin modifier // If skinning, disable skin modifier
if (nodeMap) if (nodeMap)
@ -206,7 +206,7 @@ NLMISC::CSmartPtr<NL3D::IShape> CExportNel::buildShape (INode& node, TimeValue t
else else
{ {
// Mesh base ? // Mesh base ?
CSmartPtr<CMeshBase> meshBase = NULL; CMeshBase *meshBase = NULL;
// Get the node matrix // Get the node matrix
Matrix3 nodeMatrixMax; Matrix3 nodeMatrixMax;
@ -317,8 +317,7 @@ NLMISC::CSmartPtr<NL3D::IShape> CExportNel::buildShape (INode& node, TimeValue t
// Make a CMeshMultiLod mesh object // Make a CMeshMultiLod mesh object
CMeshMultiLod *multiMesh = new CMeshMultiLod; CMeshMultiLod *multiMesh = new CMeshMultiLod; // FIXME: there is a delete bug with CMeshMultiLod exported from max!!!
++multiMesh->crefs; // hack
// Build it // Build it
multiMesh->build(multiLodBuild); multiMesh->build(multiLodBuild);
@ -461,7 +460,7 @@ NLMISC::CSmartPtr<NL3D::IShape> CExportNel::buildShape (INode& node, TimeValue t
enableSkinModifier (node, true); enableSkinModifier (node, true);
// Set the dist max for this shape // Set the dist max for this shape
if (retShape.getPtr() && !multiLodObject && buildLods) if (retShape && !multiLodObject && buildLods)
{ {
// Get the dist max for this node // Get the dist max for this node
float distmax = getScriptAppData (&node, NEL3D_APPDATA_LOD_DIST_MAX, NEL3D_APPDATA_LOD_DIST_MAX_DEFAULT); float distmax = getScriptAppData (&node, NEL3D_APPDATA_LOD_DIST_MAX, NEL3D_APPDATA_LOD_DIST_MAX_DEFAULT);

View file

@ -292,7 +292,7 @@ public:
* *
* skeletonShape must be NULL if no bones. * skeletonShape must be NULL if no bones.
*/ */
NLMISC::CSmartPtr<NL3D::IShape> buildShape (INode& node, TimeValue time, const TInodePtrInt *nodeMap, NL3D::IShape* buildShape (INode& node, TimeValue time, const TInodePtrInt *nodeMap,
bool buildLods); bool buildLods);
/** /**