The Editable_Spline script consumes all available RAM - any help would be greatly appreciated

I'm using this code to remove all spline segments outside a certain object; however, on complex splines, it consumes all available RAM immediately and crashes 3ds Max.
Is there any way to make it significantly faster and less memory-intensive?
Appreciated in advance

(
    fn getMeshBoundingBox2D obj =
    (
        local bbMin = [1e9,1e9,0]
        local bbMax = [-1e9,-1e9,0]
 
        local t = obj.transform
        local vCount = getNumVerts obj
        for i = 1 to vCount do (
            local p = getVert obj i * t
            bbMin.x = amin bbMin.x p.x
            bbMin.y = amin bbMin.y p.y
            bbMax.x = amax bbMax.x p.x
            bbMax.y = amax bbMax.y p.y
        )
        return #(bbMin, bbMax)
    )
 
    fn isInside2D p minBB maxBB =
        (p.x >= minBB.x and p.x <= maxBB.x and p.y >= minBB.y and p.y <= maxBB.y)
 
    fn keepSegmentsInBox shapeObj minBB maxBB =
    (
        local t = shapeObj.transform
 
        for i = numSplines shapeObj to 1 by -1 do (
            local newPts = #()
            local n = numKnots shapeObj i
            local closed = isClosed shapeObj i
 
            for k = 1 to n do (
                local nextK = if (k == n) then 1 else (k + 1)
                local p1 = getKnotPoint shapeObj i k * t
                local p2 = getKnotPoint shapeObj i nextK * t
 
                if (isInside2D p1 minBB maxBB and isInside2D p2 minBB maxBB) do (
                    append newPts (getKnotPoint shapeObj i k)
                )
            )
 
            deleteSpline shapeObj i
 
            if newPts.count > 1 do (
                addNewSpline shapeObj
                for pt in newPts do (
                    addKnot shapeObj (numSplines shapeObj) #corner #line pt
                )
            )
        )
        updateShape shapeObj
    )
 
    local satelliteMesh = getNodeByName "satellite_texture"
    if not isValidNode satelliteMesh do
        satelliteMesh = getNodeByName "natural_land"
 
    if isValidNode satelliteMesh and classof satelliteMesh == Editable_Mesh do (
        local bb = getMeshBoundingBox2D satelliteMesh
        local minBB = bb[1]
        local maxBB = bb[2]
 
        local splineNames = #("xx_water_gradient", "xx_spline_trees", "xx_spline_planes")
        for name in splineNames do (
            local s = getNodeByName name
            if isValidNode s and (classof s == line or classof s == splineShape or classof s == Editable_Spline) do (
                keepSegmentsInBox s minBB maxBB
            )
        )
 
        for s in objects where classof s == ChaosScatter do (
            s.enable = false
            forceCompleteRedraw()
            s.enable = true
        )
    )
)

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
SimonBourgeois's picture

Hi

Since your spline object is flat, i would use a shape boolean, using a rectangle shape and setting the boolean operation to intersect

to speed things up i've added an optimize spline modifier at 50% and collapse it before doing the boolean operation.

go to Compound Shapes ,select your spline object click on "shpBoolean", choose intersect, then "Add Operands" pick your rectangle shape then wait for a few minutes...

AttachmentSize
result.max 1.57 MB
miauu's picture

.

Upload a test scene, so we can test the script.

But, you can check which part of the code causes eats the RAM and crashes 3ds max. Just print some information across the code, so in the Listener you can see where the script stops printing and starts eating the RAM. Also, you can redirect the printed information in an external log file, so when 3ds max crashes you can have all the data(otherwise you will lost what is printed in the Listener):

Use something like this:

(
    fn getMeshBoundingBox2D obj =
    (
        local bbMin = [1e9,1e9,0]
        local bbMax = [-1e9,-1e9,0]
 
        local t = obj.transform
        local vCount = getNumVerts obj
        for i = 1 to vCount do (
            local p = getVert obj i * t
            bbMin.x = amin bbMin.x p.x
            bbMin.y = amin bbMin.y p.y
            bbMax.x = amax bbMax.x p.x
            bbMax.y = amax bbMax.y p.y
        )
        return #(bbMin, bbMax)
    )
 
    fn isInside2D p minBB maxBB =
        (p.x >= minBB.x and p.x <= maxBB.x and p.y >= minBB.y and p.y <= maxBB.y)
 
    fn keepSegmentsInBox shapeObj minBB maxBB =
    (
		format "\n"
		format "shapeObj: %   minBB: %   maxBB: %\n" shapeObj minBB maxBB
 
 
        local t = shapeObj.transform
 
        for i = numSplines shapeObj to 1 by -1 do 
		(
			format "	i: %\n" i
            local newPts = #()
            local n = numKnots shapeObj i
            local closed = isClosed shapeObj i
 
            for k = 1 to n do 
			(
                local nextK = if (k == n) then 1 else (k + 1)
                local p1 = getKnotPoint shapeObj i k * t
                local p2 = getKnotPoint shapeObj i nextK * t
 
                if (isInside2D p1 minBB maxBB and isInside2D p2 minBB maxBB) do (
                    append newPts (getKnotPoint shapeObj i k)
                )
            )
 
            deleteSpline shapeObj i
 
            if newPts.count > 1 do 
			(
                addNewSpline shapeObj
                for pt in newPts do 
				(
                    addKnot shapeObj (numSplines shapeObj) #corner #line pt
                )
            )
        )
        updateShape shapeObj
    )
 
    local satelliteMesh = getNodeByName "satellite_texture"
    if not isValidNode satelliteMesh do
        satelliteMesh = getNodeByName "natural_land"
 
    if isValidNode satelliteMesh and classof satelliteMesh == Editable_Mesh do 
	(
        local bb = getMeshBoundingBox2D satelliteMesh
        local minBB = bb[1]
        local maxBB = bb[2]
 
		print "---- 1"
 format "\n"
        local splineNames = #("xx_water_gradient", "xx_spline_trees", "xx_spline_planes")
        for name in splineNames do 
		(
            local s = getNodeByName name
 
			format "	>s1: %\n" s
 
            if isValidNode s and (classof s == line or classof s == splineShape or classof s == Editable_Spline) do 
			(
                keepSegmentsInBox s minBB maxBB
            )
        )
 
		print "---- 2"
		format "\n"
        for s in objects where classof s == ChaosScatter do 
		(
 
			format "	> s2: %\n" s
 
            s.enable = false
            forceCompleteRedraw()
            s.enable = true
        )
 
		print "---- 3"
    )
)

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.