MXS:运行我的'删除重复项'脚本

时间:2018-03-30 19:48:31

标签: crash duplicates 3dsmax maxscript

运行脚本时3ds max崩溃了。生成Windows错误消息框(通过“Windows问题报告”过程)。 Maxscript中没有产生错误(监听器在脚本运行时不显示任何错误)。在脚本运行时,CPU和RAM使用率处于可接受的水平。我的脚本在没有崩溃的情况下工作,并且在只有标准原始对象的较小场景(10-20个对象)上产生了所需的结果。错误/崩溃发生在包含4051多边形对象的较大场景上。 该脚本查看所有对象,查找相同的对象并删除除了一个相同的对象之外的所有对象,从而为您留下没有任何重复对象的场景。)

在包含4051个对象窗口的场景上运行脚本时,会给出一个错误消息框; “3ds max已停止工作 - 一个问题导致程序停止正常工作.Windows将关闭程序并在解决方案可用时通知您。” 在脚本运行时RAM和3ds max的CPU使用率仍然可以接受(根据任务管理员)(30-40%CPU(i5-6600k)和16GB内的3-4GB RAM)。

“Windows问题报告”错误消息框的图像: windows problem reporting error message box

流程在任务管理器中的显示方式enter image description here

脚本运行时期间3ds max的CPU / RAM使用率图像enter image description here

注意:出现错误消息框后3ds max的RAM / CPU / DISK使用率下降到接近零的值。在出现错误消息框之后,窗口除了关闭3ds max。

之外别无选择

我让脚本运行了很多次来检查错误消息是否在每次运行的同一个对象上发生,情况并非如此,错误消息发生在另一个对象上(当处理不同的对象时)通过脚本)每次我运行脚本。当脚本将场景中的第一个对象(“Mesh_000”)与场景中的另一个对象(网格数在“700”和“900”之间)进行比较时,脚本会崩溃。以下数组包含我执行的一些测试中脚本崩溃的网格索引:#(805,832,733,766,877)。该脚本在崩溃前运行10-20分钟。

导致错误的.max场景可以在这里找到: larger .max scene which causes error

脚本的工作原理如下(伪代码):

duplicate_objs = #()
meshes_array = Collect all meshes in scene
for mesh in meshes_array do(
    Compare mesh to all other meshes in meshes_array
    if an identical mesh is found do(append duplicate_objs identical_mesh)
)
--Delete all the duplicate meshes:
delete duplicate_objs    

我的脚本代码:     fn fn_construct_objs_array x =(         清空选项()         选择几何         取消选择助手         objs =选择为数组         checked_objs_list =#()         items_to_delete_from_objs =#()         )

fn fn_delete_duplicates equal_pos_boolean =(      - 打印“删除重复”         obj_dups =#()

    ConvertTo objs[1] Editable_Poly
    PolyCount_src = polyop.getNumFaces objs[1]
    TriCount_src = (objs[1].mesh.numFaces)
    VertCount_src = (getnumverts objs[1])    
    Position_src = objs[1].pos

    for i in 1 to objs.count do(
        if i <= objs.count and objs[i] != objs[1] do(
            format "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n--> Comp. original obj (%) to comparison-obj(%) \n" objs[1] objs[i]
            ConvertTo objs[i] Editable_Poly
            PolyCount = polyop.getNumFaces objs[i]
            Tricount = (objs[i].mesh.numFaces)
            Position = objs[i].pos
            VertCount = (getnumverts objs[i])

            if(Tricount == Tricount_src and PolyCount == PolyCount_src and VertCount == VertCount_src and ( if equal_pos_boolean then( Position == Position_src)else(true) )) do(
                if((finditem checked_objs_list (objs[i]) == 0) ) do(
                    appendifunique obj_dups objs[i]; --print "||||||||||||||||||||| FOUND DUPLICATE OBJECT |||||||||||||||||||||| \n"
                    appendifunique checked_objs_list objs[i]
                    append items_to_delete_from_objs objs[i]
                    )-- end if(finditem checked_objs_array objs[i] == 0 ) do(
                )-- end if(Tricount == Tricount_src and PolyCount == PolyCount_src and VertCount == VertCount_src and ( if equal_pos_boolean then( Position == Position_src)else(true) )) do(

            )-- end if i <= objs.count(
    )
    for item in items_to_delete_from_objs do(
        deleteitem objs (finditem objs item)
        )
    items_to_delete_from_objs = #()
    deleteitem objs 1
for duplicate in obj_dups do(delete duplicate)

if objs.count > 0 do (
    --format "objs left to process = % \n" objs.count ; 
    fn_delete_duplicates equal_pos_boolean
    )--end if objs.count > 0 do(
)--end fn_delete_duplicates

fn_construct_objs_array 1
fn_delete_duplicates true

注意:网格相同(在此上下文中)定义为具有相同多边形,vertcount,edgecount,position的网格。

3 个答案:

答案 0 :(得分:1)

从粗略的看,我警告不要使用objs[i].mesh.numFaces,因为它在内存中创建了新的网格实例而你没有调用dispose来删除它 - 如果你选择这样做并比较polycount和tricount,肯定会进行转换并首先在循环外收集网格(最好也使用snapshotAsMes)。此外,您可能希望使用getPolygonCount <node>,它为您提供节点多边形计数(如果堆栈的结果是多对象)和顶点计数。

答案 1 :(得分:1)

我擅长调试别人的代码,所以再一次只是快速浏览一下 - 我绝对避免在for duplicate in obj_dups do(delete duplicate)中进行循环,delete是一个映射函数,你可以传递一个集合作为一个论点。这样,将不会有这么多场景资源管理器更新,它应该更快。我也更喜欢迭代而不是递归。总而言之,这就是我写它的方式:

struct objInfo
(
    obj, polyCount, vertCount, pos,

    fn isSamePos pos1 pos2 eps:1e-6 =
    (
        local diff = pos2 - pos1
        dot diff diff < eps
    ),

    fn isEqual info checkPos:off =
    (
        this.vertCount == info.vertCount and
        this.polyCount == info.polyCount and
        (not checkPos or isSamePos this.pos info.pos)
    ),

    on create do
    (
        local polyVertCount = getPolygonCount obj
        polyCount = polyVertCount[1]
        vertCount = polyVertCount[2]
        pos = obj.pos
    )
)

fn collectDuplicates checkPos:off =
(
    items = for obj in geometry collect objInfo obj:obj
    itemCount = items.count
    collected = #{}
    duplicates = #()

    for item = 1 to itemCount where not collected[item] do
    (
        local current = items[item]

        for nextItem = item + 1 to itemCount
            where not collected[nextItem] and
            (
                local next = items[nextItem]
                next.isEqual current checkPos:checkPos
            )
            do
            (
                append duplicates next.obj
                append collected nextItem
            )
    )

    return duplicates
)

delete (collectDuplicates checkPos:off)

答案 2 :(得分:0)

我使用Swordslayer的建议编辑了我的代码;网格信息的集合现在发生在循环之外,我使用getpolygonCount来获取poly和vertcount。

我原始问题中提到的包含4051标准原始对象的场景不再导致崩溃(并且明显更快),但是包含导入对象的另一个场景现在导致“堆栈溢出错误”。在3ds max里面...奇怪的是这个错误只发生在我启动3ds max后第一次运行脚本时。在堆栈溢出错误发生后第二次(或第三次等)时间运行脚本时,脚本执行时没有任何错误(大约需要10-20秒才能完成)并且脚本按原样运行(如删除时)重复的对象)。每次在刚启动3ds max后在原始场景上运行脚本时都会发生堆栈溢出错误。

另一件奇怪的事(对我来说)是即使发生堆栈溢出错误,脚本确实会在产生错误之前删除正确的对象(重复的对象)。

系统异常错误之前/之后3ds max的RAM使用情况如下: 在运行脚本之前打开3ds max场景:RAM使用率=大约1800MB 在脚本运行期间,弹出错误消息框之前:RAM使用率从最初的1800增加到最终值2132.6MB 出现系统异常错误消息框:RAM使用率= 2132.6MB 在错误消息框上单击“确定”后:RAM使用率= 2132.6MB (注意:正如我原来的问题所提到的,我有16GB的ram)

我目前的代码:

checked_objs_list; items_to_delete_from_objs; theMeshes; equal_pos_bool ; mesh_data

fn construct_arrays x =(    
    max select none ; select geometry ; deselect helpers
    theMeshes = selection as array
    mesh_info = for theMesh in theMeshes collect ( #(theMesh, getpolygoncount theMesh, theMesh.pos) )  --collects #(tricount, vertcount)    for all meshes in 'getpolycount_meshes'
    max select none     
    --Declare initial values of array variables
    checked_objs_list = #()
    items_to_delete_from_objs = #()
    return mesh_info
    )--end fn construct_arrays

fn delete_duplicates equal_pos_bool =(
    obj_dups = #()
        appendifunique items_to_delete_from_objs mesh_data[1]
        if i <= mesh_data.count and i != 1 do(
            if(mesh_data[i][2][1] == mesh_data[1][2][1] and mesh_data[i][2][2] == mesh_data[1][2][2] and ( if equal_pos_bool then( mesh_data[i][3] == mesh_data[1][3])else(true) )) do(
                if((finditem checked_objs_list (mesh_data[i]) == 0) ) do(
                    appendifunique obj_dups mesh_data[i][1] ; --print "||||||||||||||||||||| FOUND DUPLICATE OBJECT |||||||||||||||||||||| \n"
                    appendifunique checked_objs_list mesh_data[i]
                    appendifunique items_to_delete_from_objs mesh_data[i]
                    )-- end if(finditem checked_objs_array objs[i] == 0 ) do(
                )-- end if(Tricount == Tricount_src and PolyCount == PolyCount_src and VertCount == VertCount_src and ( if equal_pos_boolean then( Position == Position_src)else(true) )) do(
            )-- end if i <= objs.count(
        ) --end for i in 1 to mesh_data[1].count do(

    for item in items_to_delete_from_objs do(
            deleteitem mesh_data (finditem mesh_data item)
            )

    items_to_delete_from_objs = #()
    for duplicate in obj_dups do(delete duplicate)

    if mesh_data.count > 0 do (
        delete_duplicates equal_pos_bool
        )
    )

mesh_data = construct_arrays 1 --call construct_arrays function and save        returned data in variable 'mesh_data'
delete_duplicates false --function call

该问题似乎与场景中的对象/多边形数量无关;我在包含16204个标准基本对象的场景上运行脚本。该场景由11,418,736个多边形和5,780,404个顶点组成,而导致堆栈溢出错误的导入对象的场景仅包含703,737个多边形和769,886个顶点(显着更低)。

我让堆栈溢出错误多次出现,每次都会产生一个略有不同的错误消息框,所有这些都可以在下面看到:

第一次崩溃时产生错误:

stack overflow error 1

第二次崩溃时产生错误:

stack overflow error 2

第3次崩溃时产生错误:

stack overflow error 3

监听器窗口中显示的错误告诉我在&#39; Macro_SceneExplorer.mcr&#39;中出现错误。在第1001行中,该行包含以下代码: sceneexplorermanager.ExplorerIsOpen ~SE_SCENE_EXPLORER_NAME~

它还告诉我这行代码是从我的&#39; delete_duplicates.ms&#39;的第44行调用的。脚本,其中包含以下代码: for duplicate in obj_dups do(delete duplicate)

以下是发生堆栈溢出错误后在侦听器窗口中生成的错误消息的一部分(可以在此处找到完整错误和堆栈跟踪:https://drive.google.com/open?id=1s-BplnpiM_sz3yfN4XVySmhcsK5zraeX):

-- Error occurred in anonymous codeblock; filename: C:\Program     Files\Autodesk\3ds Max 2018\MacroScripts\Macro_SceneExplorer.mcr; position: 29880; line: 1001
-- MAXScript MacroScript Error Exception:
-- Known system exception
--       ########################################################################
-- Address: 0x6745e920; nCode: 0x00000000C00000FD
-- Desc: EXCEPTION_STACK_OVERFLOW The thread used up its stack.
-- ########################################################################
-- MAXScript callstack:
--  thread data: threadID:5300
--  ------------------------------------------------------
--  [stack level: 0]
--  In isChecked(); filename: C:\Program Files\Autodesk\3ds Max 2018\MacroScripts\Macro_SceneExplorer.mcr; position: 29881; line: 1001
--  member of: codeblock macroScript: Scene Explorer_SESceneExplorer
--      Locals:
--      Externals:
--          owner: <CodeBlock:Scene Explorer_SESceneExplorer>
--          Scene Explorer_SESceneExplorer: <CodeBlock:Scene Explorer_SESceneExplorer>
--  ------------------------------------------------------
--  [stack level: 1]
--  called from codeblock macroScript: Scene Explorer_SESceneExplorer;     filename: C:\Users\Philips\Desktop\ninjaripper1.7.1\tools \3dmax_maxscript_importer\0000_delete duplicates (pre-construct_arrays) 9  (noprint) 2.ms; position: 2755; line: 44
--      Locals:
--      Externals:
--  ------------------------------------------------------
--  [stack level: 2]
--  called from duplicate loop; filename: C:\Users\Philips\Desktop\ninjaripper1.7.1\tools\3dmax_maxscript_importer\0000_delete duplicates (pre-construct_arrays) 9 (noprint) 2.ms; position: 2755; line: 44
--      Parameters:
--          duplicate: <Deleted scene node>
--      Locals:
--          duplicate: <Deleted scene node>
--      Externals:
--          owner: undefined
--  ------------------------------------------------------
--  [stack level: 3]
--  called from delete_duplicates(); filename: C:\Users\Philips\Desktop\ninjaripper1.7.1\tools\3dmax_maxscript_importer\0000_delete duplicates (pre-construct_arrays) 9 (noprint) 2.ms; position: 2755; line: 44
--      Parameters:
--          equal_pos_bool: false
--      Locals:
--          equal_pos_bool: false
--          obj_dups: #(<Deleted scene node>)
--      Externals:
--          owner: undefined
--          delete_duplicates: Global:delete_duplicates : delete_duplicates()
--          mesh_data: Global:mesh_data : #(#($Editable_Mesh:Mesh_2184 @ [0.000000,0.000000,0.000000], #(128, 28), [0,0,0]), #($Editable_Mesh:Mesh_2185 @ [0.000000,0.000000,0.000000], #(128, 28), [0,0,0]), #($Editable_Mesh:Mesh_2256 @ [0.000000,0.000000,0.000000], #(256, 768), [0,0,0]), #($Editable_Mesh:Mesh_2258 @ [0.000000,0.000000,0.000000], #(2048, 1057), [0,0,0]), #($Editable_Mesh:Mesh_2261 @ [0.000000,0.000000,0.000000], #(512, 273), [0,0,0]), #($Editable_Mesh:Mesh_2262 @ [0.000000,0.000000,0.000000], #(512, 281), [0,0,0]), #($Editable_Mesh:Mesh_2263 @ [0.000000,0.000000,0.000000], #(2048, 1057), [0,0,0]), #($Editable_Mesh:Mesh_2265 @ [0.000000,0.000000,0.000000], #(32, 23), [0,0,0]), #($Editable_Mesh:Mesh_2266 @ [0.000000,0.000000,0.000000], #(32, 23), [0,0,0]), #($Editable_Mesh:Mesh_2267 @ [0.000000,0.000000,0.000000], #(128, 73), [0,0,0]), #($Editable_Mesh:Mesh_2268 @ [0.000000,0.000000,0.000000], #(128, 77), [0,0,0]), #($Editable_Mesh:Mesh_2269 @ [0.000000,0.000000,0.000000], #(512, 273), [0,0,0]), #($Editable_Mesh:Mesh_2270 @ [0.000000,0.000000,0.000000], #(2048, 1041), [0,0,0]), #($Editable_Mesh:Mesh_2271 @ [0.000000,0.000000,0.000000], #(32, 21), [0,0,0]), #($Editable_Mesh:Mesh_2272 @ [0.000000,0.000000,0.000000], #(32, 23), [0,0,0]), #($Editable_Mesh:Mesh_2273 @ [0.000000,0.000000,0.000000], #(128, 73), [0,0,0]), #($Editable_Mesh:Mesh_2274 @ [0.000000,0.000000,0.000000], #(512, 265), [0,0,0]), #($Editable_Mesh:Mesh_2276 @ [0.000000,0.000000,0.000000], #(32, 23), [0,0,0]), #($Editable_Mesh:Mesh_2277 @ [0.000000,0.000000,0.000000], #(128, 73), [0,0,0]), #($Editable_Mesh:Mesh_2278 @ [0.000000,0.000000,0.000000], #(50, 60), [0,0,0]), ...)
--          items_to_delete_from_objs: Global:items_to_delete_from_objs : #()
--  ------------------------------------------------------
--  [stack level: 4]
--  called from delete_duplicates(); filename: C:\Users\Philips\Desktop\ninjaripper1.7.1\tools\3dmax_maxscript_importer\0000_delete duplicates (pre-construct_arrays) 9 (noprint) 2.ms; position: 2958; line: 49
--      Parameters:
--          equal_pos_bool: false
--      Locals:
--          equal_pos_bool: false
--          obj_dups: #()
--      Externals:
--          owner: undefined
--          delete_duplicates: Global:delete_duplicates : delete_duplicates()
--          mesh_data: Global:mesh_data : #(#($Editable_Mesh:Mesh_2184 @ [0.000000,0.000000,0.000000], #(128, 28), [0,0,0]), #($Editable_Mesh:Mesh_2185 @ [0.000000,0.000000,0.000000], #(128, 28), [0,0,0]), #($Editable_Mesh:Mesh_2256 @ [0.000000,0.000000,0.000000], #(256, 768), [0,0,0]), #($Editable_Mesh:Mesh_2258 @ [0.000000,0.000000,0.000000], #(2048, 1057), [0,0,0]), #($Editable_Mesh:Mesh_2261 @ [0.000000,0.000000,0.000000], #(512, 273), [0,0,0]), #($Editable_Mesh:Mesh_2262 @ [0.000000,0.000000,0.000000], #(512, 281), [0,0,0]), #($Editable_Mesh:Mesh_2263 @ [0.000000,0.000000,0.000000], #(2048, 1057), [0,0,0]), #($Editable_Mesh:Mesh_2265 @ [0.000000,0.000000,0.000000], #(32, 23), [0,0,0]), #($Editable_Mesh:Mesh_2266 @ [0.000000,0.000000,0.000000], #(32, 23), [0,0,0]), #($Editable_Mesh:Mesh_2267 @ [0.000000,0.000000,0.000000], #(128, 73), [0,0,0]), #($Editable_Mesh:Mesh_2268 @ [0.000000,0.000000,0.000000], #(128, 77), [0,0,0]), #($Editable_Mesh:Mesh_2269 @ [0.000000,0.000000,0.000000], #(512, 273), [0,0,0]), #($Editable_Mesh:Mesh_2270 @ [0.000000,0.000000,0.000000], #(2048, 1041), [0,0,0]), #($Editable_Mesh:Mesh_2271 @ [0.000000,0.000000,0.000000], #(32, 21), [0,0,0]), #($Editable_Mesh:Mesh_2272 @ [0.000000,0.000000,0.000000], #(32, 23), [0,0,0]), #($Editable_Mesh:Mesh_2273 @ [0.000000,0.000000,0.000000], #(128, 73), [0,0,0]), #($Editable_Mesh:Mesh_2274 @ [0.000000,0.000000,0.000000], #(512, 265), [0,0,0]), #($Editable_Mesh:Mesh_2276 @ [0.000000,0.000000,0.000000], #(32, 23), [0,0,0]), #($Editable_Mesh:Mesh_2277 @ [0.000000,0.000000,0.000000], #(128, 73), [0,0,0]), #($Editable_Mesh:Mesh_2278 @ [0.000000,0.000000,0.000000], #(50, 60), [0,0,0]), ...)
--          items_to_delete_from_objs: Global:items_to_delete_from_objs :   #()

错误继续这样,直到堆栈级别386 ...其余的错误看起来类似于下面显示的部分(错误再次持续很长时间,请参阅前面提到的.txt文件完整错误):

--  [stack level: 387]
--  called from top-level
--   ########################################################################
-- C++ callstack:
-- (ucrtbase): (filename not available): malloc_base
-- (maxutil): (filename not available): GetWindowTextW
-- (MAXScrpt): (filename not available): InterfaceFunction::val_to_FPValue
-- (MAXScrpt): (filename not available): Generic::apply
-- (MAXScrpt): (filename not available): CodeTree::eval
-- (MAXScrpt): (filename not available): Generic::apply
-- (MAXScrpt): (filename not available): SourceFileWrapper::apply
-- (MAXScrpt): (filename not available): SourcePositionWrapper::apply_no_alloc_frame
-- (MAXScrpt): (filename not available): MacroEntry::DisableCompileGuard::DisableCompileGuard
-- (MAXScrpt): (filename not available): InitMacroScriptDir
-- (core): (filename not available): MacroButtonData::SetLabel
-- (core): (filename not available): MaxSDK::QMaxMultiResIconManager::trUtf8
-- (Qt5Core): (filename not available): QMetaObject::activate
-- (core): (filename not available): MaxSDK::QMaxMacroButtonUpdater::qt_static_metacall
-- (core): (filename not available): MaxSDK::QMaxMacroButtonUpdater::updateAll
-- (MAXScrpt): (filename not available): collect_nodes
-- (MAXScrpt): (filename not available): Primitive::apply
-- (MAXScrpt): (filename not available): CodeTree::eval
-- (MAXScrpt): (filename not available): Primitive::apply
-- (MAXScrpt): (filename not available): Array::map
-- (MAXScrpt): (filename not available): clear_error_source_data
-- (MAXScrpt): (filename not available): Primitive::apply
-- (MAXScrpt): (filename not available): CodeTree::eval
-- (MAXScrpt): (filename not available): Primitive::apply
-- (MAXScrpt): (filename not available): CodeTree::eval
-- (MAXScrpt): (filename not available): SourceFileWrapper::eval
-- (MAXScrpt): (filename not available): Generic::apply
-- (MAXScrpt): (filename not available): CodeTree::eval
-- (MAXScrpt): (filename not available): clear_error_source_data
-- (MAXScrpt): (filename not available): Primitive::apply
-- (MAXScrpt): (filename not available): CodeTree::eval
-- (MAXScrpt): (filename not available): Primitive::apply
-- (MAXScrpt): (filename not available): CodeTree::eval
-- (MAXScrpt): (filename not available): SourceFileWrapper::eval
-- (MAXScrpt): (filename not available): Generic::apply
-- (MAXScrpt): (filename not available): CodeTree::eval
-- (MAXScrpt): (filename not available): clear_error_source_data
-- (MAXScrpt): (filename not available): Primitive::apply
-- (MAXScrpt): (filename not available): CodeTree::eval
-- (MAXScrpt): (filename not available): Primitive::apply
-- (MAXScrpt): (filename not available): CodeTree::eval
-- (MAXScrpt): (filename not available): SourceFileWrapper::eval
-- (MAXScrpt): (filename not available): Generic::apply
-- (MAXScrpt): (filename not available): CodeTree::eval
-- (MAXScrpt): (filename not available): clear_error_source_data
-- (MAXScrpt): (filename not available): Primitive::apply
-- (MAXScrpt): (filename not available): CodeTree::eval

有时,而不是错误消息框&#39;堆栈溢出错误&#39;我收到错误消息框&#39;未知系统异常&#39; (大多数时候我得到堆栈溢出错误消息框,我还没有发现其中一个发生的原因)。其他时候3ds max和Windows问题报告没有生成错误消息框给我一个消息框说3ds max已经停止工作。

我尝试了解有关“3ds max已停止工作”的更多信息。使用窗口的事件查看器时出错: enter image description here

<强>文件:

包含4000多个标准基本对象的场景,脚本完美运行:https://drive.google.com/open?id=1ittqWwvqgJjrsNcNkbhM_mOHUnz1W-SH

包含导入上述堆栈溢出/未知系统异常错误的导入对象的场景: https://drive.google.com/open?id=1JpncS9pJcYxGeZU4UI_uzmLIPnB9r0uJ

发生堆栈溢出错误消息后,

侦听器输出(错误): https://drive.google.com/open?id=1s-BplnpiM_sz3yfN4XVySmhcsK5zraeX

发生未知系统异常错误消息后,

侦听器输出(错误): https://drive.google.com/open?id=1QPl0e0RHcqKIPkMaorMRJm-Q_LyWvG1E

&#39; delete_duplicates.ms&#39; maxscript代码: https://drive.google.com/open?id=1FCpJNlgII6ouLYsh0ySjHXuTiKmfkWEK

我用于测试的另一个.max场景产生了类似的错误: https://drive.google.com/open?id=142JOth12rATD3sW4LlTmMX2vVzCLnmJs

对于我做错了什么/可能导致这些错误的任何建议将不胜感激,谢谢!