Forum Groups
  All forums
    Help & Feedback
      Work in progress
      Finished Art
      Non-Max related

Maxunderground news unavailable

Maxscript: Ordering of selected objects and controlling them.
show user profile  Herbie
I have a couple of questions about going through selections via maxscript..
Make a plane, make it an editable poly.
Now, this code should go through every face and detach it.. only it goes through half of them every time. What is causing this?
p = $
faces = p.numfaces
for c = 1 to faces do (
p.editablepoly.setselection #face #{c}
polyops.detach p
^That's not the main reason for the post, but this confuses me.

The real reason for the post is, I have all of these detached faces and an animated gradient ramp with a UVW map over the entire selection.

How do I take the value of the gradient from the center of each detached piece?
Is there a getMaterialValue at [#,#,#]?

read 1915 times
12/20/2011 1:48:44 AM (last edit: 12/20/2011 1:48:44 AM)
show user profile  Garp
Faces are always indexed from 1 and upward. So if you remove face #1 (either delete it or detach to object), the remaining faces are renumbered and removing face #2 will skip the new face #1 (after renumbering).
Just do it backward: for c = faces to 1 by -1 do (...)

Off the top of my head, use renderMap() to render the gradient in memory as a bitmap value, then for each face, find the coordinates of its center in the UV space, use them (along with the resolution of the bitmap) to determine which pixel you want and read its color value with getPixels().

read 1905 times
12/20/2011 3:17:05 AM (last edit: 12/20/2011 3:24:24 AM)
show user profile  Herbie
Wow.. I had no idea if you detach a piece they would become renumbered again.. that definitrly makes things more simple.

I would never have figured out the whole rendermap and getpixels thing.. I didnt even know that existed!
I was experimenting a bit with applying a uvw map to the selection, then throwing a volume select modifier on it to control it via an animated gradient ramp. The hard part is checking if a piece is selected by the volume select modifier and telling it to do whatever at the frame where the state switches from not being selected to being selected.

I'll give your idea a shot tomorrow and see how that goes.

Thank you for your help!
read 1889 times
12/20/2011 11:47:46 AM (last edit: 12/20/2011 11:47:46 AM)
show user profile  Herbie
I think I might just throw all my questions into this post.. because it seems like I'm hitting walls all over the place.
The question now is aligning modifier centers with objects centers.
It should be as simple as:

curCenter =
addmodifier obj (sliceModifier())
obj.modifiers[#Slice].slice_plane.position = curCenter

And if I want the slice plane to be right on the edge of the object:
curBB = nodeLocalBoundingBox $
curXsize = curBB[2][1] - curBB[1][1] --x width
obj.modifiers[#Slice].slice_plane.position = (curCenter + [(curXsize/2),0,0])

However, it's not always lining up. Is it a coordinate space issue?

So I figured it out after a bunch of digging. Turns out the slice gizmo is in object coordinate space while the transforms for the obj are in world.
It's as nasty conversion process, but it works.

Here's the solution
sliceRot = (eulerangles 90 0 0) as quat
sliceMod.slice_plane.rotation = sliceRot * modTM - (inverse (curTM as quat)) -- rotates slice gizmo
sliceMod.Slice_Plane.position = curCenter * modTM * (inverse curTM) -- centers slice modifier
read 1873 times
12/20/2011 8:27:06 PM (last edit: 12/20/2011 11:37:14 PM)
show user profile  Garp
You can simplify it a little.
Let me give you a simple example to clarify:
- make a box and a plane, move/rotate them randomly and have the plane intersect the box.
- then

read 1855 times
12/21/2011 3:11:12 AM (last edit: 12/21/2011 3:11:46 AM)
show user profile  Herbie
The renderMap() and all the math that goes with finding a point in UV space, as well as the getPixels() is all in place.
It works.... mostly.
I think I'm still screwing up somewhere though.
For all the detached pieces, I select them and make them into $group1 via maxscript

Here's where the problem happens.
when I bust out:

gMin = $group1.min
gMax = $group1.max
gDimensions = gMax - gMin
ungroup $group1

The dimensions of the group will be "0.0200005" for both x and y.
However, if I manually make it into a group via the menu, then run those 4 lines of code, everything will be correct.

What's causing the grouping via maxscript to give me the wrong dimesions of the bounding box?
read 1853 times
12/21/2011 3:12:48 AM (last edit: 12/21/2011 3:12:48 AM)
show user profile  Garp
No idea. Sounds like a little bug.
Instead of grouping/ungrouping all the detached polys, can't you just grab min and max of the original object, before you detached the polys?
Also, instead of grouping, you could use an object set. For example, if all the detached polys are named, say, theface001, theface002, etc, you can do
gDimensions = $theface*.max - $theface*.min

And did my previous bit help with the transforms?

read 1846 times
12/21/2011 3:32:36 AM (last edit: 12/21/2011 3:33:00 AM)
show user profile  Herbie
The original object may not work because there's still some manual steps involved in the process.. however, in the near future, that could easily change :)

I'm so glad you showed me the thing about the object sets! I had the same idea, however, I was avoiding going down that route because I was about to do that in a much uglier way with arrays and comparing values with one another.
I didn't know you could get properties with wildcards like that.

The transforms did help simplify it in some areas, I was having a weird problem rotating the slice plane though.
I had to set the rotation the way I wanted before I moved the slice plane, otherwise the slice plane was jumping around in odd places. Then I could offset the plane where it needed to be using local coordsys.

On another note, is there a way to move on to another object in a for loop once the condition has been met the first time? For example:
There's a loop going through all the objects and a nested loop checking whether a value has been reached, do some code then move onto the next object.

Normally this is fine, however, the nested loop is looping time, say frame 0 to 20 and the object meets the conditions from frame 13 to 20. If I'm offsetting keyframes, it's going to offset the keyframes when the condition is met at frame 13, then again at 14, 15, etc.

I was thinking about having 2 variables for the "if" statement.
The first being the currentValue and testing it against the condition, then at the end of the loop, set lastValue = currentValue.
So then the "if" statement would read something like:
if currentValue > 50 and lastValue <= 50 do ()

Is there an easier way to go about this?
read 1842 times
12/21/2011 4:35:56 AM (last edit: 12/21/2011 4:35:56 AM)
show user profile  Garp
Maybe I'm tired but I couldn't make sense of that last bit.
Care to simplify a little?

read 1840 times
12/21/2011 4:43:29 AM (last edit: 12/21/2011 4:43:29 AM)
show user profile  Herbie
Sorry, I'm not the best explainer.

I have multiple detached faces, say 10.
"for" loop going through every one
for c in (seleciton as array) do ()

each detached face has a 20 frame animation on it, say keyframe at 1 and 20.

There's an animated gradient ramp which has a solid blending mode on it, so it's either all white or black at a given point. It takes, say 30 frames to complete it's animation.

The detached faces are then applied 1 uvw map that covers all 10 faces.

I rendermap the gradient ramp at time 1 and check to see if the center point of the current face is covered in black or white.

This is where I'm having a bit of trouble and can get really confusing..
I want to find the first frame where each center point of the face goes from black to white.
I only need the first frame it goes white because I want to offset the animation to that particular frame for that face.

I believe my problem is how I'm testing for that first frame of white..
I need to break out of the loop for that particular face when it turns white and have it go on to the next face.

Normally in a for loop you can say: 't in 1 to 10' or 'c in selection' or 'i in 1 to array.count'
but if the end result is a color.. I'm not sure how to do that.. or how to iterate through that loop.

Hopefully this is a bit more simplified..
read 1836 times
12/21/2011 6:37:36 AM (last edit: 12/21/2011 6:37:36 AM)
show user profile  Garp
Try with a while loop as your inner loop with a variable that you increment each time around and a condition that tests for the color and for the frame range.
Something like:
fn is_black frame = ( -- your color test here)
local f = first
while is_black(f) and f < last do f += 1

You could also use exit to break out of a for loop, but it's pretty slow and if you have many faces to test it'll become significant.

read 1803 times
12/22/2011 12:08:39 PM (last edit: 12/22/2011 12:10:10 PM)
show user profile  Garp
Something a little more structured:

Here, the inner loop is inside a function first_white() that either returns the frame number at which the color changed to white or the value undefined if the color is still black at the end of the range (the trick is that return f exits both the loop and the function).
The outer loop then creates a Lookup object (just a pair of values) each time around and collects them into a lookup table.

In the code above, the is_white() function tests only for the diffuse color. Replace it with you own test.

read 1785 times
12/23/2011 6:51:26 AM (last edit: 12/23/2011 7:00:10 AM)
#Maxforums IRC
Open chat window