PDA

View Full Version : help needed - link to vertex script


lemasterjg
03-28-2008, 08:08 PM
Iíll start off by saying Iím new to Maxscripting, but I do have years of experience as an actionscript developer. Iíve come across a good tutorial online about how to build a scrip to automate the linking of an object to a vertex of another object at http://www.3dluvr.com/content/article/51

Unfortunately the script didnít work, it was unable to get the vertex number nor does the enable of the Link_Me_button work correctly, one any button in the scrip is pressed the link me button enables, it does not wait for both of the true statements that It should wait for.

Iíve edited the scrip by searching around online and through no easy feat of trial and error Iíve got it working to a degree. The version I have can now get the selected vertex of an object that has a mesh select modifier. The label underneath the button fully functions and changes accordingly,

Here is the real problem Iím having; the link_me_button creates the position script just fine, and however I canít get the vertex number by itself.

Child_Obj.position.controller.script = ("pos = getvert $" + (parentOBJ.name) + " " + (vertex))

I am either given an error stating it can not convert to string, number, text, or float no matter how I try. I can get it down to a number with surrounded by brackets and a # in front of it. Can anyone help?


MainFloater = NewRolloutFloater "Link To Vertex" 300 315 --creates the main floater

Rollout Vert_Linker "Vertex Linker" ( --defines the Rollout with all the settings

group "Pick Vert" ( --defines a group of settings (optional)

Label getvert1L "Select a vertex to be parent" --labels create text on the rollout
Label getvert2L "then hit 'Get Selected Vert'"
Button GetVert_Button "Get Selected Vert" --defines the get vert button
Label vertnumL "Vertex Number: (none selected)"

)

group "Pick Child" (

Label childL "Select Child Object"
PickButton GetChild_PB "Get Child" --defines a button that puts you in to a selection mode
Label childnameL "Child Object: (none)"

)

group "Link ME Plz!" (

Button LinkME_Button "Link ME!" enabled:off --defines the button to press to link
)
-----------------------------------------------------------------------------
on GetVert_Button pressed do (


parentOBJ = $
if classof parentOBJ == Editable_Mesh do (
vertnum = (getvertselection parentOBJ) as array
if vertnum.count>0 do (
vert = getVert parentOBJ vertnum[1]
vertex = (vertnum as string)
vertnumL.text = "Vertex Number: " + vertex
VertPicked = true
)
)
if ChildPicked == true do LinkME_Button.enabled = on
)
-----------------------------------------------------------------------------
on GetChild_PB picked obj do (

Child_Obj = obj
childnameL.text = "Child Object: " + Child_Obj.name
ChildPicked = true
if ChildPicked == true do LinkME_Button.enabled = on
)
-----------------------------------------------------------------------------
on LinkME_Button pressed do (

Child_Obj.position.controller = position_script()
Child_Obj.position.controller.script = ("pos = getvert $" + (parentOBJ.name) + " " + (vert.text))
)
) -- Close Rollout


addRollout Vert_Linker MainFloater -- Add Rollout to the main floater

the POS scrip in on the object just need to read:
pos = getvert $object.name number
i get eveerything but a number

S-S
03-28-2008, 10:29 PM
HI lemasterjg

If i got it right (didn't read your script), you want to "link something to vertex" you mean you want to attach something to a vertex, and then even if the object itself deforms, linked object should follow?

If this is the case, you need to use attachment constaint, which works with faces, not vertices. Look into barycentric coordinates, and if i remember correctly, how to part of max script help has good tutorials on this subject.

Hope this helps.

lemasterjg
03-29-2008, 01:46 AM
yes that is exactly what i want to do, but its only one part of the script i plan on making. I also plan on adding a parralel to normals option to the script, somtimes you want an object to stay parralell and other time you don't as well as a pick vertex mode to the script. right now you have to add a select mesh modifier to the top of the stack witht he vertex desired. I want to make teh prosess more audomated by having a button that changes the parent mesh into a vertex select form without having to add a mesh modifier, if that makes any since.

thank you i will look into barycentric coordinates and how to understand it further.

S-S
03-29-2008, 09:53 AM
Maybe these can help you too:

myMesh = $.mesh -- Mesh property of object
myMesh.verts[1].pos -- Vert N position in object space

myFacesUsingThisVert = meshop.getFacesUsingVert myMesh 1 -- Returns bitarray of faces in object, if it's using this vert, it will be true

intersectRay -- With this you can shoot a ray using vector and a position to surface, and get faces it hit...

mariovergara1
03-29-2008, 05:51 PM
im trying to do the same kind of thing but instead of using just one vertex im trying to work with 4 vertexs, something like generative componets or paracloud but done in 3d max.
The idea is to create a component and attack it to a target surface....so if the surface is deformed the componet will adapt to the new configuration, considering it's base polygon
I first tryied using scatter, but this tool is very limited, since you can only distribute the componet in the target surface's in one vertex or to do it randomly...
then i tryied attach and then Paul Hormis's Attach By Local Z script, but still this relationship is based in only one point helper....so the component follows the target surface in its rotation and position parameters, but will not adapt to the surface's polygons new configuration....
please help!!!....is it possible?
thanks....

mariovergara1
03-29-2008, 05:52 PM
you can get the idea at
http://www.youtube.com/watch?v=cPEtj-UMxAs

lemasterjg
03-29-2008, 08:48 PM
mariovargara: if i understand correctly, you want to create a point in the middle of a face that stays in the exact center of the face, based of the relationship of the 4 corners? if thats what you are trying to do you would need to average to locations of all 4 vertices together to get on set of locations that is in the middle of the 4 vertices

S-S: thanks again, i'm looking into all of your suggestions and reading up and researching how they all work, am i correct in assuming the

myMesh = $.mesh -- Mesh property of object
myMesh.verts[1].pos -- Vert N position in object space

would give me the x,y,z of one particular vert? i also tried the attach function which to my knowledge is relatively new in 2008, Iíve switched over to maya a few years ago and forgot about max all together now i have to return. a position script only seems to update on playback, where as the attach function updates regardless, that I like so I will be using the attach constraint instead of a pos script.

Iíve decided to not attach an object directly, I will be making a dummy object as an intermediate between the vertex and the intended object. This will allow the child object to move freely but stay in the same relationship as the vertex. It just gives an animator a little more freedom and control.

S-S
03-29-2008, 09:28 PM
"would give me the x,y,z of one particular vert"

Yes

"I’ve decided to not attach an object directly, I will be making a dummy object as an intermediate between the vertex and the intended object"

Yes. That's what i have done too. It's definitely the best choice. You have an option to animate position and orientation of "attached" object too.

lemasterjg
03-29-2008, 11:38 PM
i've desided to rebuld fromt he ground up, and i want to use the attach constrain as the backbone instead of a pos script.

ok here is what i have so far:

MainFloater = newRolloutFloater "Link to Face" 250 315

rollout face_linker "Link to Face"(

Group "Pick Parent Face" (
pickButton parent_PkBtn "Pick Parent Object"
label Parent_lbl "Parent Object: (none selected)"
pickButton parentFace_PkBtn "Pick Face" enabled: off
label parentFace_lbl "Face Number: (none selected)"
)

Group "Creat Dummy-Child"(
label dummyname_lbl "Name of new Dummy-Child object"
edittext dummy_txt "" fieldWidth:200
button createDummy_btn "Create Dummy Child" enabled: on
)
Group "About"(
button help_btn "Help" pos:[70,250] width: 50
button about_btn "About" pos:[130,250] witdh: 50
)
--Button comamnds:

on parent_PkBtn picked obj do (
parentOBJ = obj
Parent_lbl.text = "Parent Object: " + parentOBJ.name
parentpicked = true
if parentpicked == true do parentFace_PkBtn.enabled = on
)

on parentFace_PkBtn picked obj do (
NEED HELP HERE
)

on createDummy_btn pressed do(
if dummy_txt != "" do (
new_obj = dummy ()
dummyname = dummy_txt.text + "_"
new_obj.name = (uniquename dummyname)
)
)
)
addrollout face_linker MainFloater


above where i have the "NEED HELP HERE" is where i'm stuck at, i was reading about the intersectray and i somewhat understand that but i'm suck at how to grab one face of the parent object, which is stored as parentOBJ. any thoughts?

Anubis
03-30-2008, 11:45 AM
In videogames we cannot use any deformers from DCC apps other than bones and morphs, so sometimes we 'bake' arbitrary deformations down to bones. An easy way of doing this is driving the attached object (bone) via a float script that uses getVert to grab the point position, or a 'when' (user driven), or a callback on time slider change. Is this kind of what you were referring to?

This is a simple way of getting even things like cloth (prebaked) into a game engine.

Anubis
03-30-2008, 01:26 PM
I quickly mocked this up (excuse my removing some of your UI). There are some little things I have learned over the years in here (like changing the button text in favor of a label, closing the window if open already, etc). I think Bobo did something like this his maxscript DVD, you could grab this if you were serious about making maxscript tools.

Caveats:
- polyop doesn't work on some geometry types, you should get the geo type before and use the appropriate method.
- as the faces deform i am not orienting the objects to the face, only positioning them, i think yo ucan see from this how you would orient them to the normal
- if you have any qs just ask as i didnt comment really, and i really don't know what i am doing (self taught), anyone feel free to school me on things below; I have a lot to learn about maxscript

http://chrisevans3d.com/temp/forums/linkToFace.png http://chrisevans3d.com/temp/forums/teapotLinked.gif


if MainFloater != undefined then (closerolloutfloater mainfloater)

MainFloater = newRolloutFloater "Link Tools" 180 182

rollout face_linker "Link to Face"
(
Group "Link to Faces"
(
button getFaceBtn "Get Selected Face(s)"
edittext dummyTxt "Name: " fieldWidth:100 text:"attDummy_"
button createDummiesBtn "Create attachDummies"
checkbox alignDummies "Align to face normal" checked:true
)
Group "Link to Vertices"
(
--we do this next
)

--locals
local theNode
local theFaces

--ui
on getFaceBtn pressed do
(
if selection.count != 1 then (return undefined)
theNode = $
theFaces = polyop.getFaceSelection theNode
getFaceBtn.text = ((theFaces as array).count as string + " Faces on " + theNode.name)
)

on createDummiesBtn pressed do
(
undo "createDummies" on
(
i=1
for face in theFaces do
(
theFace = ((polyop.getFaceSelection theNode as array)[i])
local new
if alignDummies.checked == true then
(
new = dummy name:(dummyTxt.text + i as string) position:(polyop.getFaceCenter theNode theFace) dir:(polyop.getFaceNormal theNode theFace)
)
else
(
new = dummy name:(dummyTxt.text + i as string) position:(polyop.getFaceCenter theNode theFace)
)
new.position.controller = position_script()
new.position.controller.script = ("polyop.getFaceCenter $'" + theNode.name +"' " + theFace as string)
i += 1
)
)
)
)
addrollout face_linker MainFloater

lemasterjg
03-30-2008, 04:34 PM
anubis: thank you, i have heard that game engines do no like basic deformers like bend and twist, but for now i'm not restricted by those conventions. is there any way to force the user to select one face in particular without the need of applying a mesh select modifier to the stack? all i need is the number of one face to use for the attach constraint.

Anubis
03-30-2008, 07:30 PM
Well, you can shoot a ray from the mouse cursor to the first polygon it hits, but wouldn't you want to be able to use multiple polygons? The only way to select polygons in max to my knowledge is in a subobj level or like meshselect.

Maybe someone here can show you an example of firing a ray perpendicular to the viewport from the mouse position and doing a ray/scene intersect on a polygon. I can't do this off the top of my head, but if no one chimes in can maybe do this tomorrow. Max has a lot of things like get node from hit, and pickpoint, and the like, but to my knowledge none return the polygon hit.

I used to live in Gainesville, and I am originally from Florida.

lemasterjg
03-30-2008, 07:32 PM
Iíve solved my problem about selecting a face, the script temporarily adds the mesh select modifier to the modify stack, and removes the modifier after the face is obtained. The only part now is to set up the attach constraint to the new dummy object by using the parentOBJ and the paretnFace variables that have the object and face sorted in them.

My only problem now is that the maxscript listener doesnít give me any clue as to how to add or manipulate the attach constraint, anyone know how?

updated Code:

rollout face_linker "Link to Face"(

Group "Pick Parent Face" (
pickButton parent_PkBtn "Pick Parent Object"
label Parent_lbl "Parent Object: (none selected)"
label getface_lbl ""
Button parentFace_Btn "Grab Face" enabled: off
label parentFace_lbl "Face Number: (none selected)"
)
Group "Creat Dummy-Child"(
label dummyname_lbl "Name of new Dummy-Child object"
edittext dummy_txt "" fieldWidth:200
button createDummy_btn "Create Dummy Child" enabled: off
)
Group "About"(
button help_btn "Help" pos:[70,275] width: 50
button about_btn "About" pos:[130,275] witdh: 50
)

--Button comamnds:

on parent_PkBtn picked obj do (
parentOBJ = obj
Parent_lbl.text = "Parent Object: " + parentOBJ.name
select = parentOBJ
modPanel.addModToSelection (mesh_select ()) ui:off
subobjectLevel = 3
getface_lbl.text = "select a face, then press 'Grab Face'"
parentpicked = true
if parentpicked == true do parentFace_Btn.enabled = on
)

on parentFace_Btn pressed do (
select = parentOBJ
parentFace = (getFaceSelection $) as array
if parentFace.count > 0 do (
facenum = (parentFace)[1]
parentFace = (facenum as string)
parentFace_lbl.text = "Face Number: "+ parentFace
)
subobjectLevel = 0
deleteModifier $ 1
facepicked = true
if facepicked == true do createDummy_btn.enabled = on
)

on createDummy_btn pressed do(
if dummy_txt != "" do (
new_obj = dummy ()

dummyname = dummy_txt.text + "_"
new_obj.name = (uniquename dummyname)
)
)
)
if MainFloater != undefined do(
closerolloutfloater MainFloater
)
MainFloater = newRolloutFloater "Link to Face" 250 350
addrollout face_linker MainFloater

lemasterjg
03-30-2008, 07:34 PM
lol thanks Anubis, i actually went the rout of mesh select, but i also remove the mesh select after the script is done, i posed up an update like 2 minutes after your last coment

Anubis
03-30-2008, 07:40 PM
Have you used an attachment constraint? I have always felt they were hard to get right; took manual setup. Did you see how that position script was setup in the example above, or is there a reason you would want to use an attachment over that route?

lemasterjg
03-30-2008, 08:02 PM
the reason i would like to use the attach constraint VS a position script is the feed back. a position script just updates when the time line is being played where as the attach constraint updates continually. the fact the the attach constraint it a little hassle to deal with makes this script even more useful.

the values that need to change are:
http://www.3d-insights.com/attachchanges.jpg

the changes to A and B center the pivot point to the selected face of the parent object. by turning Position XYZ from 100 to 0 stops teh child object form averaging between the two and uses only the attached constrain as its position and orientation.

but really the main reason is the updating of the position, i'd prefer it to be updated on the fly VS during timeline playback only.

mariovergara1
04-01-2008, 03:57 PM
lemasterjg...
sorry for taking so long to answer...been kind of busy...
i think i did not explain the problem correctly...
what i would like to do is to attach a mesh to a target surface in 4 points...
my guess is that the mesh should be inside a cage, so the base of the cage is attached to the target surfaces polygon.
so when the surface is deformed the mesh components is deformed too...this is something paracloud or generative components is able to do....the thing is that i would like to do it in max...
thanks for you reply

JHN
04-02-2008, 08:12 AM
Maybe I understand it wrong, but couldn't you do it with a skinwrap modifier?

-Johan

lemasterjg
04-03-2008, 07:52 PM
FINISHED!!

thanks to the discreet forums and the following web links i was able to finish my first script, some people have suggested intersect ray but i still do not have a good grasp of how to use it. if someone knows of a tutorial or an example script that uses intersect ray to select a face, please let me know.

http://www.kxcad.net/autodesk/Autodesk_MAXScript_Reference_9/Attachment_PositionController.htm
http://www.kxcad.net/autodesk/Autodesk_MAXScript_Reference_9/Attachment_Controller_Keys.htm

I still need to update my website and add a download and script section but Iím also working on a new Flash version which i hope to have a beta up within the next month, until then there is no direct link besides this one

finished Linked to Face script (http://forums.cgsociety.org/www.3d-insights.com/scripts/linktoface.ms)

Right now this scrip just creates a dummy that is attached to a surface and you simply link what you want to follow to the dummy.

mariovergara1: the original link that you gave really didn't give too much of an example of what you were saying, is there another example of what you are looking for?

S-S
04-03-2008, 08:21 PM
Here's short info on how to use intersect ray, which i wrote:

http://forums.cgsociety.org/showthread.php?f=54&t=616397

But if you want to get also face you hit, use intersectRayEx.

It returns an array of values, of them is face number it hit. I think i suggested using intersectray, but maybe i should have suggested intersectRayEx in the first place, now that i think of it. Give it a try! You can find info on manual too by searching for intersectRayEx.

CGTalk Moderation
04-03-2008, 08:21 PM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.