[Closed] break uvs along uv seams without unwrap ?
Hello guys,
Following a post from my coworker Clanker, I need to optimize an operation on imported CAD objects whose uvs are fucked up. We are writing a script which could clean these uvs and make it ready for artist work.
We have hundreds of these pieces so we need a fast cleanup routine. Every second is worth it !
Here is an example of a piece (not complete because of copyright reasons):
https://dl.dropboxusercontent.com/u/13762052/polycount/cad_unwrap_test.obj
I am at a point where I need to breaks uvs along uv seams.
I have come to a solution so far by merging different pieces of code there and there in the forum :
(
function getArrayOfTVerts2VertsMESH theObj theMapChannel =
(
-- both following function are from PrettyPixel: http://forums.cgsociety.org/showthread.php?t=298713
_getNumMapVerts = meshOp.getNumMapVerts
_getNumMapFaces = meshOp.getNumMapFaces
_getMapFace = meshOp.getMapFace
local numMapVerts = _getNumMapVerts theObj theMapChannel
local mapVerts2Verts = (for mv=1 to numMapVerts collect #())
local numMapFaces = _getNumMapFaces theObj theMapChannel
for f=1 to numMapFaces do
(
local theMapFace = _getMapFace theObj theMapChannel f
theMapFace = #(theMapFace.x as integer,theMapFace.y as integer,theMapFace.z as integer)
local meshFace = getFace theObj f
meshFace = #(meshFace.x as integer,meshFace.y as integer,meshFace.z as integer)
for mv=1 to theMapFace.count do
(
local mapVert = theMapFace[mv]
if (findItem mapVerts2Verts[mapVert] meshFace[mv] == 0) do append mapVerts2Verts[mapVert] meshFace[mv]
)
)
mapVerts2Verts
)
function getArrayOfVerts2TVerts mapVerts2Verts =
(
verts2MapVerts=#()
for mv=1 to mapVerts2Verts.count do
(
currentVerts=mapVerts2Verts[mv]
if currentVerts!=undefined do
(
for v=1 to currentVerts.count do
(
if verts2MapVerts[currentVerts[v]] == undefined then verts2MapVerts[currentVerts[v]]=#(mv)
else append verts2MapVerts[currentVerts[v]] mv
)
)
)
verts2MapVerts
)
function getOpenMapEdges node channel:1 debug:off = if iskindof node GeometryClass and canconvertto node editable_mesh do
(
-- DenisT + PolyTools function from http://forums.cgsociety.org/showthread.php?f=98&t=1113501&page=3&pp=15
-- slighly modified to get the vertices indices only
local mesh = snapshotasmesh node
local edges = #()
local _getEdgesUsingVert = meshop.getEdgesUsingVert
if meshop.getmapsupport mesh channel do
(
numtverts = meshop.getnummapverts mesh channel
getmapface = meshop.getmapface
tfaces = for f=1 to mesh.numfaces collect (getmapface mesh channel f)
local emesh = TriMesh()
setmesh emesh numverts:numtverts numfaces:mesh.numfaces
setmesh emesh faces:tfaces
seamed = meshop.getopenedges emesh
opened = meshop.getopenedges mesh * seamed
faces = meshop.getfacesusingedge mesh seamed
for f in faces do
(
vv = getface mesh f
e = f*3 - 3
if seamed[e += 1] and (vv[1] < vv[2] or opened[e]) do append edges #(vv.x, vv.y) -- get the indices of the vertices only
if seamed[e += 1] and (vv[2] < vv[3] or opened[e]) do append edges #(vv.y, vv.z)
if seamed[e += 1] and (vv[3] < vv[1] or opened[e]) do append edges #(vv.x, vv.z)
)
free mesh
free emesh
)
edges
)
function BreakUVSeams obj =
(
local edges = getOpenMapEdges obj channel:1
local verts2Tverts = getArrayOfVerts2TVerts (getArrayOfTVerts2VertsMESH obj 1)
local unwrapMod = Unwrap_UVW()
addModifier obj unwrapMod
if (getCommandPanelTaskMode() != #modify) do setCommandPanelTaskMode #modify
unwrapMod.setTVSubObjectMode 1
-- convert the edges array in an array of the tverts matching both vertices of the edge
local Tedges = for i=1 to edges.count collect #()
for i=1 to edges.count do ( for j=1 to 2 do ( for tv in verts2Tverts[edges[i][j]] do append Tedges[i] tv) )
local uvSeams = #{}
-- time consuming bottleneck
for Tedge in Tedges do
(
unwrapMod.selectVertices (Tedge as bitarray)
unwrapMod.vertToEdgeSelect()
uvSeams = uvSeams + unwrapMod.getSelectedEdges()
)
unwrapMod.setTVSubObjectMode 2
unwrapMod.selectEdges uvSeams
unwrapMod.breakSelected()
)
--=========================
gc()
st = timestamp(); sh = heapfree
local part = converttomesh $test
select part
BreakUVSeams part
format "faces:% time:% ram:%
" $.numfaces (timestamp()-st) (sh-heapfree)
)
As you can see, I use unwrap functions to convert tvert selection to tedge selection then break them. The bottleneck here is that loop using unwrap functions :
for Tedge in Tedges do
(
unwrapMod.selectVertices (Tedge as bitarray)
unwrapMod.vertToEdgeSelect()
uvSeams = uvSeams + unwrapMod.getSelectedEdges()
)
1/ This patchwork of codes is nasty and I have the feeling that it is not optimized at all ! It is however pretty fast until it comes to use the above unwrap functions.
2/ I am quite sure that there is a smarter solution which do not include any unwrap modifier, working directly with tverts and tfaces, but I am not experienced enough in mesh/uvs handling to figure out how to do it.
Any hints about that ?
PS: I am sorry for the huge code but I couldn’t reduce it more…
When trying to write a “break uv open map edges” in pure maxscript, I was stuck on one simple thing without finding any answer in the forum :
How to add map vertices to an existing channel ?
I tried:
setNumTVerts $ newtvnum true
buildTVFaces $
but it totally screwed my uvs…
You can transform UV coordinates into actual geometry like Editable Poly and work with that in the viewport (which is faster and more accessable via MaxScript) using the Channel info utility.
I don’t really get your point here… sorry.
Can you give me an example, please ?
Ok. I got it.
Can I perform this operation in maxscript, by any chance ?
the thing is solved, isn’t it? here is the most resent solution: http://forums.cgsociety.org/showpost.php?p=7758801&postcount=62
for posted test it takes 64 ms
Not exactly.
Your script fixes welded tverts that dont belong to the same geo vert.
However, elements are still “attached” together when they got tverts sharing the same geo vert.
My approach was to select open uv edges and break.
From one of your/jorge script, we have an array of verts composing all (uv) open edges. But the conversion from vertex to uv edge takes a while.
In this file,
https://dl.dropboxusercontent.com/u/13762052/polycount/cad_unwrap_test.obj
after running your script, you can see that some elemnts are still attached.
tvert from vertex #{1509} should be broken for instance.
Now i guess a most efficient way would be to not use the unwrap, and test which point to keep broken in the trimesh.
So i guess what i need is a way to break this vertex while keeping the pink edges intact.
your task is technically solved. at least for me. there is nothing more that can interested me there.
it was very specific task. the only real interest and reason was to beat the max… just make the max looks snoopy … to show that 1 hour can be thousands times shorter
It is totally understandable and both your help (polytools and you) was really appreciated.
It seems to me that this new subject, independantly from the first one from Clanker, could be another room to beat max on breaking uv open edges without using the very slow unwrap methods…
I will look into modifying your previous BreakAndWeld code to handle this cases (if possible but I doubt about it) and post there if I succeed.
But a more generic solution for this specific breaking open uv edges in pure maxscript” seems however useful to me and others community members I think.
I know you are not just to post answers but I asked only hints about how to achieve it, like my last question on how to cleanly add some tverts in an existing uv channel. I’m sure you have that answer ;-).
Thanks for your time anyway. I hope you will find another interesting challenge, soon.
Antoine, I have already published the code (actually a tool) for doing this and mentioned it to @Clanker here on ScriptSpot. Latest version of the tool here.
Frome there, if you also need to break the elements that are joined by just 1 vertex, it would be pretty simple. It will in fact take you much less time than what it took me to write this.