|
created misc. maxscript UV scripts/tools
on 01-27-2009 03:05 AM
this thread has become bloody big
What it is all about?
A plugin or script collection if you will that boosts the 3dsmax tasks of UV Unwrapping and Texture related stuff. This includes handy align, relax and transformation tools for UV editing but also nifty single button scripts for baking AO, Lighttracer maps or blockout maps directly to your clipboard.
All of that super easy to install (just drag the download file into the max viewport),- and if you are interested in the scripting part or contribution you can look into the code as well.
For a full overview head over to:
http://www.renderhjs.net/textools
it has lots of GIF animations of each tool explaining them without the need of much text- though some of the text might explain some more background info for each tool. Here is a excerpt of some of the things you can do:

------------------------------------------------------
and here is the original first message:
just a thread to dumb my UV-related scripts into, some of these scripts will be eventually ported in a GUI so they are more in a usefull collection.
some of my goals:
- should run in max9+
- no xtra plugins required
- reduce tasks that are usually required
1.) render UV- template to clipboard
(does not require the avg_dlx.dlx extention!!! nor any other third party xtra plugin)

lets you render a UV-template directly into the windows clipboard so you can paste it directly into photoshop. Nor Framebuffer is displayed,- you dont even need to open the UV-editor- it requires though a UV-unwrap modifier.
Code:
--render uv to clipboard
_size = 512;
$.modifiers[#unwrap_uvw].renderuv_width = _size;
$.modifiers[#unwrap_uvw].renderuv_height = _size;
$.modifiers[#unwrap_uvw].renderuv_fillmode = 0;--solid
$.modifiers[#unwrap_uvw].renderuv_seamColor = color 255 255 255;
$.modifiers[#unwrap_uvw].renderuv_showframebuffer = false;
clipboardClass = dotNetClass "System.Windows.Forms.Clipboard" --create a Clipboard dotNetClass
theFileName = GetDir #image + "_renderToClipboard.bmp" --define a temp.file name
$.modifiers[#unwrap_uvw].unwrap5.renderUV theFileName;--save UV layout to the temp folder
theImage = dotNetClass "System.Drawing.Image" --create an Image dotNetClass
theBitmap = theImage.FromFile theFileName --get the saved image from file as bitmap
clipboardClass.setImage theBitmap --copy the image to clipboard
theBitmap.Dispose() --release the bitmap
deleteFile theFileName --delete the temp. file
clipboardClass.ContainsImage() --return true if the clipboard contains image
$.modifiers[#unwrap_uvw].renderuv_showframebuffer = true;--reset defaults
at first I found this great thread:
http://forums.cgsociety.org/showthread.php?t=677106
but its to much of a hassle and it requires some extra steps like photopshop scripts to be manually activated. With my script now all I need to do in photoshop once pasted is to select either a color range or use the magic wad or invert and set the layer mode to multiply.
Used this reference for the setClipboard part:
http://www.scriptspot.com/bobo/mxs9/...Clipboard.html
comming next is a align tool that aligns vertex UV`s on a real line and not like all the lazy scripts out there only horizontal or vertical. A angle snap determinces if they should be aligned vertical or horizontal e.g if all the points in a line are +- 5° apart from 90°. It should help up aligning verts from the faces of block type objects.
Last edited by renderhjs; 10-11-2009 at 12:14 PM..
|
, card carrying polycounter,
2,369 Posts,
Join Date Mar 2008,
Location Sydney Australia
|
I have some good progress on my vertice align script
it works like this, you select your verts and hit the script, it automaticly detects the flow and will align the verts between the 2 end points on that line.
example usage:

or

what I still plan is a angle snap value (e.g within 2° or 5°) where it detects to snap to either 45° angles or most common 90° angles which would be the same as the rest of the scripts that can only snap vertical or horizontal.
this is how it works:
draft script (requires a uv-unwrap modifier a opened UV-editor + at least 3 selected UV-verts
Code:
--uv-align script draft
function align_uv_verts =(
_uvBase = $.modifiers[#unwrap_uvw];
_uv1 = $.modifiers[#unwrap_uvw].unwrap;
_uv5 = $.modifiers[#unwrap_uvw].unwrap5;
_array = _uv1.getSelectedVertices();
_selection = #();--new array
_maxX;_maxY;_minX;_minY;
_nr=1;
for i in _array do (
local _pt = _uvBase.getVertexPosition 1 i;
if (_nr > 1) then(
local _pt2 = _uvBase.getVertexPosition 1 _maxX;
if (_pt.x > _pt2.x)then(
_maxX = i;
)
_pt2 = _uvBase.getVertexPosition 1 _minX;
if (_pt.x < _pt2.x)then(
_minX = i;
)
_pt2 = _uvBase.getVertexPosition 1 _maxY;
if (_pt.y > _pt2.y)then(
_maxY = i;
)
_pt2 = _uvBase.getVertexPosition 1 _minY;
if (_pt.y < _pt2.y)then(
_minY = i;
)
)else(
_maxX = i;
_maxY = i;
_minX = i;
_minY = i;
)
_selection[_nr] = i;
_nr+=1;
)
--determine if horizontal or vertical flow
local _a = _uvBase.getVertexPosition 1 _minX;
local _b = _uvBase.getVertexPosition 1 _maxX;
local _w = (_b.x - _a.x);
_a = _uvBase.getVertexPosition 1 _minY;
_b = _uvBase.getVertexPosition 1 _maxY;
local _h = (_b.y - _a.y);
local A=1;
local B=1;
_sel = #{};
if (_w > _h )then(
A = _minX;
B = _maxX;
)else(
A = _minY;
B = _maxY;
)
_sel = #{};
_sel[A] = true;
_sel[B] = true;
_uv1.selectVertices _sel;
if (_selection.count > 2)then(
local ptA = _uvBase.getVertexPosition 1 A;
local ptB = _uvBase.getVertexPosition 1 B;
for i = 1 to _selection.count do(
if (_selection[i] != A and _selection[i] != B)then(
local _pt = _uvBase.getVertexPosition 1 _selection[i];
if(_w > _h )then(
local _m = (ptB.y - ptA.y) / (ptB.x - ptA.x);
local _x = _pt.x - ptA.x;
_pt.y = _x * _m + ptA.y;
)else(
local _m = (ptB.x - ptA.x) / (ptB.y - ptA.y);
local _y = _pt.y - ptA.y;
_pt.x = _y * _m + ptA.x;
)
_uvBase.SetVertexPosition 1 _selection[i] _pt;
)
)
)else(
print("select at least 3 vertecies!");
)
)
align_uv_verts();
|
, card carrying polycounter,
2,369 Posts,
Join Date Mar 2008,
Location Sydney Australia
|
problem with the first one is its restricted to one resolution only unless you make a macro for each resolution you use.
2nd one looks interesting but I dont see that much use diagonally aligning things, at least I've never personally felt the need to do it for any reason
but thanks for sharing, I'll keep an eye on this thread!
|
, polycounter,
1,035 Posts,
Join Date Nov 2007,
Location UK
|
@Yozora:
1st one will most likely end up in a rollout dialogue with a dropdown menu and or input text box.
Alternativly one could predict the size for example based on the associated material and its difuse texture bitmap size - if one is applied. Or the units of the 3d poly and some math guessing the size where 1 max units in 3d space is 1 pixel or something like that. Or... a popup window appears asking you to verify the resolution - that should be possible with a macroscript
2nd script:
One main Idea was not to align vertecies diagonally but foremost having just ONE simple button that alligns things for you- like a smart button that detects automaticly if things should be aligned horizontal, vertical diagonal or snapped to the border. Depending on the vertex positions it will the automaticly determine the smartest move. To me its bothersome having 2 buttons to align horizontal and vertical,- it might be even the case that I want to align in 45°.
as for further ideas:
I am thinking of a distribute scripts that works similar to the align script as it ditributes evenly along a line in any direction- or perhaps ease to a line.
Another script I have in mind is to auto-rotate shells based on their z-axis flow or topXY alignment. I find myself often finding the right edges in the 3d view in order to know how to rotate certain islands and faces because I prefer not having flipped UV-layouts- or weired rotated ones. I think the easiest approach will be by selecting 1 edge and letting the script gess if its a side, bottom or top side on the 3d model and align the UV- shells occordingly.
yet another idea is to smart rotate shells because often my shells are +- 0.05 ° rotated and not perfectly aligned to the axis. This script should analyze the vert points and snap to the most matching 90° related vertexes. If it would go well it would simply align the rototation to the base axis in the UV view in the most suited manner.
another one:
render only selected faces/shells with a random block/face color to the clipboard. That way I could faster block out a mesh by its base elements. And quickly paste it in my existing photoshop texture.
|
, card carrying polycounter,
2,369 Posts,
Join Date Mar 2008,
Location Sydney Australia
|
Quote:
Originally Posted by renderhjs
some of my goals:
- should run in max9+
- no xtra plugins required
- reduce tasks that are usually required
|
I have to say your second goal is foolish. If you can leverage something, such as avg, or libraries you find on the net, you should, without a doubt. Otherwise you are duplicating code by writing it yourself, or copying and pasting (I'm not sure which is worse).
One of the greatest obstacles of tech art development is that there is no mentality or infrastructure for good tool distribution. Developers and scripters are both to blame- the first for not creating any good frameworks or systems in their programs, the second for not fostering a collaborative mentality even when there are some available.
Real programmers have long known the benefit of modular, reusable code, between individuals and companies both. One of the great benefits of .NET has been the utterly successful ability to share classes between users and languages, via things such as codeproject.
I'd urge you, and everyone else, to reconsider "no extra things required" as something good, and instead considering "leveraging other code but distributing it in a sensible way".
If you write your scripts in such a way as they are modular and reusable, I'm sure many, many people will have good use for your code and put it to many other tools and applications inside Max.
|
, polycounter,
926 Posts,
Join Date Jan 2007,
Location Austin, Texas
|
these look awesome, renderhjs. I'm looking forward to your progression
that's definitely true Rob, and I think in actual production where you have a little more control over who's using it that's stellar - but the majority of users for these free scripts probably don't know enough about it to put everything into place correctly.
So for them, the fewer pieces they have to worry about the better.
over all we'd probably be able to create way superior stuff, but that runs the risk of leaving some people behind - the people who know the least about the technical aspects. I think that'd be unfair because that might be the group that relies on them most.
But I'm teh noobzorz, so I don't mind being told I'm wrong.
the community scripts project you guys have been working towards sounds wonderous, btw 
|
, triangle,
429 Posts,
Join Date Mar 2006,
Location San Jose
|
ah if this can combine vertical and horizontal aligning into 1 button then it is indeed very useful!
I just tried it and I cant undo/redo once I've used it.... which pretty much makes it useless for now :/
|
, polycounter,
1,035 Posts,
Join Date Nov 2007,
Location UK
|
One thing I've been looking for is a script that takes an edge (or selection of verts) and rotates the entire uv-island so that this edge/selection is alligned flat on the horizontal or vertical axis. Does anyone know if that's possible?
|
, veteran polycounter,
2,617 Posts,
Join Date Oct 2004,
Location Amsterdam
|
@Rob Galanakis: my simple reason for that is that I have plenty of computers here on the University on which I am not allowed to copy any data in the 3dsmax directory.
The other reason is that I can go anytime with those xtras but:
- what happens if those plugins are not updated for a newer max relese?
- what if the download url should vanish
- what if autodesk no longer supports parts of it
...
surely someone like you is in a different position,- maybe I need to discover more advantages of others classes for now Id rather avoid them if possible.
|
, card carrying polycounter,
2,369 Posts,
Join Date Mar 2008,
Location Sydney Australia
|
ghostpainter bitches.
selected UVs straight into photoshop with 1 key press of F2.
its expensive though, especially since the only function i actually use is the send UVs into photoshop part, and select marked polygons in photoshop. plus its vector UVs.
Last edited by dejawolf; 01-28-2009 at 10:56 AM..
a picture says a thousand words.
|
, dedicated polycounter,
1,605 Posts,
Join Date Nov 2004,
Location Norway
|
btw something awesome i found out (and I think Per mentioned this too a while back) is that if you're using maxscript to physically set the position of a UV vertex, you will not get any undo info on that.
The only way I found to make it correctly behave with undo is put a relative move of 0,0,0 in before the actual setVertexPosition. Then the undo clause worked correctly.
Good idea to put the functionality for aligning all into one button.
I might take this idea for my UV Line Relax script so that it falls back to default align behaviour if it doesn't find a contiguous line to relax along.
|
, Administrator,
11,475 Posts,
Join Date Oct 2004,
Location London, UK
|
Quote:
Originally Posted by MoP
The only way I found to make it correctly behave with undo is put a relative move of 0,0,0 in before the actual setVertexPosition. Then the undo clause worked correctly.
|
Bless you MoP! I haven't tested it yet, but if it works I will put an animated gif of you in my sig and officially instate every january 28th as mopday
|
|
Here's what I had to hack in to get it working:
Code:
undo "Align V" on (
uv.unwrap2.MoveSelected [0.0,0.0,0.0]
uv.moveY mid
)
Where "mid" is the averaged value calculated from the selected verts' Y positions. If you try this undo clause without the MoveSelected command, Undo does nothing. Stupid Max.
You probably don't need the ".unwrap2" in there, I think you can just point it to your unwrap modifier object (in this case mine's called "uv" ).
|
, Administrator,
11,475 Posts,
Join Date Oct 2004,
Location London, UK
|
I figured it may be used to make UV stitch undoable, but no such luck
Code:
undo "Smart UV stitch" on
(
currObj.MoveSelected [0.0,0.0,0.0]
currObj.stitchVerts true 0.5
)
Any ideas?
|
|
Ouch heh, yeah that does something horrible... when I tried it stitching one selected vertex, on undo it created an extra floating UV at the original position but kept the face stitched... no idea what's going on there!
|
, Administrator,
11,475 Posts,
Join Date Oct 2004,
Location London, UK
|
Quote:
Originally Posted by Funky Bunnies
that's definitely true Rob, and I think in actual production where you have a little more control over who's using it that's stellar - but the majority of users for these free scripts probably don't know enough about it to put everything into place correctly.
So for them, the fewer pieces they have to worry about the better.
|
Yes but you are missing the point about framework and infrastructure. Good collaborative/sharing or distribution mechanisms do not exist. As long as you think there is no need for them they will not exist- this is an issue of us having to take the initiative. No one is going to build something there is no use for, and no one is going to support and improve it if it isn't used. If you are a scripter, you need to demand a collaborative and distribution infrastructure and help incubate what people are doing. These systems, when developed correctly, are only beneficial for the user.
It is very inconvenient to have to install a bunch of extra stuff to run a program. But few programs develop everything themselves, they have external libraries they depend on. The difference is, they are better about how they are distributed and they understand the need for them. We haven't figured out a distribution mechanism (part of this is because how our shitty scripting languages and programs work), but much of it, and what we can change, is the part about understanding the need for them. Once we understand and demand the need, we can develop the systems- and once the systems are developed it will be trivial/assumed/usual to distribute external code as part of a tool or app.
Quote:
|
Originally Posted by renderhjs
my simple reason for that is that I have plenty of computers here on the University on which I am not allowed to copy any data in the 3dsmax directory.
|
So what? That is an issue with how you are installing scripts, nothing more.
Quote:
The other reason is that I can go anytime with those xtras but:
- what happens if those plugins are not updated for a newer max relese?
|
Feel free to recompile them if they are plugins or rewrite them if they are scripts. But it is always better and faster to refactor someone else's working code than it is to write that code from scratch (and if you think it isn't always faster- unless the code is real shite which you shouldn't be using in the first place- then you haven't been developing enough, because it unequivocally and 100% is).
Quote:
|
- what if the download url should vanish
|
You are distributing the needed stuff with your script.
Quote:
|
- what if autodesk no longer supports parts of it
|
See response to your second point.
Quote:
|
surely someone like you is in a different position,- maybe I need to discover more advantages of others classes for now Id rather avoid them if possible.
|
No I'm not in a different position, at all. I have a different perspective and I probably need to explain better, but my position is the same.
So I have this program, called 'ProgramX' that installs to 'C  \Program Files\\ProgramX\\'. Inside I have something like 'ProgramX.exe', 'dx9.dll', 'openal.dll', 'Ionic.Zip.Utils.dll', 'DesktopDecorator.dll'. Each of these dll's are essentially someone else's code you are using.
dx9.dll- You are using DirectX, which is an API (key word is 'interface')
openal.dll- A sound library, instead of having to write all your sound stuff in C++, you can just call stuff from openal, it is also an API.
Ionic.Zip.Utils.dll and DesktopDecorator.dll- These are two C# classes. The first is for dealing with zip files, the second is for changing wallpaper.
You could, of course, write all of this stuff from scratch (assuming you had the requisite skills). But programmers don't, why? Because they have a rich library of available, good (sometimes not so good, in the case of the last dll) code they can reuse. That they don't have to update. That they don't have to maintain. But they still have the ability to extend classes and fix bugs (this is one of the infrastructure issues in our scripting languages we cannot do easily right now).
So for example I'll take chuggnut's functionally-excellent but structurally-shit UV plugin (I dont' blame him, this was made years ago when this sort of scripting was the norm and pretty usual). Great, it works, end of story, right? No. Because if the tool were written in a sensible way, the user experience wouldn't be the end of the story. Other devs would be able to take the methods and utilities chuggnut wrote and do tons of other things with them. They'd also be much better able to expand/replace/enhance functionality within the tool itself.
You should be able to use an existing script library, expand it, and others should be able to take yours (depending on license, of course, which if anything but open-source is selfish) and expand and distribute it. To the user, they are just downloading and installing stuff as usual. The problem is with few people writing extensible scripts and libraries, and fewer people participating in the discussion about how to best distribute and what systems are needed, there are still substantial issues to be solved. But simply giving up is no way to behave, as there is a solution there if we discuss and collaborate and we all acknowledge the end result will be exponentially better than what we put in (which is the entire idea behind developing tools, isn't it?).
There was something else I wanted to say but my brother called and I can't catch my train of thought a half hour later. I hope that explains my perspective more clearly.
|
, polycounter,
926 Posts,
Join Date Jan 2007,
Location Austin, Texas
|
created count black pixel
on 01-30-2009 01:52 PM
I used your renderUV script and mixed with one of mine.
Now the script count black pixel on the uv map, and drop a percentage of "wast uv space" depending on the wanted size of the map.
result just below
my code is perhaps not very optimised, but its working well on editpoly object
just select an editObj and run the script
Code:
(
rollout SizeMapDialog "Map Size"
(
editText sixze "X :" pos:[15,24] width:88 height:20
editText siyze "Y :" pos:[110,24] width:88 height:20
button btnok "OK" pos:[218,24] width:50 height:20
groupBox grp1 "Size Map" pos:[8,5] width:280 height:51
on btnok pressed do
(
destroyDialog SizeMapDialog
st = timestamp()
a = 0
pxBlack = 0
stat = 0
modPanel.addModToSelection (Unwrap_UVW ()) ui:on
--------------------------
$.modifiers[#unwrap_uvw].renderuv_width = sixze.text as integer;
$.modifiers[#unwrap_uvw].renderuv_height = siyze.text as integer;
$.modifiers[#unwrap_uvw].renderuv_fillmode = 1;--solid
$.modifiers[#unwrap_uvw].renderuv_seamColor = color 255 255 255;
$.modifiers[#unwrap_uvw].renderuv_showframebuffer = false;
boularaw = GetDir #image + "_renderTlibad.bmp" --define a temp.file name
$.modifiers[#unwrap_uvw].unwrap5.renderUV boularaw;--save UV layout to the temp folder
$.modifiers[#unwrap_uvw].renderuv_showframebuffer = true;--reset defaults
---------------------------
boula= openBitmap(boularaw as string)
progressstart "Are you a good UV mapper??..."
oldEscapeEnable = escapeEnable
escapeEnable = true
print coin2
for y = 1 to boula.height do
(
progressupdate (100.0 * y / boula.height)
g = getpixels boula [0,y-1] boula.width
for x = 1 to boula.width do
(
if g[x] == (color 0 0 0) do (pxBlack +=1)
)
)
et = timestamp()
progressend ()
escapeEnable = oldEscapeEnable
pxBlack
d = boula.width * boula.height
stat =int ((pxBlack/d as float) *100)
if stat < 10 then
(
messageBox ("You are an UV Killer!! Only " + (stat as string) + " %" + " of free space!")
)
else
(
messageBox ("You have " + (stat as string) + " %" + " of free space! Woot!")
)
-------------------------------------------------------
$.modifiers[#unwrap_uvw].renderuv_width = sixze.text as integer;
$.modifiers[#unwrap_uvw].renderuv_height = siyze.text as integer;
$.modifiers[#unwrap_uvw].renderuv_fillmode = 0;--solid
$.modifiers[#unwrap_uvw].renderuv_seamColor = color 255 255 255;
$.modifiers[#unwrap_uvw].renderuv_showframebuffer = false;
clipboardClass = dotNetClass "System.Windows.Forms.Clipboard" --create a Clipboard dotNetClass
theFileName = GetDir #image + "_renderToClipboard.png" --define a temp.file name
$.modifiers[#unwrap_uvw].unwrap5.renderUV theFileName;--save UV layout to the temp folder
theImage = dotNetClass "System.Drawing.Image" --create an Image dotNetClass
theBitmap = theImage.FromFile theFileName --get the saved image from file as bitmap
clipboardClass.setImage theBitmap --copy the image to clipboard
theBitmap.Dispose() --release the bitmap
deleteFile theFileName --delete the temp. file
clipboardClass.ContainsImage() --return true if the clipboard contains image
$.modifiers[#unwrap_uvw].renderuv_showframebuffer = true;--reset defaults
print "UV copy to clipboard OK"
-------------------------------------------------------
)
)
createDialog SizeMapDialog width:296 height:64
)
Maybe it's completely useless, but it was a challenge for me
I saw too, on your post, that you want to make a uv face selection 3ds==>photoshop?
like this?
http://www.zortech.de/uv2psScript.xhtml
I find that very useful
hope you like it 
|
, spline,
160 Posts,
Join Date Sep 2006,
Location Paris
|
@zOffTy
I got this error in max9
Code:
Surface Area 300829.781250 bounds area 329609.718750 per used 0.912685
Edge Height 1541.482056 Edge Width 1286.267456
Initial Clusters 6 finalClusters 6
undefined
-- Error occurred in ό8LTΈ˜ΰ
-- Frame:
>> MAXScript Rollout Handler Exception: -- Unknown system exception <<
thats propably the result from that thread- I just dont like the PS script part. But its a nice script to learn from.
|
, card carrying polycounter,
2,369 Posts,
Join Date Mar 2008,
Location Sydney Australia
|
on max 11 it's works well.
but on max 9 sp1 I sometimes have the same error
I'll try to see where the problem may come
is copy to clipboard limited in size?
a 1024x1024 works well, but not 2048x2048?!
|
, spline,
160 Posts,
Join Date Sep 2006,
Location Paris
|
Quote:
Originally Posted by MoP
btw something awesome i found out (and I think Per mentioned this too a while back) is that if you're using maxscript to physically set the position of a UV vertex, you will not get any undo info on that.
The only way I found to make it correctly behave with undo is put a relative move of 0,0,0 in before the actual setVertexPosition. Then the undo clause worked correctly.
Good idea to put the functionality for aligning all into one button.
I might take this idea for my UV Line Relax script so that it falls back to default align behaviour if it doesn't find a contiguous line to relax along.
|
son of a b!tch... that had me stumped on a vert/edge flatten script I was working on. Drove me batty until now. Thanks a bunch I might actually have something usable, that mimics all the other 19 UV vert flatten scripts already floating around. But consider it was a learning experience, I learned a lot. Thanks for helping me make it usable!
Renderhjs, you have some sweet stuff going, don't stop!
|
, Grand Marshall Polycounter,
9,663 Posts,
Join Date Oct 2004,
Location Seattle, Wa
|
got another script
render ambient occlusion map to clipboard

you will see a render progress bar so you know when max is done rendering the map and when its in your clipboard - but you dont see the framebuffer or renderwindow.
still prototype but here is the code:
Code:
fn bake_AO_2_clipboard _size _quality=
(
tex_size = _size;
obj = selection[1];
obj.removeAllBakeElements();
ao_bake = AmbientOcclusionBakeElement();
ao_bake.outputSzX = tex_size;
ao_bake.outputSzY = tex_size;
ao_bake.autoSzOn = false;
ao_bake.bright = color 255 255 255 0;
ao_bake.dark = color 0 0 0 0;
ao_bake.backgroundColor = color 0 0 0 0;
ao_bake.elementName = "Ambient Occlusion";
ao_bake.falloff = 1.0;
ao_bake.maxDistance = 0.0 ;
ao_bake.samples = 2+_quality*120;--16
ao_bake.spread = 40.1 - _quality*40;--0.8
ao_bake.enabled = true;
ao_bake.fileType = GetDir #image + "_renderToClipboard3.bmp";--appearently the target filename/path
-- Baking job
bake = obj.INodeBakeProperties;
bake.bakeChannel = 1;
bake.nDilations = 2; -- (Pading)
bake.flags = 1; --bit 1 of flag will be set to signify map channel conflict
bake.bakeEnabled = true;
bake.addBakeElement ao_bake;
--select obj
render rendertype:#bakeSelected outputwidth:tex_size outputheight:tex_size vfb:false;
--copy to clipoard and delete temp image
theFileName = ao_bake.fileType --define a temp.file name
clipboardClass = dotNetClass "System.Windows.Forms.Clipboard" --create a Clipboard dotNetClass
theImage = dotNetClass "System.Drawing.Image" --create an Image dotNetClass
theBitmap = theImage.FromFile theFileName --get the saved image from file as bitmap
clipboardClass.setImage theBitmap --copy the image to clipboard
theBitmap.Dispose() --release the bitmap
deleteFile theFileName --delete the temp. file
clipboardClass.ContainsImage() --return true if the clipboard contains image
--remove traces
bake.removeAllBakeElements();
bake.bakeEnabled = false;
obj.removeAllBakeElements();
)
bake_AO_2_clipboard 320 0.8;
I am still figuring out how to use as less parameters as possible to reduce complexity in the interface or usage. But in the end it might end up with textureSize², samples/qulity, spread/softness
the next thing I started roughly is a GUI for all these scripts (texture/UV stuff) though I plan designing most functions in a way so that they can used as well on keys and single buttons - so that they can survive as well without parameters somehow

|
, card carrying polycounter,
2,369 Posts,
Join Date Mar 2008,
Location Sydney Australia
|
bigger update:
I crossed the buttons that have no functions yet - those are planned atm. but not yet added. Be carefull though as open UV-editor overwrites color settings of your UV-editor such as background color and edge color. I have not yet tried it on other computers here but those should be the only settings that change things in your uv-unwrap editor in case you might edit your UV`s the regular way.
script as download (source view at the bottom)
http://www.renderhjs.net/bbs/polycou...re_tools_05.ms
more in detail:
the vertex align script:
changes:
- can handle face or edge selections as well
- spinner for the snap angle that defines within what 90° offset angle it should snap to the axis.
align edge-shell to axis

features:
- detects automaticly the closest axis to the edge slected
- aligns the associated shell around the center of the selected edge
- align shells to each other based on a edge- pair (similar to Modo or uvLayout)
future ideas:
- align face selection to 3d space equivalent orientation. Often when automatic unwrapping shells get rotated or flipped in the wrong direction - I want to get rid of that.
- render selected faces to quicker block out textures in photoshop (inking base shapes of certain model shapes)
- render convex/concave map (convexity map) based on vertex color script I found. This will be a alternative dirt map. maybe some material stuff with difuse-RTT output might be another nice idea, or a difuse-RTT of a falloff map with world-z direction (dust map).
script code (in case my url gets offline or you want to dig specific code)
Code:
fl_textureHelper;
rl_textureMain;
fn pack_uv _space = (
if classof (modPanel.getCurrentObject()) == Unwrap_UVW then(
selection[1].modifiers[1].unwrap2.pack 0 _space false false false;
)
)
fn open_uv_editor = (
try(
disableSceneRedraw()
modPanel.addModToSelection (Unwrap_UVW ()) ui:on
$.modifiers[#unwrap_uvw].unwrap5.setShowMapSeams off
$.modifiers[#unwrap_uvw].unwrap5.setPeltAlwaysShowSeams off
subobjectLevel = 3;
modPanel.setCurrentObject $.modifiers[#Unwrap_UVW]
$.modifiers[#unwrap_uvw].unwrap2.setFreeFormMode on
$.modifiers[#unwrap_uvw].unwrap.edit ()
subobjectLevel = 3
$.modifiers[#unwrap_uvw].unwrap.DisplayMap off
$.modifiers[#unwrap_uvw].unwrap.edit ()-- to maximize
$.modifiers[#unwrap_uvw].unwrap.edit ()-- to maximize
$.unwrap_uvw.unwrap2.setGeomSelectElementMode(true); -- select viewport
--$.unwrap_uvw.unwrap2.setTVElementMode(true);--select element UV view
$.unwrap_uvw.unwrap2.setTVSubObjectMode(3);--face selection more
$.unwrap_uvw.unwrap2.setShowMap(false);--disable tex view
--$.modifiers[#unwrap_uvw].unwrap2.renderuv_seamColor = color ;
--
$.modifiers[#unwrap_uvw].unwrap2.setOpenEdgeColor [256-190,256-230,256-119];
$.modifiers[#unwrap_uvw].unwrap2.setSharedColor [256-255,256-132,256-255];
$.modifiers[#unwrap_uvw].unwrap.setLineColor [256-255,256-132,256-0];
$.modifiers[#unwrap_uvw].unwrap.setSelectionColor [256-255, 256-108, 256-0];
-- new stuff
$.modifiers[#unwrap_uvw].unwrap2.setFillMode 2;
$.modifiers[#unwrap_uvw].unwrap2.setBackgroundColor [256-44,256-52,256-43];
--grid colors
$.modifiers[#unwrap_uvw].unwrap2.setGridVisible true;
$.modifiers[#unwrap_uvw].unwrap2.setGridSize 1;
$.modifiers[#unwrap_uvw].unwrap2.setGridColor [82,79,69];
--fl_textureHelper.pos = point2 96 64;
--clearlistener();
local _x = (fl_textureHelper.pos.x + 160+200) as integer;
local _y = (fl_textureHelper.pos.y + 16) as integer;
$.modifiers[#unwrap_uvw].unwrap5.setWindowXOffset 640;
print("pos x "+5 as string);
--$.modifiers[#unwrap_uvw].unwrap5.setWindowYOffset _y;
--setWindowXOffset
enableSceneRedraw();
completeRedraw();
print("any?"+2 as string);--$.modifiers[#unwrap_uvw].unwrap.pos
)catch(
enableSceneRedraw()
completeRedraw();
)
)
fn align_uv_edge_to_axis =(
local obj = selection[1];
if classof (modPanel.getCurrentObject()) == Unwrap_UVW then(
local _mode = obj.modifiers[#unwrap_uvw].unwrap2.getTVSubObjectMode();
if (_mode == 2)then(
local _array = obj.modifiers[#unwrap_uvw].unwrap2.getSelectedEdges();
if (_array.numberSet == 1)then(
local _edge = (_array as array)[1] as integer;
--get the transformation info
obj.modifiers[#unwrap_uvw].unwrap2.edgeToVertSelect();
_points = obj.modifiers[#unwrap_uvw].unwrap.getSelectedVertices() as array;
local ptA = obj.modifiers[#unwrap_uvw].getVertexPosition 1 _points[1];
local ptB = obj.modifiers[#unwrap_uvw].getVertexPosition 1 _points[2];
local dx = ptB.x - ptA.x;
local dy = ptB.y - ptA.y;
/*
local dx = amax #(ptB.x, ptA.x) - amin #(ptB.x, ptA.x);
local dy = amax #(ptB.y, ptA.y) - amin #(ptB.y, ptA.y);
*/
local _a_abs = mod ((atan2 dy dx)+4*360) 360;--the angle in closed 360 degrees
local _a_off = (mod _a_abs 90);--angle offset
if (_a_off > 45)then(
_a_off = -(90 - _a_off);
)
--was it last time already snapped to this value? - in that case flip the axis
/*local _res1 = (floor (_a_abs)) as integer;
local _res2 = (floor (_a_abs + _a_off)) as integer;
if (_res1 == _res2)then(
_a_off = _a_off+90;
)
print("angle offset "+_a_off as string+" = "+_res1 as string);
*/
obj.modifiers[#unwrap_uvw].unwrap2.selectElement();
obj.modifiers[#unwrap_uvw].unwrap2.RotateSelected (-_a_off * PI/180) [(ptA.x + dx/2),(ptA.y + dy/2),0]
obj.modifiers[#unwrap_uvw].unwrap6.selectEdgesByNode #{_edge} $;
)else(
print("select just 1 edge!");
)
)
)
)
fn align_uv_verts _angleSnap =(
if classof (modPanel.getCurrentObject()) == Unwrap_UVW then(
-- check if vertex points are selected. otherwise convert
_uvBase = $.modifiers[#unwrap_uvw];
_uv1 = $.modifiers[#unwrap_uvw].unwrap;
_uv2 = $.modifiers[#unwrap_uvw].unwrap2;
_uv5 = $.modifiers[#unwrap_uvw].unwrap5;
local _mode = _uv2.getTVSubObjectMode();
if (_mode == 2)then(
_uv2.edgeToVertSelect();
)else if (_mode == 3)then(
_uv2.faceToVertSelect();
)
_array = _uv1.getSelectedVertices();
_selection = #();--new array
_maxX;_maxY;_minX;_minY;
_nr=1;
for i in _array do (
local _pt = _uvBase.getVertexPosition 1 i;
if (_nr > 1) then(
local _pt2 = _uvBase.getVertexPosition 1 _maxX;
if (_pt.x > _pt2.x)then(
_maxX = i;
)
_pt2 = _uvBase.getVertexPosition 1 _minX;
if (_pt.x < _pt2.x)then(
_minX = i;
)
_pt2 = _uvBase.getVertexPosition 1 _maxY;
if (_pt.y > _pt2.y)then(
_maxY = i;
)
_pt2 = _uvBase.getVertexPosition 1 _minY;
if (_pt.y < _pt2.y)then(
_minY = i;
)
)else(
_maxX = i;
_maxY = i;
_minX = i;
_minY = i;
)
_selection[_nr] = i;
_nr+=1;
)
if (_nr > 1)then(
--determine if horizontal or vertical flow
local _a = _uvBase.getVertexPosition 1 _minX;
local _b = _uvBase.getVertexPosition 1 _maxX;
local _w = (_b.x - _a.x);
_a = _uvBase.getVertexPosition 1 _minY;
_b = _uvBase.getVertexPosition 1 _maxY;
local _h = (_b.y - _a.y);
local A=1;
local B=1;
_sel = #{};
if (_w > _h )then(
A = _minX;
B = _maxX;
)else(
A = _minY;
B = _maxY;
)
_sel = #{};
_sel[A] = true;
_sel[b] = true;
--_uv1.selectVertices _sel;
if (_selection.count > 2)then(
local ptA = _uvBase.getVertexPosition 1 A;
local ptB = _uvBase.getVertexPosition 1 B;
local dx = ptB.x - ptA.x;
local dy = ptB.y - ptA.y;
local _a = mod ((atan2 dy dx)+4*360) 360;--the angle in degrees
local _snap = (mod _a 90) as integer;
if (_snap > 45)then(
_snap = 90 - _snap;
)
if (_snap <= _angleSnap)then(
--snap to axis
if(_w > _h )then(
ptA.y = ptA.y + dy/2;
ptB.y = ptA.y;
)else(
ptA.x = ptA.x + dx/2;
ptB.x = ptA.x;
)
_uvBase.SetVertexPosition 1 A ptA;
_uvBase.SetVertexPosition 1 B ptB;
)
--_angleSnap
print("angle "+_a as string+" %90= ("+_snap as string+")");
for i = 1 to _selection.count do(
if (_selection[i] != A and _selection[i] != B)then(
local _pt = _uvBase.getVertexPosition 1 _selection[i];
if(_w > _h )then(
local _m = (ptB.y - ptA.y) / (ptB.x - ptA.x);
local _x = _pt.x - ptA.x;
_pt.y = _x * _m + ptA.y;
)else(
local _m = (ptB.x - ptA.x) / (ptB.y - ptA.y);
local _y = _pt.y - ptA.y;
_pt.x = _y * _m + ptA.x;
)
_uvBase.SetVertexPosition 1 _selection[i] _pt;
)
)
)else if (_selection.count == 2) then(
--align just 2 verts
local ptA = _uvBase.getVertexPosition 1 A;
local ptB = _uvBase.getVertexPosition 1 B;
local dx = ptB.x - ptA.x;
local dy = ptB.y - ptA.y;
local _a = mod ((atan2 dy dx)+4*360) 360;--the angle in degrees
local _snap = (mod _a 90) as integer;
if (_snap > 45)then(
_snap = 90 - _snap;
)
if (_snap <= _angleSnap)then(
--snap to axis
if(_w > _h )then(
ptA.y = ptA.y + dy/2;
ptB.y = ptA.y;
)else(
ptA.x = ptA.x + dx/2;
ptB.x = ptA.x;
)
_uvBase.SetVertexPosition 1 A ptA;
_uvBase.SetVertexPosition 1 B ptB;
)
)
)
)else(
print("you are not in UV-edit mode!");
)
)
fn get_tex_size_auto = (
local _w;
local _h;
local _result;
if (selection[1].material != undefined)then(--the object material difuse bitmap width
_w = selection[1].material.maps[2].bitmap.width;
_h = selection[1].material.maps[2].bitmap.height;
_result = amax #(_w, _h);
)else(
if classof (modPanel.getCurrentObject()) == Unwrap_UVW then(
_w = selection[1].modifiers[1].unwrap.getRenderWidth();
_h = selection[1].modifiers[1].unwrap.getRenderHeight();
_result = amax #(_w, _h);
)else(
_result = 512;
)
)
return _result;
)
fn bake_ao_2_clipboard _size _samples _spread=(
tex_size = _size;
obj = selection[1];
obj.removeAllBakeElements();
ao_bake = AmbientOcclusionBakeElement();
ao_bake.outputSzX = tex_size;
ao_bake.outputSzY = tex_size;
ao_bake.autoSzOn = false;
ao_bake.bright = color 255 255 255 0;
ao_bake.dark = color 0 0 0 0;
ao_bake.backgroundColor = color 0 0 0 0;
ao_bake.elementName = "Ambient Occlusion";
ao_bake.falloff = 1.0;
ao_bake.maxDistance = 0.0 ;
ao_bake.samples = _samples;--16
ao_bake.spread = _spread;--0.8
ao_bake.enabled = true;
ao_bake.fileType = GetDir #image + "_renderToClipboard3.bmp";--appearently the target filename/path
-- Baking job
bake = obj.INodeBakeProperties;
bake.bakeChannel = 1;
bake.nDilations = 2; -- (Pading)
bake.flags = 1; --bit 1 of flag will be set to signify map channel conflict
bake.bakeEnabled = true;
bake.addBakeElement ao_bake;
--select obj
render rendertype:#bakeSelected outputwidth:tex_size outputheight:tex_size vfb:false;
--copy to clipoard and delete temp image
theFileName = ao_bake.fileType --define a temp.file name
clipboardClass = dotNetClass "System.Windows.Forms.Clipboard" --create a Clipboard dotNetClass
theImage = dotNetClass "System.Drawing.Image" --create an Image dotNetClass
theBitmap = theImage.FromFile theFileName --get the saved image from file as bitmap
clipboardClass.setImage theBitmap --copy the image to clipboard
theBitmap.Dispose() --release the bitmap
deleteFile theFileName --delete the temp. file
clipboardClass.ContainsImage() --return true if the clipboard contains image
--remove traces
bake.removeAllBakeElements();
bake.bakeEnabled = false;
obj.removeAllBakeElements();
)
function bake_uv_2_clipboard _size = (
--check if UV- modifier is present...
local obj = selection[1];
local del_uvModifier = false;
if classof (modPanel.getCurrentObject()) != Unwrap_UVW then(--add a UVW unwrap modifier
modPanel.addModToSelection (Unwrap_UVW ()) ui:on;
del_uvModifier = true;
)
--_size = 512;
obj.modifiers[#unwrap_uvw].renderuv_width = _size;
obj.modifiers[#unwrap_uvw].renderuv_height = _size;
obj.modifiers[#unwrap_uvw].renderuv_fillmode = 0;--solid
obj.modifiers[#unwrap_uvw].renderuv_seamColor = color 255 255 255;
obj.modifiers[#unwrap_uvw].renderuv_showframebuffer = false;
clipboardClass = dotNetClass "System.Windows.Forms.Clipboard" --create a Clipboard dotNetClass
theFileName = GetDir #image + "_renderToClipboard.bmp" --define a temp.file name
obj.modifiers[#unwrap_uvw].unwrap5.renderUV theFileName;--save UV layout to the temp folder
theImage = dotNetClass "System.Drawing.Image" --create an Image dotNetClass
theBitmap = theImage.FromFile theFileName --get the saved image from file as bitmap
clipboardClass.setImage theBitmap --copy the image to clipboard
theBitmap.Dispose() --release the bitmap
deleteFile theFileName --delete the temp. file
clipboardClass.ContainsImage() --return true if the clipboard contains image
obj.modifiers[#unwrap_uvw].renderuv_showframebuffer = true;--reset defaults
if (del_uvModifier == true)then(
deleteModifier obj 1;
print("modifier has been deleted!!!");
)
)
rollout rl_textureMain "general" width:128 height:353
(
label lbl1 "res:" pos:[2,6] width:31 height:14
button btn_bake_uv "bake UV wire" pos:[2,26] width:124 height:20
button btn_bake_ao "bake AO" pos:[2,75] width:124 height:20
spinner spn_ao_samples "smpl" pos:[9,96] width:56 height:16 range:[0,800,64] scale:1
spinner spn_ao_spread "sprd" pos:[71,96] width:56 height:16 range:[0,100,50] scale:1
button btn_align_verts "align verts" pos:[2,189] width:78 height:28
spinner spn_snap_align "" pos:[79,200] width:40 height:16 range:[0,45,45] scale:1
label lbl_degrees "°" pos:[121,201] width:4 height:14
button btn_res_guess "get" pos:[55,3] width:25 height:21
edittext edt_tex_size "" pos:[18,3] width:37 height:21
dropdownList ddl_uvChannel "" pos:[92,3] width:37 height:21 items:#("1", "2", "3", "4") selection:1
button btn_bake_faces "bake UV sel. faces" pos:[2,46] width:124 height:20
label lbl_channel "#" pos:[83,6] width:9 height:14
button btn_align_edge_shell_axis "align edge-shell to axis" pos:[2,222] width:124 height:20
button btn_align_shell_3d "align shell to 3d-space" pos:[2,265] width:124 height:20
button btn_align_edge_neighbor "align edge to neighbor" pos:[2,242] width:124 height:20
label lbl_uv_tools "UV alinging tools" pos:[23,126] width:82 height:14
label lbl9 "axis snap" pos:[81,186] width:45 height:14
button btn_open_uv_editor "open UV editor" pos:[2,142] width:124 height:30
button btn_pack_uv "pack UV" pos:[2,292] width:87 height:30
spinner spn_btn_pack_uv_space "" pos:[88,305] width:39 height:16 range:[0,100,0] scale:1
label lbl_btn_pack_uv_space "pix spc" pos:[89,291] width:37 height:14
-------------------------------------------------
on btn_bake_uv pressed do
(
bake_uv_2_clipboard (edt_tex_size.text as integer);
)
on btn_bake_ao pressed do
(
bake_ao_2_clipboard (edt_tex_size.text as integer ) (spn_ao_samples.value/100) (spn_ao_spread.value/100);
)
on btn_align_verts pressed do
(
align_uv_verts spn_snap_align.value;
)
on btn_res_guess pressed do
(
edt_tex_size.text = get_tex_size_auto() as string;
)
on btn_bake_faces pressed do
(
--render selected faces
)
on btn_align_shell_3d pressed do
(
--
)
on btn_align_edge_neighbor pressed do
(
--
)
on btn_align_edge_shell_axis pressed do
(
align_uv_edge_to_axis();
)
on btn_open_uv_editor pressed do
(
open_uv_editor();
)
on btn_pack_uv pressed do
(
pack_uv (spn_btn_pack_uv_space.value/(rl_textureMain.edt_tex_size.text as integer));
)
)
function _init = (
try (-- close existing rolloutFloater
closeRolloutFloater fl_textureHelper;
) catch();
fl_textureHelper = newRolloutFloater "texture tools" 142 370;
addrollout rl_textureMain fl_textureHelper;
rl_textureMain.edt_tex_size.text ="512";
fl_textureHelper.pos = point2 96 64;
)
_init();
|
, card carrying polycounter,
2,369 Posts,
Join Date Mar 2008,
Location Sydney Australia
|
just played around with it...
Thanks for the idea to change the colours of the uv window, I was always annoyed at that background grid thing and how the lines were not visible in the black squares, cant believe changing the colours didnt occur to me until now -.-
btw you can make the uv window pop up by default by enabling the "always bring up the edit window"under options and then saving preferences.
The features are awesome, I really like that shell aligning idea and the copy-uv-wire. But a few things I dont like;
First I cant hotkey the UV aligning tools, this is really important because I dont want to be clicking on a 2nd window to do this. Actually I'd like to put all of this stuff in a quad menu or hotkeyed instead of a clicking interface, but I guess it will be impossible to do with the ones that require a number input box.
Secondly when undoing the UV aligning, it undos each vertex individually instead of the whole process. So If I align 20 UVs, it will have to go through 20 undos to get back to the previous state whereas with chuggnuts (or mops tools), you can undo the whole thing.
And I realize I can rip your script to make a hotkeyable version of the alignment tool, I just felt like suggesting you to put it in there by default :p
Last edited by Yozora; 02-06-2009 at 04:56 PM..
|
, polycounter,
1,035 Posts,
Join Date Nov 2007,
Location UK
|
Quote:
|
First I cant hotkey the UV aligning tools, th...
|
defenitly planned once its all cleaned up- I need as well to assign stuff to hotkeys later.
That is also why I mentioned in the beginning to try to design functions to be useable even witout parameters (e.g angle snap value - would then be hard coded i the function and each time come with the same value). Another goal was to reduce the amount of functions or keys one use (by smartly determining between horizontal or vertical align for example).
but thx for the try and feedback
|
, card carrying polycounter,
2,369 Posts,
Join Date Mar 2008,
Location Sydney Australia
|
awesome, I'll try and mess with it later!
|
, veteran polycounter,
2,679 Posts,
Join Date Jan 2007,
Location San Jose, CA
| Thread Tools |
|
|
| Display Modes |
Linear Mode
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
Copyright 1998-2010 A. Risch
|