Home Technical Talk

3DS Max: UV Script to weld Overlapping vertices.

polycounter lvl 18
Offline / Send Message
oXYnary polycounter lvl 18
Remember when Max used to allow you to weld vertices that were on top of one another? So if you had a mirror part, you could weld the mirrors vertices on top of the otherside versus just having the vertices in the same place.

Why you ask? Because when I drag things around or use the packing ability in max, it just makes the mirrored pieces have their own area. In the older versions with them attached to one another, it would keep them together being moved around without click dragging.

If not, does Ipackthat have something like this?

Replies

  • [PB]Snoelk
    Options
    Offline / Send Message
    [PB]Snoelk polycounter lvl 7
    Irs an import option inside IPackThat. It will detect such overlaps and treat them as one uv cluster. It also detect offseted uv islands and use them as one cluster either. On export they will be shifted back again
  • oXYnary
    Options
    Offline / Send Message
    oXYnary polycounter lvl 18
    Guess I better get it then. :D
  • Synaesthesia
    Options
    Offline / Send Message
    Synaesthesia polycounter
    Apologies for the bump.

    really want this feature back, even in script form. IPackThat is great for the end-packing but I want to be able to relax verts and rescale and all that other fun stuff without worrying about my overlaps getting separated while doing so.

    Is anyone able to create a script for this purpose?
  • PolyHertz
    Options
    Offline / Send Message
    PolyHertz polycount lvl 666
    It can easily be done as a script (or at least synchronizing the vert positions can be). The problem is processing the data quickly. Maxscript is not a fast language, and iterating over and matching the positions of thousands / tens of thousands of vertices could take a long time.

    Anyhow, here's a simple/unoptimized script that'll work on a single low-poly stack of UV islands at a time:
    try(destroyDialog uvwSync)catch()
    rollout uvwSync "uvwSync" width:170 height:110 (
    button get_uvwIslandsA "Set UVW Stack" pos:[11,10] width:150 height:25
    button get_uvwIslandsB "Set Main UVW Island" pos:[11,40] width:150 height:25
    button set_uvwIslands "Sync UVW Stack" pos:[11,70] width:150 height:25

    local vrtMultiArray = #()
    local vrtLinked = #()
    fn switchSubMode = (
    (modpanel.getCurrentObject()).faceToVertSelect()
    return ((modpanel.getCurrentObject()).getSelectedVertices())
    )

    --Get all verts, and their positions, for all islands in stack.
    on get_uvwIslandsA pressed do (
    vrtMultiArray = #()
    if (classOf (modpanel.getCurrentObject()) == Unwrap_UVW) do (
    allVrts = #()
    if subObjectLevel == 3 then ( allVrts = switchSubMode() )
    else if subObjectLevel == 2 then ( allVrts = switchSubMode() )
    else if subObjectLevel == 1 do ( allVrts = (modpanel.getCurrentObject()).getSelectedVertices() )

    if allVrts.count != 0 do (
    --Get all their positions
    for vrtIndex in allVrts do (
    curVrtPos = (modpanel.getCurrentObject()).getVertexPosition 0 vrtIndex
    append vrtMultiArray #(vrtIndex, curVrtPos)
    )
    )
    )
    )
    --Get the verts for the island the user will be modifying.
    on get_uvwIslandsB pressed do (
    vrtLinked = #()
    if (classOf (modpanel.getCurrentObject()) == Unwrap_UVW) and (vrtMultiArray.count != 0) do (
    tmpVrts = #()
    if subObjectLevel == 3 then ( tmpVrts = switchSubMode() )
    else if subObjectLevel == 2 then ( tmpVrts = switchSubMode() )
    else if subObjectLevel == 1 do ( tmpVrts = (modpanel.getCurrentObject()).getSelectedVertices() )

    --Split main array into 'main island' and 'sub-islands'.
    mainIsland = #()
    subIslands = #()
    for node in vrtMultiArray do (
    if (findItem tmpVrts node[1] != 0) then (append mainIsland node)
    else (append subIslands node)
    )

    --Determine which verts positions are linked to each other.
    for mvNode in mainIsland do (
    local tmpCol = for evNode in subIslands where evNode[2] == mvNode[2] collect #(mvNode[1], evNode[1])
    join vrtLinked tmpCol
    )
    )
    )

    on set_uvwIslands pressed do (
    undo "Sync UVW Stack" on (
    for node in vrtLinked do (
    curVrtPos = (modpanel.getCurrentObject()).getVertexPosition 0 node[1]
    (modpanel.getCurrentObject()).SetVertexPosition 0 node[2] curVrtPos
    )
    )
    )
    )
    createDialog uvwSync

    How to use it;
    1. In any element mode, select the entire UV island stack you want to work with, then press the first button.
    2. Select a single element from the stack, move it somewhere else, then with it still selected press the second button. (This is the part that takes the longest to process.)
    3. Now the UV island you moved elsewhere can be modified however you like. Just press the 3rd button whenever you want the rest of the elements in the stack to snap to it.

    Be sure that the verts are perfectly on top of one another before doing any of this, else the script wont know that their positions are supposed to be linked. Also, I'd highly recommend not using this on any element over maybe 5000 tris, as the tri count increases the number of loops done exponentially (and thus also the processing time).


  • Synaesthesia
    Options
    Offline / Send Message
    Synaesthesia polycounter
    I can only sit in awe of the skill required to code anything useful. I'll try that out tomorrow. Thank you so much!
  • Synaesthesia
    Options
    Offline / Send Message
    Synaesthesia polycounter
    So I'm working on a jet right now. It's got windows cut-in with some depth. I want the windows to sit in the holes in the fuselage instead of being offset somewhere else on the map due to LOD constraints. The script works beautifully - the only thing it isn't doing is welding the windows to the fuselage in the UV editor. It will snap the UV shells to their correct position but they'll stay as separate elements. Am I doing anything wrong here?
  • PolyHertz
    Options
    Offline / Send Message
    PolyHertz polycount lvl 666
    Yea it isn't designed to weld anything, just update vert positions. Sorry, I should have explained it better before.
    Welding stacked objects isn't possible anymore, even as a script. In fact, it seems AD removed all references to it in the documents several years ago (and they only host documents online as far back as Max 2012), so even if it was possible to do using depreciated functions there's no way to look them up.
    The script is an attempt at doing the next best thing.
  • Synaesthesia
    Options
    Offline / Send Message
    Synaesthesia polycounter
    Well, it's certainly the next best thing, so thank you for creating it! :)

    I'm quite surprised that they would completely remove that ability. Fun fact, though, I can get stacked welded shells occasionally from kicking something back from IPackThat. I'm not sure what causes that behavior, but it's apparently still possible outside of Max so long as you're able to bring the file back in.
  • cptSwing
    Options
    Offline / Send Message
    cptSwing polycounter lvl 11
    Have you tried using groups in Max's UV editor?
  • Synaesthesia
    Options
    Offline / Send Message
    Synaesthesia polycounter
    That unfortunately does not work with tools like Polyunwrapper 4, and it won't work with relaxing IIRC.
  • cptSwing
    Options
    Offline / Send Message
    cptSwing polycounter lvl 11
    Yeah, tis true. Not happy with their implementation either (for being a good idea in theory). Though I'm sure the creator of Polyunwrapper could probably start supporting them at some point, if enough interest is shown.
Sign In or Register to comment.