diff --git a/code/nel/tools/3d/plugin_max/nel_export/nel_export_export.cpp b/code/nel/tools/3d/plugin_max/nel_export/nel_export_export.cpp index c79295925..9f582bd23 100644 --- a/code/nel/tools/3d/plugin_max/nel_export/nel_export_export.cpp +++ b/code/nel/tools/3d/plugin_max/nel_export/nel_export_export.cpp @@ -17,6 +17,7 @@ #include "std_afx.h" #include "nel_export.h" #include "nel/misc/file.h" +#include "nel/misc/path.h" #include "nel/3d/shape.h" #include "nel/3d/animation.h" #include "nel/3d/skeleton_shape.h" @@ -34,94 +35,133 @@ using namespace NLMISC; bool CNelExport::exportMesh (const char *sPath, INode& node, TimeValue time) { // Result to return - bool bRet=false; - - // Eval the object a time - ObjectState os = node.EvalWorldState(time); - - // Object exist ? - if (os.obj) + bool bRet = false; + char tempName[L_tmpnam]; + tmpnam(tempName); + + try { - // Skeleton shape - CSkeletonShape *skeletonShape=NULL; - TInodePtrInt *mapIdPtr=NULL; - TInodePtrInt mapId; + // Eval the object a time + ObjectState os = node.EvalWorldState(time); - // If model skinned ? - if (CExportNel::isSkin (node)) + // Object exist ? + if (os.obj) { - // Create a skeleton - INode *skeletonRoot=CExportNel::getSkeletonRootBone (node); + // Skeleton shape + CSmartPtr skeletonShape = NULL; + TInodePtrInt *mapIdPtr=NULL; + TInodePtrInt mapId; - // Skeleton exist ? - if (skeletonRoot) + // If model skinned ? + if (CExportNel::isSkin (node)) { - // Build a skeleton - skeletonShape=new CSkeletonShape(); + // Create a skeleton + INode *skeletonRoot = CExportNel::getSkeletonRootBone(node); - // Add skeleton bind pos info - CExportNel::mapBoneBindPos boneBindPos; - CExportNel::addSkeletonBindPos (node, boneBindPos); + // Skeleton exist ? + if (skeletonRoot) + { + // Build a skeleton + skeletonShape = new CSkeletonShape(); - // Build the skeleton based on the bind pos information - _ExportNel->buildSkeletonShape (*skeletonShape, *skeletonRoot, &boneBindPos, mapId, time); + // Add skeleton bind pos info + CExportNel::mapBoneBindPos boneBindPos; + CExportNel::addSkeletonBindPos (node, boneBindPos); - // Set the pointer to not NULL - mapIdPtr=&mapId; + // Build the skeleton based on the bind pos information + _ExportNel->buildSkeletonShape(*skeletonShape.getPtr(), *skeletonRoot, &boneBindPos, mapId, time); - // Erase the skeleton - if (skeletonShape) - delete skeletonShape; + // Set the pointer to not NULL + mapIdPtr=&mapId; + + // Erase the skeleton + skeletonShape = NULL; + } } - } - - DWORD t = timeGetTime(); - if (InfoLog) - InfoLog->display("Beg buildShape %s \n", node.GetName()); - // Export in mesh format - IShape* pShape=_ExportNel->buildShape (node, time, mapIdPtr, true); - if (InfoLog) - InfoLog->display("End buildShape in %d ms \n", timeGetTime()-t); - - // Conversion success ? - if (pShape) - { - // Open a file - COFile file; - if (file.open (sPath)) + + DWORD t = timeGetTime(); + if (InfoLog) + InfoLog->display("Beg buildShape %s \n", node.GetName()); + // Export in mesh format + CSmartPtr pShape = _ExportNel->buildShape(node, time, mapIdPtr, true); + if (InfoLog) + InfoLog->display("End buildShape in %d ms \n", timeGetTime()-t); + + // Conversion success ? + if (pShape.getPtr()) { + // Open a file + COFile file; + if (file.open(tempName)) + { + try + { + // Create a streamable shape + CShapeStream shapeStream(pShape); + + // Serial the shape + shapeStream.serial(file); + + // All is good + bRet = true; + } + catch (...) + { + nlwarning("Shape serialization failed!"); + try + { + file.close(); + } + catch (...) + { + + } + remove(tempName); + } + } + else + { + nlwarning("Failed to create file %s", tempName); + } + + // Delete the pointer + nldebug ("Delete the pointer"); try { - // Create a streamable shape - CShapeStream shapeStream (pShape); - - // Serial the shape - shapeStream.serial (file); - - // All is good - bRet=true; + bool tempBRet = bRet; + bRet = false; + pShape = NULL; + bRet = tempBRet; } catch (...) { - nlwarning("Shape serialization failed!"); - file.close(); - remove(sPath); + nlwarning("Failed to delete pShape pointer! Something might be wrong."); + remove(tempName); + bRet = false; } } - - // Delete the pointer - nldebug ("Delete the pointer"); - try - { - // memory leak, fixme - // delete pShape; - } - catch (...) - { - nlwarning("Failed to delete pShape pointer! Something might be wrong."); - } } } + catch (...) + { + nlwarning("Fatal exception at CNelExport::exportMesh."); + bRet = false; + } + + if (bRet) + { + try + { + remove(sPath); + } + catch (...) + { + + } + CFile::moveFile(sPath, tempName); + nlinfo("MOVE %s -> %s", tempName, sPath); + } + return bRet; } diff --git a/code/nel/tools/3d/plugin_max/nel_mesh_lib/calc_lm.cpp b/code/nel/tools/3d/plugin_max/nel_mesh_lib/calc_lm.cpp index 9f5d95441..e65b4ea56 100644 --- a/code/nel/tools/3d/plugin_max/nel_mesh_lib/calc_lm.cpp +++ b/code/nel/tools/3d/plugin_max/nel_mesh_lib/calc_lm.cpp @@ -77,7 +77,8 @@ SLightBuild::SLightBuild() bool SLightBuild::canConvertFromMaxLight (INode *node, TimeValue tvTime) { // Get a pointer on the object's node - Object *obj = node->EvalWorldState(tvTime).obj; + ObjectState os = node->EvalWorldState(tvTime); + Object *obj = os.obj; // Check if there is an object if (!obj) @@ -98,7 +99,7 @@ bool SLightBuild::canConvertFromMaxLight (INode *node, TimeValue tvTime) return false; if( deleteIt ) - maxLight->DeleteMe(); + maxLight->MaybeAutoDelete(); return true; } @@ -107,7 +108,8 @@ bool SLightBuild::canConvertFromMaxLight (INode *node, TimeValue tvTime) void SLightBuild::convertFromMaxLight (INode *node,TimeValue tvTime) { // Get a pointer on the object's node - Object *obj = node->EvalWorldState(tvTime).obj; + ObjectState os = node->EvalWorldState(tvTime); + Object *obj = os.obj; // Check if there is an object if (!obj) return; @@ -295,7 +297,7 @@ void SLightBuild::convertFromMaxLight (INode *node,TimeValue tvTime) this->rSoftShadowConeLength = (float)atof(sTmp.c_str()); if( deleteIt ) - maxLight->DeleteMe(); + maxLight->MaybeAutoDelete(); } // *********************************************************************************************** @@ -2401,7 +2403,10 @@ bool CExportNel::calculateLM( CMesh::CMeshBuild *pZeMeshBuild, CMeshBase::CMeshB TempPlanes[nPlaneNb]->copyFirstLayerTo(*AllPlanes[AllPlanesPrevSize+nPlaneNb],(uint8)nLight); for( nPlaneNb = 0; nPlaneNb < (sint)FaceGroupByPlane.size(); ++nPlaneNb ) + { delete TempPlanes[nPlaneNb]; + TempPlanes[nPlaneNb] = NULL; + } } // Next group of face with the same smooth group and the same material @@ -2497,6 +2502,7 @@ bool CExportNel::calculateLM( CMesh::CMeshBuild *pZeMeshBuild, CMeshBase::CMeshB MoveFaceUV1( AllPlanes[i]->faces.begin(), AllPlanes[i]->faces.size(), AllPlanes[i]->x, AllPlanes[i]->y ); delete AllPlanes[i]; + AllPlanes[i] = NULL; } // Save the lightmap diff --git a/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_anim.cpp b/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_anim.cpp index f47204575..3a5d5a259 100644 --- a/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_anim.cpp +++ b/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_anim.cpp @@ -264,6 +264,7 @@ void CExportNel::addParticleSystemTracks(CAnimation& animation, INode& node, con if (animation.getTrackByName (name.c_str())) { delete pTrack; + pTrack = NULL; } else { @@ -281,6 +282,7 @@ void CExportNel::addParticleSystemTracks(CAnimation& animation, INode& node, con if (animation.getTrackByName (name.c_str())) { delete pTrack; + pTrack = NULL; } else { @@ -325,6 +327,7 @@ void CExportNel::addNodeTracks (CAnimation& animation, INode& node, const char* if (animation.getTrackByName (name.c_str())) { delete pTrack; + pTrack = NULL; } else { @@ -348,6 +351,7 @@ void CExportNel::addNodeTracks (CAnimation& animation, INode& node, const char* if (animation.getTrackByName (name.c_str())) { delete pTrack; + pTrack = NULL; } else { @@ -371,6 +375,7 @@ void CExportNel::addNodeTracks (CAnimation& animation, INode& node, const char* if (animation.getTrackByName (name.c_str())) { delete pTrack; + pTrack = NULL; } else { @@ -389,6 +394,7 @@ void CExportNel::addNodeTracks (CAnimation& animation, INode& node, const char* if (animation.getTrackByName (name.c_str())) { delete pTrack; + pTrack = NULL; } else { @@ -413,6 +419,7 @@ void CExportNel::addNodeTracks (CAnimation& animation, INode& node, const char* if (animation.getTrackByName (name.c_str())) { delete pTrack; + pTrack = NULL; } else { @@ -443,6 +450,7 @@ void CExportNel::addNodeTracks (CAnimation& animation, INode& node, const char* if (animation.getTrackByName (name.c_str())) { delete pTrack; + pTrack = NULL; } else { @@ -541,7 +549,8 @@ void CExportNel::addLightTracks (NL3D::CAnimation& animation, INode& node, const { CExportDesc desc; - Object *obj = node.EvalWorldState(0).obj; + ObjectState os = node.EvalWorldState(0); + Object *obj = os.obj; // Check if there is an object if (!obj) @@ -567,6 +576,7 @@ void CExportNel::addLightTracks (NL3D::CAnimation& animation, INode& node, const if (animation.getTrackByName (name.c_str())) { delete pTrack; + pTrack = NULL; } else { @@ -609,6 +619,7 @@ void CExportNel::addMorphTracks (NL3D::CAnimation& animation, INode& node, const if (animation.getTrackByName (name.c_str())) { delete pTrack; + pTrack = NULL; } else { @@ -639,6 +650,7 @@ void CExportNel::addObjTracks (CAnimation& animation, Object& obj, const char* p if (animation.getTrackByName (name.c_str())) { delete pTrack; + pTrack = NULL; } else { @@ -681,6 +693,7 @@ void CExportNel::addMtlTracks (CAnimation& animation, Mtl& mtl, const char* pare if (animation.getTrackByName (name.c_str())) { delete pTrack; + pTrack = NULL; } else { @@ -705,6 +718,7 @@ void CExportNel::addMtlTracks (CAnimation& animation, Mtl& mtl, const char* pare if (animation.getTrackByName (name.c_str())) { delete pTrack; + pTrack = NULL; } else { @@ -731,6 +745,7 @@ void CExportNel::addMtlTracks (CAnimation& animation, Mtl& mtl, const char* pare if (animation.getTrackByName (name.c_str())) { delete pTrack; + pTrack = NULL; } else { @@ -755,6 +770,7 @@ void CExportNel::addMtlTracks (CAnimation& animation, Mtl& mtl, const char* pare if (animation.getTrackByName (name.c_str())) { delete pTrack; + pTrack = NULL; } else { @@ -779,6 +795,7 @@ void CExportNel::addMtlTracks (CAnimation& animation, Mtl& mtl, const char* pare if (animation.getTrackByName (name.c_str())) { delete pTrack; + pTrack = NULL; } else { @@ -862,6 +879,7 @@ void CExportNel::addTexTracks (CAnimation& animation, Texmap& tex, uint stage, c if (animation.getTrackByName (name.c_str())) { delete pTrack; + pTrack = NULL; } else { @@ -884,6 +902,7 @@ void CExportNel::addTexTracks (CAnimation& animation, Texmap& tex, uint stage, c if (animation.getTrackByName (name.c_str())) { delete pTrack; + pTrack = NULL; } else { @@ -906,6 +925,7 @@ void CExportNel::addTexTracks (CAnimation& animation, Texmap& tex, uint stage, c if (animation.getTrackByName (name.c_str())) { delete pTrack; + pTrack = NULL; } else { @@ -928,6 +948,7 @@ void CExportNel::addTexTracks (CAnimation& animation, Texmap& tex, uint stage, c if (animation.getTrackByName (name.c_str())) { delete pTrack; + pTrack = NULL; } else { @@ -950,6 +971,7 @@ void CExportNel::addTexTracks (CAnimation& animation, Texmap& tex, uint stage, c if (animation.getTrackByName (name.c_str())) { delete pTrack; + pTrack = NULL; } else { @@ -2319,7 +2341,7 @@ void CSSSBuild::compile(NL3D::CAnimation &dest, const char* sBaseName) { // no keys added delete finalTrack; - finalTrack= NULL; + finalTrack = NULL; } diff --git a/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_collision.cpp b/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_collision.cpp index b0264a8e9..e417539ce 100644 --- a/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_collision.cpp +++ b/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_collision.cpp @@ -60,7 +60,8 @@ CCollisionMeshBuild* CExportNel::createCollisionMeshBuild(std::vector & for (node=0; nodeEvalWorldState(tvTime).obj; + ObjectState os = nodes[node]->EvalWorldState(tvTime); + Object *obj = os.obj; // Check if there is an object if (obj) @@ -70,72 +71,76 @@ CCollisionMeshBuild* CExportNel::createCollisionMeshBuild(std::vector & { // Get a triobject from the node TriObject *tri = (TriObject*)obj->ConvertToType(tvTime, Class_ID(TRIOBJ_CLASS_ID, 0)); - - // get the mesh name - uint meshId = rootMeshNames.size(); - rootMeshNames.push_back(nodes[node]->GetName()); - bool collision = getScriptAppData (nodes[node], NEL3D_APPDATA_COLLISION, 0) != 0; - bool exterior = getScriptAppData (nodes[node], NEL3D_APPDATA_COLLISION_EXTERIOR, 0) != 0; - - bool deleteIt=false; - if (collision) + + if (tri) { - // Note that the TriObject should only be deleted - // if the pointer to it is not equal to the object - // pointer that called ConvertToType() - if (obj != tri) - deleteIt = true; + // get the mesh name + uint meshId = rootMeshNames.size(); + rootMeshNames.push_back(nodes[node]->GetName()); + bool collision = getScriptAppData (nodes[node], NEL3D_APPDATA_COLLISION, 0) != 0; + bool exterior = getScriptAppData (nodes[node], NEL3D_APPDATA_COLLISION_EXTERIOR, 0) != 0; - uint i; - Mesh &mesh = tri->GetMesh(); - - // Get the object matrix - CMatrix ToWorldSpace; - Matrix3 verticesToWorld = nodes[node]->GetObjectTM(tvTime); - convertMatrix (ToWorldSpace, verticesToWorld); - - // Convert the vertices - for (i=0; i<(uint)mesh.numVerts; ++i) + bool deleteIt=false; + if (collision) { - Point3 v=mesh.verts[i]; - CVector vv=ToWorldSpace*CVector (v.x, v.y, v.z); - pCollisionMeshBuild->Vertices.push_back(vv); - rootMeshVertices.push_back(node); + // Note that the TriObject should only be deleted + // if the pointer to it is not equal to the object + // pointer that called ConvertToType() + if (obj != tri) + deleteIt = true; + + uint i; + Mesh &mesh = tri->GetMesh(); + + // Get the object matrix + CMatrix ToWorldSpace; + Matrix3 verticesToWorld = nodes[node]->GetObjectTM(tvTime); + convertMatrix (ToWorldSpace, verticesToWorld); + + // Convert the vertices + for (i=0; i<(uint)mesh.numVerts; ++i) + { + Point3 v=mesh.verts[i]; + CVector vv=ToWorldSpace*CVector (v.x, v.y, v.z); + pCollisionMeshBuild->Vertices.push_back(vv); + rootMeshVertices.push_back(node); + } + + uint maxMatId = 0; + + // Convert the faces + for (i=0; i<(uint)mesh.numFaces; ++i) + { + facesRootMeshesInfo.push_back(make_pair(meshId, i)); + + pCollisionMeshBuild->Faces.resize(pCollisionMeshBuild->Faces.size()+1); + pCollisionMeshBuild->Faces.back().V[0] = mesh.faces[i].v[0]+totalVertices; + pCollisionMeshBuild->Faces.back().V[1] = mesh.faces[i].v[1]+totalVertices; + pCollisionMeshBuild->Faces.back().V[2] = mesh.faces[i].v[2]+totalVertices; + + pCollisionMeshBuild->Faces.back().Visibility[0] = ((mesh.faces[i].flags & EDGE_B) != 0); + pCollisionMeshBuild->Faces.back().Visibility[1] = ((mesh.faces[i].flags & EDGE_C) != 0); + pCollisionMeshBuild->Faces.back().Visibility[2] = ((mesh.faces[i].flags & EDGE_A) != 0); + + uint32 maxMaterialId = mesh.faces[i].getMatID(); + if (!exterior && maxMaterialId > maxMatId) + maxMatId = maxMaterialId; + sint32 sid = (exterior) ? -1 : totalSurfaces+maxMaterialId; + + pCollisionMeshBuild->Faces.back().Surface = sid; + pCollisionMeshBuild->Faces.back().Material = maxMaterialId; + } + + totalVertices = pCollisionMeshBuild->Vertices.size(); + totalFaces = pCollisionMeshBuild->Faces.size(); + totalSurfaces += maxMatId+1; } - uint maxMatId = 0; + // Delete the triObject if we should... + if (deleteIt) + tri->MaybeAutoDelete(); - // Convert the faces - for (i=0; i<(uint)mesh.numFaces; ++i) - { - facesRootMeshesInfo.push_back(make_pair(meshId, i)); - - pCollisionMeshBuild->Faces.resize(pCollisionMeshBuild->Faces.size()+1); - pCollisionMeshBuild->Faces.back().V[0] = mesh.faces[i].v[0]+totalVertices; - pCollisionMeshBuild->Faces.back().V[1] = mesh.faces[i].v[1]+totalVertices; - pCollisionMeshBuild->Faces.back().V[2] = mesh.faces[i].v[2]+totalVertices; - - pCollisionMeshBuild->Faces.back().Visibility[0] = ((mesh.faces[i].flags & EDGE_B) != 0); - pCollisionMeshBuild->Faces.back().Visibility[1] = ((mesh.faces[i].flags & EDGE_C) != 0); - pCollisionMeshBuild->Faces.back().Visibility[2] = ((mesh.faces[i].flags & EDGE_A) != 0); - - uint32 maxMaterialId = mesh.faces[i].getMatID(); - if (!exterior && maxMaterialId > maxMatId) - maxMatId = maxMaterialId; - sint32 sid = (exterior) ? -1 : totalSurfaces+maxMaterialId; - - pCollisionMeshBuild->Faces.back().Surface = sid; - pCollisionMeshBuild->Faces.back().Material = maxMaterialId; - } - - totalVertices = pCollisionMeshBuild->Vertices.size(); - totalFaces = pCollisionMeshBuild->Faces.size(); - totalSurfaces += maxMatId+1; } - - // Delete the triObject if we should... - if (deleteIt) - tri->DeleteMe(); } } } @@ -436,6 +441,7 @@ void CExportNel::computeCollisionRetrieverFromScene(TimeValue time, // free the CCollisionMeshBuild. delete pCmb; + pCmb = NULL; // does igname match prefix/suffix??? if(igname.find(igNamePrefix)==0) diff --git a/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_light.cpp b/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_light.cpp index 14b38ad78..9bda607bb 100644 --- a/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_light.cpp +++ b/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_light.cpp @@ -200,7 +200,8 @@ void CExportNel::getLights (std::vector& vectLight, TimeValue time, INod node=_Ip->GetRootNode(); // Get a pointer on the object's node - Object *obj = node->EvalWorldState(time).obj; + ObjectState os = node->EvalWorldState(time); + Object *obj = os.obj; // Check if there is an object if (obj) @@ -235,9 +236,9 @@ void CExportNel::getLights (std::vector& vectLight, TimeValue time, INod // Add the light in the list vectLight.push_back (nelLight); - // Delete the triObject if we should... + // Delete the GenLight if we should... if (deleteIt) - maxLight->DeleteMe(); + maxLight->MaybeAutoDelete(); } } diff --git a/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_lod_character.cpp b/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_lod_character.cpp index baccbe17b..40cdbf1e6 100644 --- a/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_lod_character.cpp +++ b/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_lod_character.cpp @@ -43,7 +43,8 @@ bool CExportNel::buildLodCharacter (NL3D::CLodCharacterShapeBuild& lodBuild, IN return false; // Get a pointer on the object's node - Object *obj = node.EvalWorldState(time).obj; + ObjectState os = node.EvalWorldState(time); + Object *obj = os.obj; // Check if there is an object if (obj) @@ -55,129 +56,131 @@ bool CExportNel::buildLodCharacter (NL3D::CLodCharacterShapeBuild& lodBuild, IN { // Get a triobject from the node TriObject *tri = (TriObject *) obj->ConvertToType(time, Class_ID(TRIOBJ_CLASS_ID, 0)); + if (tri) + { + // Note that the TriObject should only be deleted + // if the pointer to it is not equal to the object + // pointer that called ConvertToType() + bool deleteIt=false; + if (obj != tri) + deleteIt = true; - // Note that the TriObject should only be deleted - // if the pointer to it is not equal to the object - // pointer that called ConvertToType() - bool deleteIt=false; - if (obj != tri) - deleteIt = true; - - // Get the node matrix - Matrix3 nodeMatrixMax; - CMatrix nodeMatrix; - getLocalMatrix (nodeMatrixMax, node, time); - convertMatrix (nodeMatrix, nodeMatrixMax); + // Get the node matrix + Matrix3 nodeMatrixMax; + CMatrix nodeMatrix; + getLocalMatrix (nodeMatrixMax, node, time); + convertMatrix (nodeMatrix, nodeMatrixMax); - // build the shape - { - // Array of name for the material - CMaxMeshBaseBuild maxBaseBuild; + // build the shape + { + // Array of name for the material + CMaxMeshBaseBuild maxBaseBuild; - // Fill the build interface of CMesh - CMeshBase::CMeshBaseBuild buildBaseMesh; - buildBaseMeshInterface (buildBaseMesh, maxBaseBuild, node, time, nodeMatrix); + // Fill the build interface of CMesh + CMeshBase::CMeshBaseBuild buildBaseMesh; + buildBaseMeshInterface (buildBaseMesh, maxBaseBuild, node, time, nodeMatrix); - CMesh::CMeshBuild buildMesh; - buildMeshInterface (*tri, buildMesh, buildBaseMesh, maxBaseBuild, node, time, nodeMap); + CMesh::CMeshBuild buildMesh; + buildMeshInterface (*tri, buildMesh, buildBaseMesh, maxBaseBuild, node, time, nodeMap); - /* Build a mesh. (duplicate UV/normals) - Use a CMeshMRM for an historic reason: simpler because don't use "matrix blocks". - */ - CMRMParameters mrmParams; - CMeshMRM meshMRM; - // To avoid heavy MRM compute, ask for only one lod (=> no poly reduction) - mrmParams.Divisor= 1; - mrmParams.NLods= 1; - meshMRM.build (buildBaseMesh, buildMesh, std::vector(), mrmParams); - const CMeshMRMGeom &meshMRMGeom= meshMRM.getMeshGeom(); - nlassert(meshMRMGeom.getNbLod()==1); + /* Build a mesh. (duplicate UV/normals) + Use a CMeshMRM for an historic reason: simpler because don't use "matrix blocks". + */ + CMRMParameters mrmParams; + CMeshMRM meshMRM; + // To avoid heavy MRM compute, ask for only one lod (=> no poly reduction) + mrmParams.Divisor= 1; + mrmParams.NLods= 1; + meshMRM.build (buildBaseMesh, buildMesh, std::vector(), mrmParams); + const CMeshMRMGeom &meshMRMGeom= meshMRM.getMeshGeom(); + nlassert(meshMRMGeom.getNbLod()==1); - // Build the lodBuild with the mesh - const CVertexBuffer &VB= meshMRMGeom.getVertexBuffer(); - uint32 format= VB.getVertexFormat(); - uint numVerts= VB.getNumVertices(); + // Build the lodBuild with the mesh + const CVertexBuffer &VB= meshMRMGeom.getVertexBuffer(); + uint32 format= VB.getVertexFormat(); + uint numVerts= VB.getNumVertices(); - // The mesh must have at least skinning. - if( (format & CVertexBuffer::PositionFlag) && meshMRMGeom.isSkinned() ) - { - uint i; - CVertexBufferRead vba; - VB.lock (vba); - - // build vertices and skinWeights - lodBuild.Vertices.resize(numVerts); - for(i=0;i triangleSelection; - lodBuild.TriangleIndices.resize(buildMesh.Faces.size() * 3); - triangleSelection.resize(buildMesh.Faces.size(), false); - uint dstTriIdx= 0; - for(i=0;i0;--n) - *(dst++)=*(src++); + for(i=0;i triangleSelection; + lodBuild.TriangleIndices.resize(buildMesh.Faces.size() * 3); + triangleSelection.resize(buildMesh.Faces.size(), false); + uint dstTriIdx= 0; + for(i=0;i0;--n) + *(dst++)=*(src++); + } + // if the material of this pass is the 0th material, flag tris for TextureInfo selection + if(meshMRMGeom.getRdrPassMaterial(0,i)==0) + { + for(uint tri= dstTriIdx/3; triDeleteMe(); + // Delete the triObject if we should... + if (deleteIt) + tri->MaybeAutoDelete(); + } } } diff --git a/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_material.cpp b/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_material.cpp index 5d67684cb..640cf8a19 100644 --- a/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_material.cpp +++ b/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_material.cpp @@ -1294,6 +1294,7 @@ ITexture* CExportNel::buildATexture (Texmap& texmap, CMaterialDesc &remap3dsTexC // Ok, good texture pTexture=pTextureCube; delete srcTex; + srcTex = NULL; } else { diff --git a/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_mesh.cpp b/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_mesh.cpp index afa742b61..aad5ee1b9 100644 --- a/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_mesh.cpp +++ b/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_mesh.cpp @@ -68,7 +68,8 @@ CMesh::CMeshBuild* CExportNel::createMeshBuild(INode& node, TimeValue tvTime, CM baseBuild = new CMeshBase::CMeshBaseBuild(); // Get a pointer on the object's node - Object *obj = node.EvalWorldState(tvTime).obj; + ObjectState os = node.EvalWorldState(tvTime); + Object *obj = os.obj; // Check if there is an object if (obj) @@ -79,35 +80,39 @@ CMesh::CMeshBuild* CExportNel::createMeshBuild(INode& node, TimeValue tvTime, CM { // Get a triobject from the node TriObject *tri = (TriObject*)obj->ConvertToType(tvTime, Class_ID(TRIOBJ_CLASS_ID, 0)); + if (tri) + { - // Note that the TriObject should only be deleted - // if the pointer to it is not equal to the object - // pointer that called ConvertToType() - bool deleteIt=false; - if (obj != tri) - deleteIt = true; + // Note that the TriObject should only be deleted + // if the pointer to it is not equal to the object + // pointer that called ConvertToType() + bool deleteIt=false; + if (obj != tri) + deleteIt = true; - // Description of materials - CMaxMeshBaseBuild maxBaseBuild; + // Description of materials + CMaxMeshBaseBuild maxBaseBuild; - // Fill the build interface of CMesh + // Fill the build interface of CMesh - // Reset the material array of the buildMesh because it will be rebuild by the exporter - baseBuild->Materials.clear(); + // Reset the material array of the buildMesh because it will be rebuild by the exporter + baseBuild->Materials.clear(); - // Get the node matrix - Matrix3 nodeMatrixMax; - CMatrix nodeMatrix; - getLocalMatrix (nodeMatrixMax, node, tvTime); - convertMatrix (nodeMatrix, nodeMatrixMax); + // Get the node matrix + Matrix3 nodeMatrixMax; + CMatrix nodeMatrix; + getLocalMatrix (nodeMatrixMax, node, tvTime); + convertMatrix (nodeMatrix, nodeMatrixMax); - buildBaseMeshInterface (*baseBuild, maxBaseBuild, node, tvTime, nodeMatrix); - buildMeshInterface (*tri, *pMeshBuild, *baseBuild, maxBaseBuild, node, tvTime, NULL, CMatrix::Identity, masterNodeMat, isMorphTarget); - + buildBaseMeshInterface (*baseBuild, maxBaseBuild, node, tvTime, nodeMatrix); + buildMeshInterface (*tri, *pMeshBuild, *baseBuild, maxBaseBuild, node, tvTime, NULL, CMatrix::Identity, masterNodeMat, isMorphTarget); + - // Delete the triObject if we should... - if (deleteIt) - tri->DeleteMe(); + // Delete the triObject if we should... + if (deleteIt) + tri->MaybeAutoDelete(); + tri = NULL; + } } } @@ -126,7 +131,7 @@ static void copyMultiLodMeshBaseLod0Infos(CMeshBase::CMeshBaseBuild &dst, const // *************************************************************************** // Export a mesh -IShape* CExportNel::buildShape (INode& node, TimeValue time, const TInodePtrInt *nodeMap, bool buildLods) +NLMISC::CSmartPtr CExportNel::buildShape (INode& node, TimeValue time, const TInodePtrInt *nodeMap, bool buildLods) { // Is this a multi lod object ? @@ -134,14 +139,15 @@ IShape* CExportNel::buildShape (INode& node, TimeValue time, const TInodePtrInt // Here, we must check what kind of node we can build with this mesh. // For the time, just Triobj is supported. - IShape *retShape=NULL; + CSmartPtr retShape = NULL; // If skinning, disable skin modifier if (nodeMap) enableSkinModifier (node, false); // Get a pointer on the object's node - Object *obj = node.EvalWorldState(time).obj; + ObjectState os = node.EvalWorldState(time); + Object *obj = os.obj; // Check if there is an object if (obj) @@ -184,264 +190,269 @@ IShape* CExportNel::buildShape (INode& node, TimeValue time, const TInodePtrInt // Get a triobject from the node TriObject *tri = (TriObject *) obj->ConvertToType(time, Class_ID(TRIOBJ_CLASS_ID, 0)); - // Note that the TriObject should only be deleted - // if the pointer to it is not equal to the object - // pointer that called ConvertToType() - bool deleteIt=false; - if (obj != tri) - deleteIt = true; - - if (hasWaterMaterial(node, time)) // is this a water shape ? + if (tri) { - retShape = buildWaterShape(node, time); - } - else - { - // Mesh base ? - CMeshBase *meshBase; + // Note that the TriObject should only be deleted + // if the pointer to it is not equal to the object + // pointer that called ConvertToType() + bool deleteIt=false; + if (obj != tri) + deleteIt = true; - // Get the node matrix - Matrix3 nodeMatrixMax; - CMatrix nodeMatrix; - getLocalMatrix (nodeMatrixMax, node, time); - convertMatrix (nodeMatrix, nodeMatrixMax); - - // Is a multi lod object ? - uint lodCount=getScriptAppData (&node, NEL3D_APPDATA_LOD_NAME_COUNT, 0); - if (lodCount && buildLods) + if (hasWaterMaterial(node, time)) // is this a water shape ? { - // This is a multilod object - multiLodObject = true; + retShape = buildWaterShape(node, time); + } + else + { + // Mesh base ? + CSmartPtr meshBase = NULL; - // Listy of material names - std::vector listMaterialName; + // Get the node matrix + Matrix3 nodeMatrixMax; + CMatrix nodeMatrix; + getLocalMatrix (nodeMatrixMax, node, time); + convertMatrix (nodeMatrix, nodeMatrixMax); - // Make the root mesh - CMeshMultiLod::CMeshMultiLodBuild multiLodBuild; - multiLodBuild.LodMeshes.reserve (lodCount+1); - - // Resize to one - bool isTransparent; - bool isOpaque; - multiLodBuild.LodMeshes.resize (1); - multiLodBuild.LodMeshes[0].MeshGeom=buildMeshGeom (node, time, nodeMap, multiLodBuild.BaseMesh, - listMaterialName, isTransparent, isOpaque, nodeMatrix); - multiLodBuild.LodMeshes[0].DistMax=getScriptAppData (&node, NEL3D_APPDATA_LOD_DIST_MAX, NEL3D_APPDATA_LOD_DIST_MAX_DEFAULT); - multiLodBuild.LodMeshes[0].BlendLength=getScriptAppData (&node, NEL3D_APPDATA_LOD_BLEND_LENGTH, NEL3D_APPDATA_LOD_BLEND_LENGTH_DEFAULT); - multiLodBuild.LodMeshes[0].Flags=0; - if (getScriptAppData (&node, NEL3D_APPDATA_LOD_BLEND_IN, NEL3D_APPDATA_LOD_BLEND_IN_DEFAULT)) - multiLodBuild.LodMeshes[0].Flags|=CMeshMultiLod::CMeshMultiLodBuild::CBuildSlot::BlendIn; - if (getScriptAppData (&node, NEL3D_APPDATA_LOD_BLEND_OUT, NEL3D_APPDATA_LOD_BLEND_OUT_DEFAULT)) - multiLodBuild.LodMeshes[0].Flags|=CMeshMultiLod::CMeshMultiLodBuild::CBuildSlot::BlendOut; - if ((getScriptAppData (&node, NEL3D_APPDATA_LOD_COARSE_MESH, NEL3D_APPDATA_LOD_COARSE_MESH_DEFAULT)) && (!_View)) - multiLodBuild.LodMeshes[0].Flags|=CMeshMultiLod::CMeshMultiLodBuild::CBuildSlot::CoarseMesh; - if (isTransparent) - multiLodBuild.LodMeshes[0].Flags|=CMeshMultiLod::CMeshMultiLodBuild::CBuildSlot::IsTransparent; - if (isOpaque) - multiLodBuild.LodMeshes[0].Flags|=CMeshMultiLod::CMeshMultiLodBuild::CBuildSlot::IsOpaque; - multiLodBuild.StaticLod=getScriptAppData (&node, NEL3D_APPDATA_LOD_DYNAMIC_MESH, NEL3D_APPDATA_LOD_DYNAMIC_MESH_DEFAULT)==0; - - // Bacup scale, rot and pos, etc... - CMeshBase::CMeshBaseBuild bkupMeshBase; - copyMultiLodMeshBaseLod0Infos(bkupMeshBase, multiLodBuild.BaseMesh); - - // Build a world to local matrix - CMatrix worldToNodeMatrix; - - // Is first slot is skinned ? - INode *rootSkel=getSkeletonRootBone (node); - - // For all the other lods - for (uint lod=0; lodGetINodeByName(nodeName.c_str()); - if (lodNode) + // Listy of material names + std::vector listMaterialName; + + // Make the root mesh + CMeshMultiLod::CMeshMultiLodBuild multiLodBuild; + multiLodBuild.LodMeshes.reserve (lodCount+1); + + // Resize to one + bool isTransparent; + bool isOpaque; + multiLodBuild.LodMeshes.resize (1); + multiLodBuild.LodMeshes[0].MeshGeom=buildMeshGeom (node, time, nodeMap, multiLodBuild.BaseMesh, + listMaterialName, isTransparent, isOpaque, nodeMatrix); + multiLodBuild.LodMeshes[0].DistMax=getScriptAppData (&node, NEL3D_APPDATA_LOD_DIST_MAX, NEL3D_APPDATA_LOD_DIST_MAX_DEFAULT); + multiLodBuild.LodMeshes[0].BlendLength=getScriptAppData (&node, NEL3D_APPDATA_LOD_BLEND_LENGTH, NEL3D_APPDATA_LOD_BLEND_LENGTH_DEFAULT); + multiLodBuild.LodMeshes[0].Flags=0; + if (getScriptAppData (&node, NEL3D_APPDATA_LOD_BLEND_IN, NEL3D_APPDATA_LOD_BLEND_IN_DEFAULT)) + multiLodBuild.LodMeshes[0].Flags|=CMeshMultiLod::CMeshMultiLodBuild::CBuildSlot::BlendIn; + if (getScriptAppData (&node, NEL3D_APPDATA_LOD_BLEND_OUT, NEL3D_APPDATA_LOD_BLEND_OUT_DEFAULT)) + multiLodBuild.LodMeshes[0].Flags|=CMeshMultiLod::CMeshMultiLodBuild::CBuildSlot::BlendOut; + if ((getScriptAppData (&node, NEL3D_APPDATA_LOD_COARSE_MESH, NEL3D_APPDATA_LOD_COARSE_MESH_DEFAULT)) && (!_View)) + multiLodBuild.LodMeshes[0].Flags|=CMeshMultiLod::CMeshMultiLodBuild::CBuildSlot::CoarseMesh; + if (isTransparent) + multiLodBuild.LodMeshes[0].Flags|=CMeshMultiLod::CMeshMultiLodBuild::CBuildSlot::IsTransparent; + if (isOpaque) + multiLodBuild.LodMeshes[0].Flags|=CMeshMultiLod::CMeshMultiLodBuild::CBuildSlot::IsOpaque; + multiLodBuild.StaticLod=getScriptAppData (&node, NEL3D_APPDATA_LOD_DYNAMIC_MESH, NEL3D_APPDATA_LOD_DYNAMIC_MESH_DEFAULT)==0; + + // Bacup scale, rot and pos, etc... + CMeshBase::CMeshBaseBuild bkupMeshBase; + copyMultiLodMeshBaseLod0Infos(bkupMeshBase, multiLodBuild.BaseMesh); + + // Build a world to local matrix + CMatrix worldToNodeMatrix; + + // Is first slot is skinned ? + INode *rootSkel=getSkeletonRootBone (node); + + // For all the other lods + for (uint lod=0; lodGetNodeTM (time)); - - // Get the parent matrix - CMatrix parentMatrix; - if (rootSkel) + // Get the node + INode *lodNode=_Ip->GetINodeByName(nodeName.c_str()); + if (lodNode) { - // Yes.. - CMatrix tmp; - convertMatrix (tmp, rootSkel->GetNodeTM (time)); - parentMatrix=nodeTM; + // Index of the lod in the build structure + uint index=multiLodBuild.LodMeshes.size(); + + // Resize the build structure + multiLodBuild.LodMeshes.resize (index+1); + + // Get matrix node + CMatrix nodeTM; + convertMatrix (nodeTM, lodNode->GetNodeTM (time)); + + // Get the parent matrix + CMatrix parentMatrix; + if (rootSkel) + { + // Yes.. + CMatrix tmp; + convertMatrix (tmp, rootSkel->GetNodeTM (time)); + parentMatrix=nodeTM; + } + else + { + buildNeLMatrix (parentMatrix, bkupMeshBase.DefaultScale, bkupMeshBase.DefaultRotQuat, bkupMeshBase.DefaultPos); + } + + // Fill the structure + multiLodBuild.LodMeshes[index].MeshGeom=buildMeshGeom (*lodNode, time, nodeMap, multiLodBuild.BaseMesh, + listMaterialName, isTransparent, isOpaque, parentMatrix); + multiLodBuild.LodMeshes[index].DistMax=getScriptAppData (lodNode, NEL3D_APPDATA_LOD_DIST_MAX, NEL3D_APPDATA_LOD_DIST_MAX_DEFAULT); + multiLodBuild.LodMeshes[index].BlendLength=getScriptAppData (lodNode, NEL3D_APPDATA_LOD_BLEND_LENGTH, NEL3D_APPDATA_LOD_BLEND_LENGTH_DEFAULT); + multiLodBuild.LodMeshes[index].Flags=0; + if (getScriptAppData (lodNode, NEL3D_APPDATA_LOD_BLEND_IN, NEL3D_APPDATA_LOD_BLEND_IN_DEFAULT)) + multiLodBuild.LodMeshes[index].Flags|=CMeshMultiLod::CMeshMultiLodBuild::CBuildSlot::BlendIn; + if (getScriptAppData (lodNode, NEL3D_APPDATA_LOD_BLEND_OUT, NEL3D_APPDATA_LOD_BLEND_OUT_DEFAULT)) + multiLodBuild.LodMeshes[index].Flags|=CMeshMultiLod::CMeshMultiLodBuild::CBuildSlot::BlendOut; + if ((getScriptAppData (lodNode, NEL3D_APPDATA_LOD_COARSE_MESH, NEL3D_APPDATA_LOD_COARSE_MESH_DEFAULT)) && (!_View)) + multiLodBuild.LodMeshes[index].Flags|=CMeshMultiLod::CMeshMultiLodBuild::CBuildSlot::CoarseMesh; + if (isTransparent) + multiLodBuild.LodMeshes[index].Flags|=CMeshMultiLod::CMeshMultiLodBuild::CBuildSlot::IsTransparent; + if (isOpaque) + multiLodBuild.LodMeshes[index].Flags|=CMeshMultiLod::CMeshMultiLodBuild::CBuildSlot::IsOpaque; + } + } + + // Restaure default pos, scale and rot, etc... + copyMultiLodMeshBaseLod0Infos(multiLodBuild.BaseMesh, bkupMeshBase); + + + // Make a CMeshMultiLod mesh object + CMeshMultiLod *multiMesh = new CMeshMultiLod; + ++multiMesh->crefs; // hack + + // Build it + multiMesh->build(multiLodBuild); + + // Return this pointer + meshBase = multiMesh; + + // ** force material to be animatable + if (CExportNel::getScriptAppData (&node, NEL3D_APPDATA_EXPORT_ANIMATED_MATERIALS, 0) != 0) + { + /// todo hulud: check if material are animated before + for (uint i=0; isetAnimatedMaterial (i, listMaterialName[i]); + } + } + } + else + { + // Array of name for the material + CMaxMeshBaseBuild maxBaseBuild; + + // Fill the build interface of CMesh + CMeshBase::CMeshBaseBuild buildBaseMesh; + buildBaseMeshInterface (buildBaseMesh, maxBaseBuild, node, time, nodeMatrix); + + CMesh::CMeshBuild buildMesh; + buildMeshInterface (*tri, buildMesh, buildBaseMesh, maxBaseBuild, node, time, nodeMap); + + if( hasLightMap( node, time ) && _Options.bExportLighting ) + calculateLM(&buildMesh, &buildBaseMesh, node, time, maxBaseBuild.FirstMaterial, _Options.OutputLightmapLog); + + // optimized materials remap + std::vector materialRemap; + + // MRM mesh ? + if (getScriptAppData (&node, NEL3D_APPDATA_LOD_MRM, 0)) + { + // Build a MRM parameters block + CMRMParameters parameters; + buildMRMParameters (node, parameters); + + // Get the blend shapes that can be linked + std::vector bsList; + getBSMeshBuild (bsList, node, time, nodeMap!=NULL); + + // CMeshMRM or CMeshMRMSkinned ? + + /* + * Here, export plugin choose between CMeshMRM and CMeshMRMSkinned + */ + if (CMeshMRMSkinned::isCompatible(buildMesh) && bsList.empty()) + { + // Make a CMesh object + CMeshMRMSkinned* meshMRMSkinned=new CMeshMRMSkinned; + + // Build the mesh with the build interface + meshMRMSkinned->build (buildBaseMesh, buildMesh, parameters); + + // optimize number of material + meshMRMSkinned->optimizeMaterialUsage(materialRemap); + + // Return this pointer + meshBase=meshMRMSkinned; } else { - buildNeLMatrix (parentMatrix, bkupMeshBase.DefaultScale, bkupMeshBase.DefaultRotQuat, bkupMeshBase.DefaultPos); + // Make a CMesh object + CMeshMRM* meshMRM=new CMeshMRM; + + // Build the mesh with the build interface + meshMRM->build (buildBaseMesh, buildMesh, bsList, parameters); + + // optimize number of material + meshMRM->optimizeMaterialUsage(materialRemap); + + // Return this pointer + meshBase=meshMRM; } - - // Fill the structure - multiLodBuild.LodMeshes[index].MeshGeom=buildMeshGeom (*lodNode, time, nodeMap, multiLodBuild.BaseMesh, - listMaterialName, isTransparent, isOpaque, parentMatrix); - multiLodBuild.LodMeshes[index].DistMax=getScriptAppData (lodNode, NEL3D_APPDATA_LOD_DIST_MAX, NEL3D_APPDATA_LOD_DIST_MAX_DEFAULT); - multiLodBuild.LodMeshes[index].BlendLength=getScriptAppData (lodNode, NEL3D_APPDATA_LOD_BLEND_LENGTH, NEL3D_APPDATA_LOD_BLEND_LENGTH_DEFAULT); - multiLodBuild.LodMeshes[index].Flags=0; - if (getScriptAppData (lodNode, NEL3D_APPDATA_LOD_BLEND_IN, NEL3D_APPDATA_LOD_BLEND_IN_DEFAULT)) - multiLodBuild.LodMeshes[index].Flags|=CMeshMultiLod::CMeshMultiLodBuild::CBuildSlot::BlendIn; - if (getScriptAppData (lodNode, NEL3D_APPDATA_LOD_BLEND_OUT, NEL3D_APPDATA_LOD_BLEND_OUT_DEFAULT)) - multiLodBuild.LodMeshes[index].Flags|=CMeshMultiLod::CMeshMultiLodBuild::CBuildSlot::BlendOut; - if ((getScriptAppData (lodNode, NEL3D_APPDATA_LOD_COARSE_MESH, NEL3D_APPDATA_LOD_COARSE_MESH_DEFAULT)) && (!_View)) - multiLodBuild.LodMeshes[index].Flags|=CMeshMultiLod::CMeshMultiLodBuild::CBuildSlot::CoarseMesh; - if (isTransparent) - multiLodBuild.LodMeshes[index].Flags|=CMeshMultiLod::CMeshMultiLodBuild::CBuildSlot::IsTransparent; - if (isOpaque) - multiLodBuild.LodMeshes[index].Flags|=CMeshMultiLod::CMeshMultiLodBuild::CBuildSlot::IsOpaque; - } - } - - // Restaure default pos, scale and rot, etc... - copyMultiLodMeshBaseLod0Infos(multiLodBuild.BaseMesh, bkupMeshBase); - - - // Make a CMeshMultiLod mesh object - CMeshMultiLod* multiMesh=new CMeshMultiLod; - - // Build it - multiMesh->build (multiLodBuild); - - // Return this pointer - meshBase=multiMesh; - - // ** force material to be animatable - if (CExportNel::getScriptAppData (&node, NEL3D_APPDATA_EXPORT_ANIMATED_MATERIALS, 0) != 0) - { - /// todo hulud: check if material are animated before - for (uint i=0; isetAnimatedMaterial (i, listMaterialName[i]); - } - } - } - else - { - // Array of name for the material - CMaxMeshBaseBuild maxBaseBuild; - - // Fill the build interface of CMesh - CMeshBase::CMeshBaseBuild buildBaseMesh; - buildBaseMeshInterface (buildBaseMesh, maxBaseBuild, node, time, nodeMatrix); - - CMesh::CMeshBuild buildMesh; - buildMeshInterface (*tri, buildMesh, buildBaseMesh, maxBaseBuild, node, time, nodeMap); - - if( hasLightMap( node, time ) && _Options.bExportLighting ) - calculateLM(&buildMesh, &buildBaseMesh, node, time, maxBaseBuild.FirstMaterial, _Options.OutputLightmapLog); - - // optimized materials remap - std::vector materialRemap; - - // MRM mesh ? - if (getScriptAppData (&node, NEL3D_APPDATA_LOD_MRM, 0)) - { - // Build a MRM parameters block - CMRMParameters parameters; - buildMRMParameters (node, parameters); - - // Get the blend shapes that can be linked - std::vector bsList; - getBSMeshBuild (bsList, node, time, nodeMap!=NULL); - - // CMeshMRM or CMeshMRMSkinned ? - - /* - * Here, export plugin choose between CMeshMRM and CMeshMRMSkinned - */ - if (CMeshMRMSkinned::isCompatible(buildMesh) && bsList.empty()) - { - // Make a CMesh object - CMeshMRMSkinned* meshMRMSkinned=new CMeshMRMSkinned; - - // Build the mesh with the build interface - meshMRMSkinned->build (buildBaseMesh, buildMesh, parameters); - - // optimize number of material - meshMRMSkinned->optimizeMaterialUsage(materialRemap); - - // Return this pointer - meshBase=meshMRMSkinned; } else { // Make a CMesh object - CMeshMRM* meshMRM=new CMeshMRM; + CMesh* mesh=new CMesh; // Build the mesh with the build interface - meshMRM->build (buildBaseMesh, buildMesh, bsList, parameters); + mesh->build (buildBaseMesh, buildMesh); + + // Must be done after the build to update vertex links + // Pass to buildMeshMorph if the original mesh is skinned or not + buildMeshMorph (buildMesh, node, time, nodeMap!=NULL); + mesh->setBlendShapes (buildMesh.BlendShapes); // optimize number of material - meshMRM->optimizeMaterialUsage(materialRemap); + mesh->optimizeMaterialUsage(materialRemap); // Return this pointer - meshBase=meshMRM; + meshBase=mesh; + } + + // Animate materials (must do it after optimizeMaterialUsage()); + if (CExportNel::getScriptAppData (&node, NEL3D_APPDATA_EXPORT_ANIMATED_MATERIALS, 0) != 0) + { + for (uint i=0; i=0) + // animate it + meshBase->setAnimatedMaterial (dstMatId, matName); + } } } - else + + // check wether this mesh is auto-animated. Force to false if in view mode + if ( !_View && (CExportNel::getScriptAppData (&node, NEL3D_APPDATA_AUTOMATIC_ANIMATION, 0) != 0) ) { - // Make a CMesh object - CMesh* mesh=new CMesh; - - // Build the mesh with the build interface - mesh->build (buildBaseMesh, buildMesh); - - // Must be done after the build to update vertex links - // Pass to buildMeshMorph if the original mesh is skinned or not - buildMeshMorph (buildMesh, node, time, nodeMap!=NULL); - mesh->setBlendShapes (buildMesh.BlendShapes); - - // optimize number of material - mesh->optimizeMaterialUsage(materialRemap); - - // Return this pointer - meshBase=mesh; + // yes, it is + meshBase->setAutoAnim(true); } - // Animate materials (must do it after optimizeMaterialUsage()); - if (CExportNel::getScriptAppData (&node, NEL3D_APPDATA_EXPORT_ANIMATED_MATERIALS, 0) != 0) - { - for (uint i=0; i=0) - // animate it - meshBase->setAnimatedMaterial (dstMatId, matName); - } - } + // Return the mesh base + retShape = meshBase; } - // check wether this mesh is auto-animated. Force to false if in view mode - if ( !_View && (CExportNel::getScriptAppData (&node, NEL3D_APPDATA_AUTOMATIC_ANIMATION, 0) != 0) ) - { - // yes, it is - meshBase->setAutoAnim(true); - } - - // Return the mesh base - retShape=meshBase; + // Delete the triObject if we should... + if (deleteIt) + tri->MaybeAutoDelete(); + tri = NULL; } - - // Delete the triObject if we should... - if (deleteIt) - tri->DeleteMe(); } } @@ -450,7 +461,7 @@ IShape* CExportNel::buildShape (INode& node, TimeValue time, const TInodePtrInt enableSkinModifier (node, true); // Set the dist max for this shape - if (retShape && !multiLodObject && buildLods) + if (retShape.getPtr() && !multiLodObject && buildLods) { // Get the dist max for this node float distmax = getScriptAppData (&node, NEL3D_APPDATA_LOD_DIST_MAX, NEL3D_APPDATA_LOD_DIST_MAX_DEFAULT); @@ -1173,6 +1184,7 @@ void CExportNel::getBSMeshBuild (std::vector &bsList, INode CMeshBase::CMeshBaseBuild *dummyMBB = NULL; std::auto_ptr baseMB(createMeshBuild (node, time, dummyMBB, finalSpace)); delete dummyMBB; + dummyMBB = NULL; if (baseMB.get() == NULL) return; j = 0; @@ -1184,7 +1196,7 @@ void CExportNel::getBSMeshBuild (std::vector &bsList, INode ++j; } - bsList.resize (j); + bsList.resize(j, NULL); j = 0; for (i = 0; i < 100; ++i) @@ -1198,6 +1210,7 @@ void CExportNel::getBSMeshBuild (std::vector &bsList, INode // get the meshbuild of the morhp target bsList[j] = createMeshBuild (*pNode, time, pMBB, finalSpace, true); delete pMBB; + pMBB = NULL; // copy src normals from src mesh for vertices that are on interfaces CMesh::CMeshBuild *mb = bsList[j]; if (mb) @@ -1281,7 +1294,8 @@ IMeshGeom *CExportNel::buildMeshGeom (INode& node, TimeValue time, const TInodeP enableSkinModifier (node, false); // Get a pointer on the object's node - Object *obj = node.EvalWorldState(time).obj; + ObjectState os = node.EvalWorldState(time); + Object *obj = os.obj; // Check if there is an object if (obj) @@ -1291,104 +1305,111 @@ IMeshGeom *CExportNel::buildMeshGeom (INode& node, TimeValue time, const TInodeP { // Get a triobject from the node TriObject *tri = (TriObject *) obj->ConvertToType(time, Class_ID(TRIOBJ_CLASS_ID, 0)); - - // Note that the TriObject should only be deleted - // if the pointer to it is not equal to the object - // pointer that called ConvertToType() - bool deleteIt=false; - if (obj != tri) - deleteIt = true; - - // Coarse mesh ? - bool coarseMesh=(getScriptAppData (&node, NEL3D_APPDATA_LOD_COARSE_MESH, 0)!=0) && (!_View); - - // No skeleton shape - if (coarseMesh) - nodeMap=NULL; - - // Array of name for the material - CMaxMeshBaseBuild maxBaseBuild; - - // Append material to the base - buildBaseMeshInterface (buildBaseMesh, maxBaseBuild, node, time, parentMatrix); - - // Get the node matrix - Matrix3 nodeMatrixMax; - CMatrix nodeMatrix; - getLocalMatrix (nodeMatrixMax, node, time); - convertMatrix (nodeMatrix, nodeMatrixMax); - - // Get the node to parent matrix - CMatrix nodeToParentMatrix; - nodeToParentMatrix = parentMatrix.inverted () * nodeMatrix; - - // Fill the build interface of CMesh - CMesh::CMeshBuild buildMesh; - buildMeshInterface (*tri, buildMesh, buildBaseMesh, maxBaseBuild, node, time, nodeMap, nodeToParentMatrix); - - // Append material names - isTransparent=false; - isOpaque=false; - for (uint i=0; i bsList; - getBSMeshBuild (bsList, node, time, nodeMap!=NULL); - - // Build the mesh with the build interface - meshMRMGeom->build (buildMesh, bsList, buildBaseMesh.Materials.size(), parameters); - - // Return this pointer - meshGeom=meshMRMGeom; - - for (uint32 bsListIt = 0; bsListIt < bsList.size(); ++bsListIt) - delete bsList[bsListIt]; - } - else - { - // Make a CMesh object - CMeshGeom* mGeom=new CMeshGeom; + // Note that the TriObject should only be deleted + // if the pointer to it is not equal to the object + // pointer that called ConvertToType() + bool deleteIt = (obj != tri); // Coarse mesh ? + bool coarseMesh=(getScriptAppData (&node, NEL3D_APPDATA_LOD_COARSE_MESH, 0)!=0) && (!_View); + + // No skeleton shape if (coarseMesh) + nodeMap=NULL; + + // Array of name for the material + CMaxMeshBaseBuild maxBaseBuild; + + // Append material to the base + buildBaseMeshInterface (buildBaseMesh, maxBaseBuild, node, time, parentMatrix); + + // Get the node matrix + Matrix3 nodeMatrixMax; + CMatrix nodeMatrix; + getLocalMatrix (nodeMatrixMax, node, time); + convertMatrix (nodeMatrix, nodeMatrixMax); + + // Get the node to parent matrix + CMatrix nodeToParentMatrix; + nodeToParentMatrix = parentMatrix.inverted () * nodeMatrix; + + // Fill the build interface of CMesh + CMesh::CMeshBuild buildMesh; + buildMeshInterface (*tri, buildMesh, buildBaseMesh, maxBaseBuild, node, time, nodeMap, nodeToParentMatrix); + + // Append material names + isTransparent=false; + isOpaque=false; + for (uint i=0; ibuild (buildMesh, buildBaseMesh.Materials.size()); + if( hasLightMap( node, time ) && _Options.bExportLighting ) + calculateLM(&buildMesh, &buildBaseMesh, node, time, maxBaseBuild.FirstMaterial, _Options.OutputLightmapLog); - // Return this pointer - meshGeom=mGeom; + // MRM mesh ? + if (getScriptAppData (&node, NEL3D_APPDATA_LOD_MRM, 0) && (!coarseMesh) ) + { + // Build a MRM parameters block + CMRMParameters parameters; + buildMRMParameters (node, parameters); + + // Make a CMesh object + CMeshMRMGeom* meshMRMGeom=new CMeshMRMGeom; + + // Get the blend shapes but in mesh build form + std::vector bsList; + getBSMeshBuild (bsList, node, time, nodeMap!=NULL); + + // Build the mesh with the build interface + meshMRMGeom->build (buildMesh, bsList, buildBaseMesh.Materials.size(), parameters); + + // Return this pointer + meshGeom=meshMRMGeom; + + #ifdef NL_DONT_FIND_MAX_CRASH + for (uint32 bsListIt = 0; bsListIt < bsList.size(); ++bsListIt) + { + delete bsList[bsListIt]; + bsList[bsListIt] = NULL; + } + #endif + } + else + { + // Make a CMesh object + CMeshGeom* mGeom=new CMeshGeom; + + // Coarse mesh ? + if (coarseMesh) + { + // Force vertex format + buildMesh.VertexFlags=NL3D_COARSEMESH_VERTEX_FORMAT_EXPORT; + } + + // Build the mesh with the build interface + mGeom->build(buildMesh, buildBaseMesh.Materials.size()); + + // Return this pointer + meshGeom=mGeom; + } + + // Delete the triObject if we should... + if (deleteIt) + tri->MaybeAutoDelete(); + tri = NULL; } - - // Delete the triObject if we should... - if (deleteIt) - tri->DeleteMe(); } } @@ -1397,7 +1418,7 @@ IMeshGeom *CExportNel::buildMeshGeom (INode& node, TimeValue time, const TInodeP enableSkinModifier (node, true); if (InfoLog) - InfoLog->display("buidlMeshGeom : %d ms\n", timeGetTime()-t); + InfoLog->display("buildMeshGeom : %d ms\n", timeGetTime()-t); if (InfoLog) InfoLog->display("End of %s \n", node.GetName()); @@ -1657,10 +1678,15 @@ NL3D::IShape *CExportNel::buildWaterShape(INode& node, TimeValue time) // Get a pointer on the object's node - Object *obj = node.EvalWorldState(time).obj; + ObjectState os = node.EvalWorldState(time); + Object *obj = os.obj; + + if (!obj) return NULL; // Get a triobject from the node - TriObject *tri = (TriObject *) obj->ConvertToType(0, Class_ID(TRIOBJ_CLASS_ID, 0)); + TriObject *tri = (TriObject *) obj->ConvertToType(time, Class_ID(TRIOBJ_CLASS_ID, 0)); + + if (!tri) return NULL; // Note that the TriObject should only be deleted // if the pointer to it is not equal to the object @@ -2033,7 +2059,8 @@ NL3D::IShape *CExportNel::buildWaterShape(INode& node, TimeValue time) // Delete the triObject if we should... if (deleteIt) - tri->DeleteMe(); + tri->MaybeAutoDelete(); + tri = NULL; nlinfo("WaterShape : build succesful"); return ws; } @@ -2047,11 +2074,13 @@ NL3D::IShape *CExportNel::buildWaterShape(INode& node, TimeValue time) // *************************************************************************** bool CExportNel::buildMeshAABBox(INode &node, NLMISC::CAABBox &dest, TimeValue time) { - Object *obj = node.EvalWorldState(time).obj; + ObjectState os = node.EvalWorldState(time); + Object *obj = os.obj; if (!obj) return false; if (!obj->CanConvertToType(Class_ID(TRIOBJ_CLASS_ID, 0))) return false; // Get a triobject from the node TriObject *tri = (TriObject*)obj->ConvertToType(time, Class_ID(TRIOBJ_CLASS_ID, 0)); + if (!tri) return false; // Note that the TriObject should only be deleted // if the pointer to it is not equal to the object // pointer that called ConvertToType() @@ -2073,10 +2102,11 @@ bool CExportNel::buildMeshAABBox(INode &node, NLMISC::CAABBox &dest, TimeValue t // if (deleteIt) { -#ifndef NL_DEBUG - tri->DeleteMe(); +#ifdef NL_DONT_FIND_MAX_CRASH + tri->MaybeAutoDelete(); #endif // NL_DEBUG } + tri = NULL; return true; } diff --git a/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_mesh_interface.cpp b/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_mesh_interface.cpp index 4ec4f5ba3..e0b647da3 100644 --- a/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_mesh_interface.cpp +++ b/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_mesh_interface.cpp @@ -131,7 +131,8 @@ struct CMeshInterface bool CMeshInterface::buildFromMaxMesh(INode &node, TimeValue tvTime) { // Get a pointer on the object's node - Object *obj = node.EvalWorldState(tvTime).obj; + ObjectState os = node.EvalWorldState(tvTime); + Object *obj = os.obj; // Check if there is an object if (!obj) return false; @@ -140,6 +141,8 @@ bool CMeshInterface::buildFromMaxMesh(INode &node, TimeValue tvTime) { // Get a triobject from the node TriObject *tri = (TriObject*)obj->ConvertToType(tvTime, Class_ID(TRIOBJ_CLASS_ID, 0)); + + if (!tri) return false; // Note that the TriObject should only be deleted // if the pointer to it is not equal to the object @@ -177,9 +180,8 @@ bool CMeshInterface::buildFromMaxMesh(INode &node, TimeValue tvTime) } // if (deleteIt) - { - tri->DeleteMe(); - } + tri->MaybeAutoDelete(); + tri = NULL; return true; } return false; @@ -316,50 +318,53 @@ static void AddNodeToQuadGrid(const NLMISC::CAABBox &delimiter, TNodeFaceQG &des { nldebug((std::string("Adding ") + node.GetName() + std::string(" to mesh interface quad grid")).c_str()); // add this node tris - Object *obj = node.EvalWorldState(time).obj; + ObjectState os = node.EvalWorldState(time); + Object *obj = os.obj; if (obj) { if (obj->CanConvertToType(Class_ID(TRIOBJ_CLASS_ID, 0))) { // Get a triobject from the node TriObject *tri = (TriObject*)obj->ConvertToType(time, Class_ID(TRIOBJ_CLASS_ID, 0)); - // Note that the TriObject should only be deleted - // if the pointer to it is not equal to the object - // pointer that called ConvertToType() - bool deleteIt = false; - if (obj != tri) - deleteIt = true; - Mesh &mesh = tri->GetMesh(); - - Matrix3 nodeMat = node.GetObjectTM(time); - CNodeFace nodeFace; - - NLMISC::CAABBox faceBBox; - - uint numFaceAdded = 0; - for(sint l = 0; l < mesh.getNumFaces(); ++l) + if (tri) { - for(uint m = 0; m < 3; ++m) + // Note that the TriObject should only be deleted + // if the pointer to it is not equal to the object + // pointer that called ConvertToType() + bool deleteIt = false; + if (obj != tri) + deleteIt = true; + Mesh &mesh = tri->GetMesh(); + + Matrix3 nodeMat = node.GetObjectTM(time); + CNodeFace nodeFace; + + NLMISC::CAABBox faceBBox; + + uint numFaceAdded = 0; + for(sint l = 0; l < mesh.getNumFaces(); ++l) { - Point3 pos = nodeMat * mesh.getVert(mesh.faces[l].v[m]); - CExportNel::convertVector(nodeFace.P[m], pos); - } - // test if we must insert in quadgrid - nodeFace.buildBBox(faceBBox); - if (faceBBox.intersect(delimiter)) - { - nodeFace.SmoothGroup = mesh.faces[l].smGroup; - destQuadGrid.insert(faceBBox.getMin(), faceBBox.getMax(), nodeFace); - ++ numFaceAdded; - } - - } - nldebug("%d faces where added", numFaceAdded); - // - if (deleteIt) - { - tri->DeleteMe(); - } + for(uint m = 0; m < 3; ++m) + { + Point3 pos = nodeMat * mesh.getVert(mesh.faces[l].v[m]); + CExportNel::convertVector(nodeFace.P[m], pos); + } + // test if we must insert in quadgrid + nodeFace.buildBBox(faceBBox); + if (faceBBox.intersect(delimiter)) + { + nodeFace.SmoothGroup = mesh.faces[l].smGroup; + destQuadGrid.insert(faceBBox.getMin(), faceBBox.getMax(), nodeFace); + ++ numFaceAdded; + } + + } + nldebug("%d faces where added", numFaceAdded); + // + if (deleteIt) + tri->MaybeAutoDelete(); + tri = NULL; + } } } } @@ -478,16 +483,20 @@ static void ApplyMeshInterfacesUsingSceneNormals(INode &sceneBaseNode, std::vect */ static bool SelectVerticesInMeshFromInterfaces(const std::vector &inters, float threshold, INode &node, TimeValue tvTime) { - Object *obj = node.EvalWorldState(tvTime).obj; + ObjectState os = node.EvalWorldState(tvTime); + Object *obj = os.obj; // Check if there is an object + if (!obj) return false; if (obj->CanConvertToType(Class_ID(TRIOBJ_CLASS_ID, 0))) { // Get a triobject from the node - TriObject *tri = (TriObject*)obj->ConvertToType(tvTime, Class_ID(TRIOBJ_CLASS_ID, 0)); + TriObject *tri = (TriObject*)obj->ConvertToType(tvTime, Class_ID(TRIOBJ_CLASS_ID, 0)); + if (!tri) return false; if (obj != tri) { // not a mesh object, so do nothing - tri->DeleteMe(); + tri->MaybeAutoDelete(); + tri = NULL; return false; } diff --git a/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_misc.cpp b/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_misc.cpp index 0f2ebdc18..0b2426758 100644 --- a/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_misc.cpp +++ b/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_misc.cpp @@ -511,7 +511,8 @@ std::string CExportNel::getNelObjectName (INode& node) { // Workaround for FX (don't know why, but the AppData are not copied when FX are duplicated, so try to get the name in another way) // If this is a particle system, try to get the name of the shape.from the param blocks - Object *obj = node.EvalWorldState(0).obj; + ObjectState os = node.EvalWorldState(0); + Object *obj = os.obj; // Check if there is an object if (obj) { @@ -542,7 +543,8 @@ std::string CExportNel::getNelObjectName (INode& node) } else { - Object *obj = node.EvalWorldState(0).obj; + ObjectState os = node.EvalWorldState(0); + Object *obj = os.obj; if (obj) { ad = obj->GetAppDataChunk (MAXSCRIPT_UTILITY_CLASS_ID, UTILITY_CLASS_ID, NEL3D_APPDATA_INSTANCE_SHAPE); @@ -906,7 +908,8 @@ void CExportNel::getObjectNodes (std::vector& vectNode, TimeValue time, node=_Ip->GetRootNode(); // Get a pointer on the object's node - Object *obj = node->EvalWorldState(time).obj; + ObjectState os = node->EvalWorldState(time); + Object *obj = os.obj; // Check if there is an object if (obj) @@ -1257,7 +1260,8 @@ void CExportNel::buildCamera(NL3D::CCameraInfo &cameraInfo, INode& node, TimeVal cameraInfo.Fov = genCamera->GetFOV(time); if (deleteIt) - genCamera->DeleteMe(); + genCamera->MaybeAutoDelete(); + genCamera = NULL; } } } diff --git a/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_nel.h b/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_nel.h index 81fbac682..d413e1109 100644 --- a/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_nel.h +++ b/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_nel.h @@ -292,7 +292,7 @@ public: * * skeletonShape must be NULL if no bones. */ - NL3D::IShape* buildShape (INode& node, TimeValue time, const TInodePtrInt *nodeMap, + NLMISC::CSmartPtr buildShape (INode& node, TimeValue time, const TInodePtrInt *nodeMap, bool buildLods); /** diff --git a/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_particle_system.cpp b/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_particle_system.cpp index 4d10a5508..4c6b6bc8b 100644 --- a/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_particle_system.cpp +++ b/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_particle_system.cpp @@ -26,7 +26,8 @@ using namespace NL3D; IShape* CExportNel::buildParticleSystem(INode& node, TimeValue time) { - Object *obj = node.EvalWorldState(time).obj; + ObjectState os = node.EvalWorldState(time); + Object *obj = os.obj; nlassert(obj); std::string shapeName; // try to get the complete path diff --git a/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_scene.cpp b/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_scene.cpp index 8395d11ce..4e7edea8a 100644 --- a/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_scene.cpp +++ b/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_scene.cpp @@ -249,8 +249,8 @@ CInstanceGroup* CExportNel::buildInstanceGroup(const vector& vectNode, v clusterTemp.Name = pNode->GetName(); vClusters.push_back (clusterTemp); - delete pMB; - delete pMBB; + delete pMB; pMB = NULL; + delete pMBB; pMBB = NULL; } } @@ -376,7 +376,9 @@ CInstanceGroup* CExportNel::buildInstanceGroup(const vector& vectNode, v vPortals.push_back (portalTemp); delete pMB; + pMB = NULL; delete pMBB; + pMBB = NULL; } } @@ -406,7 +408,8 @@ CInstanceGroup* CExportNel::buildInstanceGroup(const vector& vectNode, v * If it is a FX, we read its bbox from its shape * If we can't read it, we use the bbox of the fx helper in max */ - Object *obj = pNode->EvalWorldState(tvTime).obj; + ObjectState os = pNode->EvalWorldState(tvTime); + Object *obj = os.obj; // Check if there is an object if (obj) { @@ -452,6 +455,7 @@ CInstanceGroup* CExportNel::buildInstanceGroup(const vector& vectNode, v buildMeshBBox = false; } delete ss.getShapePointer(); + ss.setShapePointer(NULL); } catch (NLMISC::Exception &e) { @@ -506,8 +510,8 @@ CInstanceGroup* CExportNel::buildInstanceGroup(const vector& vectNode, v } // debug purpose : to remove - delete pMB; - delete pMBB; + delete pMB; pMB = NULL; + delete pMBB; pMBB = NULL; } ++nNumIG; @@ -911,7 +915,7 @@ void CExportNel::buildScene (NL3D::CScene &scene, NL3D::CShapeBank &shapeBank, I // Swap pointer and release unlighted one. swap(ig, igOut); - delete igOut; + delete igOut; igOut = NULL; } // Add all models to the scene diff --git a/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_skinning.cpp b/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_skinning.cpp index c48b840c7..c1809508f 100644 --- a/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_skinning.cpp +++ b/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_skinning.cpp @@ -1386,7 +1386,8 @@ bool CExportNel::mirrorPhysiqueSelection(INode &node, TimeValue tvTime, const st uint vertCount; // Get a pointer on the object's node. - Object *obj = node.EvalWorldState(tvTime).obj; + ObjectState os = node.EvalWorldState(tvTime); + Object *obj = os.obj; // Check if there is an object ok= false; @@ -1398,35 +1399,39 @@ bool CExportNel::mirrorPhysiqueSelection(INode &node, TimeValue tvTime, const st { // Get a triobject from the node TriObject *tri = (TriObject*)obj->ConvertToType(tvTime, Class_ID(TRIOBJ_CLASS_ID, 0)); - - // Note that the TriObject should only be deleted - // if the pointer to it is not equal to the object - // pointer that called ConvertToType() - bool deleteIt=false; - if (obj != tri) - deleteIt = true; - - // Get the node matrix. TODO: Matrix headhache? - /*Matrix3 nodeMatrixMax; - CMatrix nodeMatrix; - getLocalMatrix (nodeMatrixMax, node, tvTime); - convertMatrix (nodeMatrix, nodeMatrixMax);*/ - - // retrive Position geometry - vertCount= tri->NumPoints(); - tempVertex.resize(vertCount); - for(uint i=0;iGetPoint(i); - tempVertex[i].Pos.set(v.x, v.y, v.z); + // Note that the TriObject should only be deleted + // if the pointer to it is not equal to the object + // pointer that called ConvertToType() + bool deleteIt=false; + if (obj != tri) + deleteIt = true; + + // Get the node matrix. TODO: Matrix headhache? + /*Matrix3 nodeMatrixMax; + CMatrix nodeMatrix; + getLocalMatrix (nodeMatrixMax, node, tvTime); + convertMatrix (nodeMatrix, nodeMatrixMax);*/ + + // retrive Position geometry + vertCount= tri->NumPoints(); + tempVertex.resize(vertCount); + for(uint i=0;iGetPoint(i); + tempVertex[i].Pos.set(v.x, v.y, v.z); + } + + // Delete the triObject if we should... + if (deleteIt) + tri->MaybeAutoDelete(); + tri = NULL; + + // ok! + ok= true; } - - // Delete the triObject if we should... - if (deleteIt) - tri->DeleteMe(); - - // ok! - ok= true; } } if(!ok) diff --git a/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_vegetable.cpp b/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_vegetable.cpp index 6c054404a..6e10f9c78 100644 --- a/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_vegetable.cpp +++ b/code/nel/tools/3d/plugin_max/nel_mesh_lib/export_vegetable.cpp @@ -33,7 +33,8 @@ bool CExportNel::buildVegetableShape (NL3D::CVegetableShape& skeletonShape, INo bool res = false; // Get a pointer on the object's node - Object *obj = node.EvalWorldState(time).obj; + ObjectState os = node.EvalWorldState(time); + Object *obj = os.obj; // Check if there is an object if (obj) @@ -42,116 +43,119 @@ bool CExportNel::buildVegetableShape (NL3D::CVegetableShape& skeletonShape, INo { // Get a triobject from the node TriObject *tri = (TriObject *) obj->ConvertToType(time, Class_ID(TRIOBJ_CLASS_ID, 0)); - - // Note that the TriObject should only be deleted - // if the pointer to it is not equal to the object - // pointer that called ConvertToType() - bool deleteIt=false; - if (obj != tri) - deleteIt = true; - - // Build a mesh base structure - CMeshBase::CMeshBaseBuild buildBaseMesh; - CMaxMeshBaseBuild maxBaseBuild; - - // Get the node matrix - Matrix3 nodeMatrixMax; - CMatrix nodeMatrix; - getLocalMatrix (nodeMatrixMax, node, time); - convertMatrix (nodeMatrix, nodeMatrixMax); - - buildBaseMeshInterface (buildBaseMesh, maxBaseBuild, node, time, nodeMatrix); - - // Build a mesh - CMesh::CMeshBuild buildMesh; - buildMeshInterface (*tri, buildMesh, buildBaseMesh, maxBaseBuild, node, time, NULL); - - // Has UV 1 - if ((buildMesh.VertexFlags & CVertexBuffer::TexCoord0Flag) == 0) - { - // Error - outputErrorMessage ("Can't build vegetable mesh: need UV1 coordinates"); - } - else + + if (tri) { + // Note that the TriObject should only be deleted + // if the pointer to it is not equal to the object + // pointer that called ConvertToType() + bool deleteIt=false; + if (obj != tri) + deleteIt = true; + + // Build a mesh base structure + CMeshBase::CMeshBaseBuild buildBaseMesh; + CMaxMeshBaseBuild maxBaseBuild; + + // Get the node matrix + Matrix3 nodeMatrixMax; + CMatrix nodeMatrix; + getLocalMatrix (nodeMatrixMax, node, time); + convertMatrix (nodeMatrix, nodeMatrixMax); + + buildBaseMeshInterface (buildBaseMesh, maxBaseBuild, node, time, nodeMatrix); + // Build a mesh - CMesh mesh; - mesh.build (buildBaseMesh, buildMesh); + CMesh::CMeshBuild buildMesh; + buildMeshInterface (*tri, buildMesh, buildBaseMesh, maxBaseBuild, node, time, NULL); - // Number of matrix block - if (mesh.getNbMatrixBlock () != 1) + // Has UV 1 + if ((buildMesh.VertexFlags & CVertexBuffer::TexCoord0Flag) == 0) { // Error - outputErrorMessage ("The object can't be skinned"); + outputErrorMessage ("Can't build vegetable mesh: need UV1 coordinates"); } else { - // Number of render pass - if (mesh.getNbRdrPass (0) != 1) + // Build a mesh + CMesh mesh; + mesh.build (buildBaseMesh, buildMesh); + + // Number of matrix block + if (mesh.getNbMatrixBlock () != 1) { // Error - outputErrorMessage ("The object must have less than one material!"); + outputErrorMessage ("The object can't be skinned"); } else { - // Build a vegetable mesh - CVegetableShapeBuild vegetableBuild; - - // Copy the vertex buffer - vegetableBuild.VB = mesh.getVertexBuffer (); - - // Copy the primitive block - vegetableBuild.PB = mesh.getRdrPassPrimitiveBlock (0, 0); - - // Get the appdata - vegetableBuild.AlphaBlend = CExportNel::getScriptAppData (&node, NEL3D_APPDATA_VEGETABLE_ALPHA_BLEND, 0) == 0; - - // Alpha blend ? - if (vegetableBuild.AlphaBlend) + // Number of render pass + if (mesh.getNbRdrPass (0) != 1) { - // Default options - vegetableBuild.PreComputeLighting = true; - vegetableBuild.DoubleSided = true; - - // Lighted ? - vegetableBuild.Lighted = CExportNel::getScriptAppData (&node, NEL3D_APPDATA_VEGETABLE_ALPHA_BLEND_ON_LIGHTED, 0) == 0; + // Error + outputErrorMessage ("The object must have less than one material!"); } else { - // Lighted ? - vegetableBuild.Lighted = CExportNel::getScriptAppData (&node, NEL3D_APPDATA_VEGETABLE_ALPHA_BLEND_OFF_LIGHTED, 0) != 2; + // Build a vegetable mesh + CVegetableShapeBuild vegetableBuild; - // Precompute light ? - vegetableBuild.PreComputeLighting = CExportNel::getScriptAppData (&node, NEL3D_APPDATA_VEGETABLE_ALPHA_BLEND_OFF_LIGHTED, 0) == 0; + // Copy the vertex buffer + vegetableBuild.VB = mesh.getVertexBuffer (); - // Double sided ? - vegetableBuild.DoubleSided = CExportNel::getScriptAppData (&node, NEL3D_APPDATA_VEGETABLE_ALPHA_BLEND_OFF_DOUBLE_SIDED, 0) != BST_UNCHECKED; + // Copy the primitive block + vegetableBuild.PB = mesh.getRdrPassPrimitiveBlock (0, 0); + + // Get the appdata + vegetableBuild.AlphaBlend = CExportNel::getScriptAppData (&node, NEL3D_APPDATA_VEGETABLE_ALPHA_BLEND, 0) == 0; + + // Alpha blend ? + if (vegetableBuild.AlphaBlend) + { + // Default options + vegetableBuild.PreComputeLighting = true; + vegetableBuild.DoubleSided = true; + + // Lighted ? + vegetableBuild.Lighted = CExportNel::getScriptAppData (&node, NEL3D_APPDATA_VEGETABLE_ALPHA_BLEND_ON_LIGHTED, 0) == 0; + } + else + { + // Lighted ? + vegetableBuild.Lighted = CExportNel::getScriptAppData (&node, NEL3D_APPDATA_VEGETABLE_ALPHA_BLEND_OFF_LIGHTED, 0) != 2; + + // Precompute light ? + vegetableBuild.PreComputeLighting = CExportNel::getScriptAppData (&node, NEL3D_APPDATA_VEGETABLE_ALPHA_BLEND_OFF_LIGHTED, 0) == 0; + + // Double sided ? + vegetableBuild.DoubleSided = CExportNel::getScriptAppData (&node, NEL3D_APPDATA_VEGETABLE_ALPHA_BLEND_OFF_DOUBLE_SIDED, 0) != BST_UNCHECKED; + } + + // PreComputeLighting? + if (vegetableBuild.PreComputeLighting) + { + // BestSidedPreComputeLighting? + vegetableBuild.BestSidedPreComputeLighting= CExportNel::getScriptAppData (&node, NEL3D_APPDATA_VEGETABLE_FORCE_BEST_SIDED_LIGHTING, 0) != BST_UNCHECKED; + } + + // Max bend weight + vegetableBuild.MaxBendWeight = CExportNel::getScriptAppData (&node, NEL3D_APPDATA_BEND_FACTOR, NEL3D_APPDATA_BEND_FACTOR_DEFAULT); + + // BendMode + vegetableBuild.BendCenterMode = (CVegetableShapeBuild::TBendCenterMode)CExportNel::getScriptAppData (&node, NEL3D_APPDATA_BEND_CENTER, 0); + + // Build it + skeletonShape.build (vegetableBuild); + + // Ok + res = true; } - - // PreComputeLighting? - if (vegetableBuild.PreComputeLighting) - { - // BestSidedPreComputeLighting? - vegetableBuild.BestSidedPreComputeLighting= CExportNel::getScriptAppData (&node, NEL3D_APPDATA_VEGETABLE_FORCE_BEST_SIDED_LIGHTING, 0) != BST_UNCHECKED; - } - - // Max bend weight - vegetableBuild.MaxBendWeight = CExportNel::getScriptAppData (&node, NEL3D_APPDATA_BEND_FACTOR, NEL3D_APPDATA_BEND_FACTOR_DEFAULT); - - // BendMode - vegetableBuild.BendCenterMode = (CVegetableShapeBuild::TBendCenterMode)CExportNel::getScriptAppData (&node, NEL3D_APPDATA_BEND_CENTER, 0); - - // Build it - skeletonShape.build (vegetableBuild); - - // Ok - res = true; } } - } - if (deleteIt) - tri->DeleteMe(); + if (deleteIt) + tri->MaybeAutoDelete(); + } } } diff --git a/code/nel/tools/3d/plugin_max/scripts/nel_assets_png.ms b/code/nel/tools/3d/plugin_max/scripts/nel_assets_png.ms index 531c0f0b8..82d691d5f 100644 --- a/code/nel/tools/3d/plugin_max/scripts/nel_assets_png.ms +++ b/code/nel/tools/3d/plugin_max/scripts/nel_assets_png.ms @@ -101,3 +101,8 @@ for m in getClassInstances NelMaterial do m.delegate.ReflectionMap = undefined m.delegate.RefractionMap = undefined ) + +actionMan.executeAction 0 "40021" -- Selection: Select All +actionMan.executeAction 0 "311" -- Tools: Zoom Extents All Selected +actionMan.executeAction 0 "63508" -- Views: Standard Display with Maps +actionMan.executeAction 0 "40043" -- Selection: Select None diff --git a/code/nel/tools/3d/plugin_max/scripts/nel_assets_png_batched.ms b/code/nel/tools/3d/plugin_max/scripts/nel_assets_png_batched.ms index b6b5e0434..cdff0431c 100644 --- a/code/nel/tools/3d/plugin_max/scripts/nel_assets_png_batched.ms +++ b/code/nel/tools/3d/plugin_max/scripts/nel_assets_png_batched.ms @@ -169,9 +169,12 @@ rollout assets_png_rollout "Properties" m.delegate.ReflectionMap = undefined m.delegate.RefractionMap = undefined ) - actionMan.executeAction 0 "63508" -- Views: Standard Display with Maps + actionMan.executeAction 0 "40021" -- Selection: Select All actionMan.executeAction 0 "311" -- Tools: Zoom Extents All Selected + actionMan.executeAction 0 "63508" -- Views: Standard Display with Maps + actionMan.executeAction 0 "40043" -- Selection: Select None + return 1 ) diff --git a/code/nel/tools/3d/plugin_max/scripts/nel_assets_png_database.ms b/code/nel/tools/3d/plugin_max/scripts/nel_assets_png_database.ms index cd372322c..2d119e4e0 100644 --- a/code/nel/tools/3d/plugin_max/scripts/nel_assets_png_database.ms +++ b/code/nel/tools/3d/plugin_max/scripts/nel_assets_png_database.ms @@ -141,3 +141,8 @@ for m in getClassInstances NelMaterial do m.delegate.ReflectionMap = undefined m.delegate.RefractionMap = undefined ) + +actionMan.executeAction 0 "40021" -- Selection: Select All +actionMan.executeAction 0 "311" -- Tools: Zoom Extents All Selected +actionMan.executeAction 0 "63508" -- Views: Standard Display with Maps +actionMan.executeAction 0 "40043" -- Selection: Select None