Inside Sabertooth
Learn how Sabertooth uses 3ds Max to create 3D interactive projects, including HBO Go’s Game of Thrones interactive experience
  • 1/3
You are here: Forum Home / Autodesk 3ds® Max® / MaxScript / FLIP UV across several files - Solution included
  RSS 2.0 ATOM  

FLIP UV across several files - Solution included
Rate this thread
 
63102
 
Permlink of this thread  
avatar
  • tomacmuni
  • Posted: 26 December 2011 10:38 PM
  • Total Posts: 35
  • Joined: 29 August 2006 08:21 AM

Edit: The solution is down the page.

Hello,

I am no maxscripter, but I captured this from the listener and it works if I paste in each command one by one.  I’m wondering if someone can give a demo of how to turn this into proper automation so all I need to do is click-ez a button and then choose the file(s) and set the output files.  For example, this would be great for processing a bunch of OBJs exported from ZBrush without FlipV set for their normal map extraction.

One click Flip UV Vertically

max file import
//   - pause so the user has to choose the file, though a batch would be even better

//assign an UnwrapUVW modifier
modPanel.addModToSelection (Unwrap_UVW ()) ui:on

//go to face mode 
subobjectLevel 3

//select all the faces 
max select all
 
// OPEN EDITOR (how automatically to do it, I press the button for this)?

//Flip 'em
actionMan.executeAction 2077580866 "40039"  -- All CommandsFlip Vertical

//export the result 
max file export selected
//  - pause so the user has to choose the file

//clear the selected object from the scene
max delete


Replies: 1
/img/forum/dark/default_avatar.png

Moved from Max2012. You are likely to get better anwers by posting in the most appropriate forum.

Author: Steve_Curley

Replied: 27 December 2011 02:17 AM  
avatar
  • Anubis
  • Posted: 27 December 2011 03:29 PM

Keep in mind that i write all this by memory ;)

importFile (GetDir #import + "\\cool.3ds") #noPrompt

mUnv Unwrap_UVW()
obj  selection[1]

addModifier obj mUnv
max modify mode

mUnv
.unwrap2.selectFaces #{1..obj.numFaces}
mUnv.edit() -- open the uvw editor
mUnv
.unwrap.flipVertical()

exportFile (GetDir #export + "\\cool.3ds") #noPrompt selectedOnly:on


Max 9 through 2009, XP-Pro x64 SP2
ASUS EAH3450 Series (Driver 8.470).
Core 2 Duo E8400 3GHz, 4Gb Ram, DX9.0c.

Replies: 0
avatar
  • tomacmuni
  • Posted: 27 December 2011 08:36 PM

What is “\\cool.3ds” to be replaced with?

Is this a folder where I keep my FBX models?
Do I specify an actual file?

Tom



Replies: 1
/img/forum/dark/default_avatar.png

You not mention anything about the file format you intend to import or export.
The “cool” is just random name, the “3ds” - i think you know.
So yep, replace that with actual file name and file extension (like “\\example.fbx")

Author: Anubis

Replied: 27 December 2011 11:09 PM  
avatar
  • Anubis
  • Posted: 28 December 2011 12:02 AM

Just in case you wonder about GetDir() function, its just for the example.
So the script above will look at Max import/export folder.
If your models are in other location you s’d use the full path.
Example:

impDir "D:\\Import\\"
expDir "F:\\Export\\"

impFbx GetFiles (impDir "*.fbx")
fCount impFbx.count

if fCount == 0 then
    messageBox 
"No FBX files in that location!" title:"?..."
else
(
    
expFbx = for file in impFbx collect (
        
expDir + (filenameFromPath file)
    )
    
    for 
1 to fCount do
    (
        
importFile impFbx[f] #noPrompt

        
...

        
exportFile expFbx[f] #noPrompt selectedOnly:on
    
)
)

And if the paths s’d not be hard-coded, i.e. need user interaction then
use getSavePath() function to popup browse for folder dialog.



Max 9 through 2009, XP-Pro x64 SP2
ASUS EAH3450 Series (Driver 8.470).
Core 2 Duo E8400 3GHz, 4Gb Ram, DX9.0c.

Replies: 0
avatar
  • tomacmuni
  • Posted: 29 December 2011 01:26 AM

Hi

I tried your script, and it processed through but only output OBJs and the UVs didn’t flip.

I tried tinkering with it - here’s what I have currently, but now there is no output file.
The vertex selection is flipping vertically, which is great to see after a couple of hours. ;)

The final model remains in vertex mode in Unwrap UVW modifier editing ... this shouldn’t make a difference to file export of one .FBX but it might effect a list of them ?
Maybe it doesn’t matter, but I notice the Unwrap UVW modifier is applied as an instance.

impDir "C:\\UV FLIP INPUT\\"
expDir "C:\\UV FLIP OUTPUT\\"

impObj GetFiles (impDir "*.obj")
fCount impobj.count
MyUV 
unwrap_uvw()

if 
fCount == 0 then
    messageBox 
"No OBJ files in that location!" title:"?..."
else
(
    
expFbx = for file in impObj collect (
        
expDir + (filenameFromPath file)
    )

    for 
1 to fCount do
    (
        
importFile impObj[f] #noPrompt

MyObj = $

addmodifier MyObj MyUV 
UVertCount 
MyUV.NumberVertices() 
max modify mode
MyUV
.edit() -- open the uvw editor
MyUV
.unwrap2.setTVSubObjectMode 1
-- MyUV.unwrap2.selectFaces #{1..obj.numFaces}
-- MyUV.unwrap2.selectVerticesByNode #{1..obj.numFaces}
MyUV.unwrap6.selectVerticesByNode #{1..UVertCount} $;
MyUV.unwrap.mirrorv()
-- 
MyUV.unwrap.flipVertical()

exportFile expFbx[f] #noPrompt using:FBXEXP selectedOnly:true 

    
)
)


Replies: 0
avatar
  • Anubis
  • Posted: 29 December 2011 05:03 AM

Well, as i said don’t take my examples as complete help as i wrote this by memory. Maybe after the holidays me or someone else w’d help better but for now i just dig into online help to remember correct syntax of concrete functions :) so seems to me that flipVertical() and mirrorv() is not the same but if mirrorv() works fine then you’re step forward ;)

As for the file format you still confusing me. You already analyse each line of my code, right? For ex. “impObj = GetFiles (impDir + “*.obj")" will collect all OBJ files, so the script will import OBJ files. And what this line do - “expFbx = for file in impObj collect (expDir + (filenameFromPath file))” ?… 1st see in the help filenameFromPath() - its get the file name + it extension. In other words, the script will export the file using exact the same name and of’cuz the same file format, only the directory/folder is different. So if you need to import OBJ but to export to FBX then use getFilenameFile() function (check the help for details). It get only the name w/o extension. So building the array of names for the export w’d become:

/* old */
expFbx = for file in impObj collect (
    
expDir + (filenameFromPath file)
)

/ * new */
expFbx = for file in impObj collect (
    
expDir + (getFilenameFile file) + ".fbx"
)

As for the modifier applied as instance, look at this example:

bend() -- create Bend modifier
boxes 
= for 1 to 10 collect Box() -- create 10 boxes

for obj in boxes do addModifier obj b

-- above is the same as this:
addModifier boxes b

/*
   i.e. both add Bend as instance
   to add new modifier on each box
   should create new modifier inside the loop,
   i.e next will add unique modifier to each box:
*/
for obj in boxes do addModifier obj (bend())

Or another way, in case you create the modifier once and out of the loop is to use copy() function inside the loop like:

addModifier MyObj (copy MyUV)

So lets hope this part is clear.
Still remains one hard question - closing the UV-editor.

No built-in function for that purpose (unfortunately) and can ‘hack’ this with UIAccessor interface (a bit advanced feature) using “UIAccessor.CloseDialog hwnd”, but i can’t help on this one w/o Max at hand. You can search in this forum for UIAccessor and will find a few useful topics about.

Good luck! ;)



Max 9 through 2009, XP-Pro x64 SP2
ASUS EAH3450 Series (Driver 8.470).
Core 2 Duo E8400 3GHz, 4Gb Ram, DX9.0c.

Replies: 0
avatar
  • Anubis
  • Posted: 29 December 2011 06:17 AM

Ok, can’t guarantee this will work but here is
what i can help at the moment about closing the uvw-editor:

-- 1st way to find the HWND:
hwnd windows.getChildHWND 0 "Edit UVWs" parent:#max

-- and close using Windows structure:
if 
hwnd != undefined do -- if foundsend close message
    windows
.sendMessage hwnd[1] 0x0010 0 0

-- 2nd way to find the HWND:
hwnd = for win in (windows.getChildrenHWND #max) where \
    
win[5] == "Edit UVWs" collect win[1]

-- and close using UIAccessor:
if 
hwnd[1] != undefined do -- if foundsend close message
    UIAccessor
.CloseDialog hwnd[1]


Max 9 through 2009, XP-Pro x64 SP2
ASUS EAH3450 Series (Driver 8.470).
Core 2 Duo E8400 3GHz, 4Gb Ram, DX9.0c.

Replies: 0
avatar
  • tomacmuni
  • Posted: 29 December 2011 03:15 PM

Hi - I read your reply, and it’s great.  I was admiring the extent of help given, especially if it’s from out of your head.  Very educational for me.

The FBX output change you suggested for the file name + .fbx extension worked.

For the rest, closing the unwrap UV I had an idea to try another way, which is much simpler.  Just set the object’s modifier stack to the base level, then delete the current object.  It is in the final two lines.  Happy to say it works exactly as intended.

So here is the final working script:

-- UVFLIP BATCH by Panayot Karabakalov (virtuoso) and Tom Mooney (conductor).
-- 
Set up folders as indicated below and dump texture mapped OBJs into the input folder.
-- 
Load up an empty 3ds max scene and run the script.  Pick up FBX results in output folder.

impDir "C:\\UV FLIP INPUT\\"
expDir "C:\\UV FLIP OUTPUT\\"

impObj GetFiles (impDir "*.obj")
fCount impobj.count
MyUV 
unwrap_uvw()

if 
fCount == 0 then
    messageBox 
"No OBJ files in that location!" title:"?..."
else
(
    
expFbx = for file in impObj collect (
    
expDir + (getFilenameFile file) + ".fbx"
    
)

    for 
1 to fCount do
    (
        
importFile impObj[f] #noPrompt

MyObj = $

-- If 
you just want to convert OBJ to FBX in a batch without Flipping UVscut this section.
addmodifier MyObj MyUV 
UVertCount 
MyUV.NumberVertices() 
max modify mode
MyUV
.edit() -- open the uvw editor
MyUV
.unwrap2.setTVSubObjectMode 1
MyUV
.unwrap6.selectVerticesByNode #{1..UVertCount} $;
MyUV.unwrap.mirrorv()
-- 
End of section to cut.

exportFile expFbx[f] #noPrompt selectedOnly:on
modPanel.setCurrentObject $.baseObject
max delete
    
)
)


Replies: 0
avatar
  • Anubis
  • Posted: 30 December 2011 12:14 AM

Cool, glad to see that i was helpful to you :)
Honestly, this is not beginners level script,
in such task s’d take care for many thinks and
I hope you’ll appreciate a few extra notes.

1. Most importers keep new objects selected, but thats not true for FBX. So if you one day decide to import FBX, that script w’d not works. In this case you s’d operate on Objects collection instead of Selection.

2. Currently you get imported object with $ sign and thats OK for OBJ format as it import 1 object, but if they are many (in FBX for ex.) then your modifier w’d be applied on them as instance. In this case you’ll need additional iteration inside the Selection, i.e. something like:

-----MyObj = $ -- hiding this
max modify mode
theObjs 
selection as array -- get them to variable

for obj in theObjs do
(
    
MyUV unwrap_uvw()
    
addModifier obj MyUV
    Select obj 
--------- select one at a time

    MyUV
.edit()
    
MyUV.unwrap2.setTVSubObjectMode 1
    MyUV
.unwrap6.selectVerticesByNode #{1..UVertCount} obj
    
MyUV.unwrap.mirrorv()
    
modPanel.setCurrentObject obj.baseObject
)

Select theObjs ---------
exportFile expFbx[f] #noPrompt selectedOnly:on
max delete

Cheers!



Max 9 through 2009, XP-Pro x64 SP2
ASUS EAH3450 Series (Driver 8.470).
Core 2 Duo E8400 3GHz, 4Gb Ram, DX9.0c.

Replies: 0