CGTalk > Software Specific Forums > Autodesk 3ds max > 3dsMax SDK and MaxScript
To minimize the ads you see on this page create a CGTalk account and log in HERE
Thread Closed share thread « Previous Thread | Next Thread »
 
Thread Tools Search this Thread Display Modes
Old 03-01-2013, 07:38 AM   #1
Ian31R
Frequenter
portfolio
Ian Adams
Freelancer
Kent, USA
 
Join Date: Aug 2011
Posts: 289
Red face Exit loop when bitarray stops changing

I'm trying to figure out how the best method for exiting a loop after a bitarray stops changing. For example if I'm growing a selection until it fills up the mesh's elements, I could grow to the total number of verts, edges, or faces getting the selection before you grow, and exit when the numberset of the current selection equals the numberset of the previous selection. I think using a for loop is the only way to go for this, but I'm not 100 percent sure. I was curious if anyone knows a better / faster method for this.

Here's a function using this method, which converts an edge selection to borders in editable mesh, by growing the edge selection once, and intersecting it with all open edges. -

Code:
fn GetBordersUsingEdgeMesh Obj:$ Sel:(getEdgeSelection $) = ( local AllBorderSel = (meshop.getOpenEdges Obj) local BorderSel = (Sel * AllBorderSel) -- Select within borders for i = 1 to (Obj.numFaces * 3) do ( local OldNum = BorderSel.numberset -- Get past selection BorderSel += ((meshop.getEdgesUsingVert Obj (meshop.getVertsUsingEdge Obj BorderSel)) * AllBorderSel) -- Grow edge selection once within border if (BorderSel.numberset == OldNum) then exit -- Exit if selection doesn't change ) -- Convert edges to border return BorderSel -- Get edges )


It seems to work ok, but I'm thinking there has to be a more efficient way..
 
Old 03-01-2013, 09:56 AM   #2
DanGrover
Know-it-All
portfolio
Dan Grover
Technical Director
River Film
London, United Kingdom
 
Join Date: Sep 2004
Posts: 355
Send a message via MSN to DanGrover
It may be worth have a While loop and omitting the 'if' test that currently exits the loop. You already have the variable assignment necessary, so it'd basically be (pseduocode)

while BorderSel.numberset != OldNum do
(
grow border stuff
)

This way you avoid the (according to the maxscript documentation) slow 'exit' process, as well as save on generating the variable 'i' that it appears you actually don't need (though you could do this by simply omitting the 'i=' entirely - you can, I believe, simply do 'for 1 to 10 do' etc).
__________________

 
Old 03-01-2013, 10:46 AM   #3
miauu
Expert
 
miauu's Avatar
portfolio
Kostadin Kotev
Blagoevgrad, Bulgaria
 
Join Date: Sep 2009
Posts: 760
Or, if you want to stay with for loop use this:

Code:
fn GetBordersUsingEdgeMesh Obj:$ Sel:(getEdgeSelection $) = ( local AllBorderSel = (meshop.getOpenEdges Obj) local BorderSel = (Sel * AllBorderSel) -- Select within borders stopLoop = false for i = 1 to (Obj.numFaces * 3) while stopLoop == false do ( local OldNum = BorderSel.numberset -- Get past selection BorderSel += ((meshop.getEdgesUsingVert Obj (meshop.getVertsUsingEdge Obj BorderSel)) * AllBorderSel) -- Grow edge selection once within border if (BorderSel.numberset == OldNum) do stopLoop = true ) -- Convert edges to border return BorderSel -- Get edges )
 
Old 03-01-2013, 01:52 PM   #4
denisT
MAX Doctor
 
denisT's Avatar
portfolio
Denis Trofimov
CA, USA
 
Join Date: Jul 2009
Posts: 9,094
Send a message via ICQ to denisT
the method itself is OK but Obj:$ Sel:(getEdgeSelection $) is very bad for many reasons...
 
Old 03-01-2013, 01:57 PM   #5
denisT
MAX Doctor
 
denisT's Avatar
portfolio
Denis Trofimov
CA, USA
 
Join Date: Jul 2009
Posts: 9,094
Send a message via ICQ to denisT
Quote:
Originally Posted by denisT
the method itself is OK but Obj:$ Sel:(getEdgeSelection $) is very bad for many reasons...

no... the method is also wrong.
 
Old 03-01-2013, 03:05 PM   #6
gazybara
Architect
 
gazybara's Avatar
portfolio
Branko Živković
Freelancer
Niš, Serbia
 
Join Date: Apr 2011
Posts: 1,077
Quote:
Originally Posted by denisT
the method itself is OK but Obj:$ Sel:(getEdgeSelection $) is very bad for many reasons...

Hi Denis, can you explain why this concept in not good
I supose that this is also bad
Code:
...Obj:$ Sel:($.selectededges as array)
__________________
Looking in the right side. [bgaTools]
 
Old 03-01-2013, 06:22 PM   #7
denisT
MAX Doctor
 
denisT's Avatar
portfolio
Denis Trofimov
CA, USA
 
Join Date: Jul 2009
Posts: 9,094
Send a message via ICQ to denisT
Quote:
Originally Posted by gazybara
Hi Denis, can you explain why this concept in not good
I supose that this is also bad
Code:
...Obj:$ Sel:($.selectededges as array)

the idea is stop loop when edge collection stopped grow. right? but we check only size (numberset) of this collection. but there's possible topology when growing border edges doesn't change the number of new border edges. for example when you grow edges from pole of a sphere. got it?
 
Old 03-01-2013, 07:00 PM   #8
denisT
MAX Doctor
 
denisT's Avatar
portfolio
Denis Trofimov
CA, USA
 
Join Date: Jul 2009
Posts: 9,094
Send a message via ICQ to denisT
Code:
fn growEdgesToBorder node edges: show:on = if iskindof node editable_mesh or iskindof node trimesh do ( if edges == unsupplied do edges = node.selectededges as bitarray local ee = #{}, border = edges, opened = meshop.getopenedges node while not (border - ee).isEmpty do ( ee = border border = edges - opened edges = meshop.getedgesusingvert node (meshop.getvertsusingedge node edges) border = edges - border ) if show do node.selectededges = border border )

any smarter solution is welcome...

Last edited by denisT : 03-01-2013 at 07:04 PM.
 
Old 03-01-2013, 07:35 PM   #9
gazybara
Architect
 
gazybara's Avatar
portfolio
Branko Živković
Freelancer
Niš, Serbia
 
Join Date: Apr 2011
Posts: 1,077
Quote:
Originally Posted by denisT
the idea is stop loop when edge collection stopped grow. right? but we check only size (numberset) of this collection. but there's possible topology when growing border edges doesn't change the number of new border edges. for example when you grow edges from pole of a sphere. got it?

Thanks Denis for the explanation and example. I don't think there is better solution.
Is it better(fester) to use meshOp and polyOp operations outside for-loop and while-loop as variable?
__________________
Looking in the right side. [bgaTools]
 
Old 03-01-2013, 07:36 PM   #10
denisT
MAX Doctor
 
denisT's Avatar
portfolio
Denis Trofimov
CA, USA
 
Join Date: Jul 2009
Posts: 9,094
Send a message via ICQ to denisT
Quote:
Originally Posted by gazybara
Thanks Denis for the explanation and examle. I don't think there is better solution.
Is it better(fester) to use meshOp and polyOp operations outside for-loop and while-loop as variable?

it's better to local... not faster but saves a lot of memory
i didn't do it the sample to not confuse rookies...

so the pro version might look as
Code:
fn growEdgesToBorder node edges: show:on = if iskindof node editable_mesh or iskindof node trimesh do ( if edges == unsupplied do edges = node.selectededges as bitarray local ee = #{}, border = edges, opened = meshop.getopenedges node, getedgesusingvert = meshop.getedgesusingvert, getvertsusingedge = meshop.getvertsusingedge while not (border - ee).isEmpty do ( ee = border border = edges - opened edges = getedgesusingvert node (getvertsusingedge node edges) border = edges - border ) if show do node.selectededges = border border )

Last edited by denisT : 03-01-2013 at 07:40 PM.
 
Old 03-01-2013, 08:08 PM   #11
denisT
MAX Doctor
 
denisT's Avatar
portfolio
Denis Trofimov
CA, USA
 
Join Date: Jul 2009
Posts: 9,094
Send a message via ICQ to denisT
meshop.getedgesusingvert
meshop.getvertsusingedge

these particular functions don't really leak much, but in general it's safer to put any interface function in a local variable and call it from there.
I posted several samples on this forum which show the difference.
 
Old 03-01-2013, 08:16 PM   #12
gazybara
Architect
 
gazybara's Avatar
portfolio
Branko Živković
Freelancer
Niš, Serbia
 
Join Date: Apr 2011
Posts: 1,077
Quote:
Originally Posted by denisT
meshop.getedgesusingvert
meshop.getvertsusingedge

these particular functions don't really leak much, but in general it's safer to put any interface function in a local variable and call it from there.
I posted several samples on this forum which show the difference.

Yep. I already saw a few. Cheers!
__________________
Looking in the right side. [bgaTools]
 
Old 03-02-2013, 12:34 AM   #13
Ian31R
Frequenter
portfolio
Ian Adams
Freelancer
Kent, USA
 
Join Date: Aug 2011
Posts: 289
Wow, thanks for all the replies guys! And thanks denis for the examples.

I've noticed the assignment of operations to variables in the reference before, and I can definitely see the performance gain with that. I also didn't think about cases where your selection is outside of open borders, which would lead to an empty selection that wouldn't grow. I still think though that cases where the edge selection is on a pole would still grow, I don't see why it wouldn't.

One thing I don't understand is why using default values for node and the edge selection are bad, that's what I've used for all of my functions and their inputs, is default values, so I don't always need to specify them. Is specifying the default value in the function a lot safer?

Again, thanks for your help everyone.
 
Old 03-02-2013, 12:49 AM   #14
denisT
MAX Doctor
 
denisT's Avatar
portfolio
Denis Trofimov
CA, USA
 
Join Date: Jul 2009
Posts: 9,094
Send a message via ICQ to denisT
Quote:
Originally Posted by Ian31R
One thing I don't understand is why using default values for node and the edge selection are bad, that's what I've used for all of my functions and their inputs, is default values, so I don't always need to specify them. Is specifying the default value in the function a lot safer?

look at what you have:
Code:
fn GetBordersUsingEdgeMesh Obj:$ Sel:(getEdgeSelection $)

i said there are reasons that make it bad... check yourself:
# what if noting selected
# what if multiple selection
# what if not an editable mesh selected

of course you can use default values for additional arguments and do it, but be sure that these values don't break the function before it goes to execution.

if you are absolutely sure that the function can never be called with wrong values where is a reason to give it defaults. does it make sense?
 
Old 03-02-2013, 07:55 AM   #15
Ian31R
Frequenter
portfolio
Ian Adams
Freelancer
Kent, USA
 
Join Date: Aug 2011
Posts: 289
Well I usually check for if an object is selected and if there are subobjects selected, I forgot to put the checks in this function. Although I should put in a check for multiple node selections.I haven't worried about checking the class of the the node in most of my functions, because I plan on checking that later, when I call the functions, depending on what the user has selected. That's also why I put Mesh at the end of the function name, so I know what its used for.

Having defaults in the functions just seems more flexible to me. Especially for functions that have a lot of parameters, and can do many different things. Its nice to not have to specify all of the parameters all the time.
 
Thread Closed share thread


Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
CGSociety
Society of Digital Artists
www.cgsociety.org

Powered by vBulletin
Copyright ©2000 - 2006,
Jelsoft Enterprises Ltd.
Minimize Ads
Forum Jump
Miscellaneous

All times are GMT. The time now is 12:42 PM.


Powered by vBulletin
Copyright ©2000 - 2016, Jelsoft Enterprises Ltd.