277 lines
8.4 KiB
Plaintext
Executable File
277 lines
8.4 KiB
Plaintext
Executable File
(
|
|
local obj = $
|
|
local faceSel
|
|
|
|
/*
|
|
while (obj.modifiers.count > 0) do (deletemodifier obj 1)
|
|
*/
|
|
|
|
case of
|
|
(
|
|
((obj == undefined) or (isKindOf obj array) or (not isKindOf obj.baseObject Editable_Poly)):
|
|
(
|
|
messageBox "Please select an Editable Poly object" title:""
|
|
)
|
|
(obj.modifiers.count != 0):
|
|
(
|
|
messageBox "Please select an Editable Poly object with no modifiers" title:"Object has modifiers"
|
|
)
|
|
(
|
|
(subObjectLevel !=0) and ((polyop.getFaceSelection obj) == 0)
|
|
):
|
|
(
|
|
messageBox "Please select at least one face on object" title:"No faces selected"
|
|
)
|
|
Default:
|
|
(
|
|
local initialFaceSel = polyop.getFaceSelection obj
|
|
local initialEdgeSel = polyop.getEdgeSelection obj
|
|
|
|
local useFaces = if (subObjectLevel ==0) then #{1..obj.numfaces} else polyop.getFaceSelection obj
|
|
|
|
local faceEdges = for n = 1 to useFaces.count collect
|
|
(
|
|
if useFaces[n] then (polyop.getFaceEdges obj n) else undefined
|
|
)
|
|
|
|
for faceNum in useFaces do
|
|
(
|
|
-- Don't include non-quads:
|
|
if (polyop.getFaceVerts obj faceNum).count != 4 do
|
|
(
|
|
useFaces[faceNum] = false
|
|
)
|
|
)
|
|
|
|
-- Create UVWunwrap modifier, select the relevant quads:
|
|
local newUVmod = Unwrap_UVW()
|
|
newUVmod.unwrap5.setShowMapSeams off
|
|
newUVmod.unwrap5.setPeltAlwaysShowSeams off
|
|
|
|
addModifier obj newUVmod
|
|
|
|
/*
|
|
newUVmod.setApplyToWholeObject true
|
|
newUVmod.selectPolygonsUpdate useFaces true
|
|
newUVmod.setApplyToWholeObject false
|
|
*/
|
|
|
|
-- Work out which faces are contiguous:
|
|
local faceGroups = for n in useFaces collect #{n}
|
|
local faceGroupEdges = for item in faceEdges where (item != undefined) collect (item as bitarray)
|
|
|
|
-- Get edge-lengths for all used edges:
|
|
local allUsedEdges = #{}
|
|
for item in faceGroupEdges do (allUsedEdges += item)
|
|
local edgeNum, edgeVerts
|
|
local edgeLengths = for n = 1 to allUsedEdges.count collect
|
|
(
|
|
if allUsedEdges[n] then
|
|
(
|
|
edgeVerts = polyop.getEdgeVerts obj n
|
|
distance (polyop.getVert obj edgeVerts[1]) (polyop.getVert obj edgeVerts[2])
|
|
) else undefined
|
|
)
|
|
|
|
local existingGroups = #{1..faceGroups.count}
|
|
|
|
local repeatLoop = true
|
|
local combinedEdges
|
|
while repeatLoop do
|
|
(
|
|
repeatLoop = false
|
|
|
|
for grpNum = 1 to faceGroups.count where existingGroups[grpNum] do
|
|
(
|
|
for compareNum = (grpNum + 1) to faceGroups.count where existingGroups[compareNum] do
|
|
(
|
|
combinedEdges = faceGroupEdges[grpNum] + faceGroupEdges[compareNum]
|
|
|
|
-- If the edge-bitarrays overlap, the combined array will have fewer items than the seperate arrays:
|
|
if (combinedEdges.numberSet != (faceGroupEdges[grpNum].numberSet + faceGroupEdges[compareNum].numberSet)) do
|
|
(
|
|
faceGroupEdges[grpNum] = combinedEdges
|
|
faceGroups[grpNum] += faceGroups[compareNum]
|
|
existingGroups[compareNum] = false
|
|
repeatLoop = true
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
-- Keep only the combined facegroups:
|
|
local faceGroups = for n = 1 to faceGroups.count where existingGroups[n] collect faceGroups[n]
|
|
|
|
struct faceEdgeData (faceNum, pos, faceEdges, faceVerts = #(1,2,3,4), neighbours, xSize, ySize)
|
|
|
|
for faceNums in faceGroups do
|
|
(
|
|
-- Work out 2d positions for each quad:
|
|
|
|
local faceEdgeBits = for faceNum in faceNums collect (faceEdges[faceNum] as bitarray)
|
|
|
|
-- Make array with initial face:
|
|
local faceInfoArray = for faceNum in faceNums collect (faceEdgeData faceNum:faceNum faceEdges:faceEdges[faceNum])
|
|
faceInfoArray[1].pos = [0,0]
|
|
local doneFaces = #{}
|
|
local toDofaces = #{1}
|
|
|
|
local minPos = [0,0]
|
|
local maxPos = [0,0]
|
|
|
|
local adjFaceNum, adjFaceInfo, adjPos, adjFaceEdges, newEdgeList, neighbourNum, rotateVal
|
|
|
|
while (toDofaces.numberSet != 0) do
|
|
(
|
|
for toDoNum in toDofaces do
|
|
(
|
|
toDofaces[toDoNum] = false
|
|
doneFaces[toDoNum] = true
|
|
|
|
local faceInfo = faceInfoArray[toDoNum]
|
|
|
|
faceInfo.xSize = 0.5 * (edgeLengths[faceInfo.faceEdges[1]] + edgeLengths[faceInfo.faceEdges[3]])
|
|
faceInfo.ySize = 0.5 * (edgeLengths[faceInfo.faceEdges[2]] + edgeLengths[faceInfo.faceEdges[4]])
|
|
|
|
neighbourNum = 0
|
|
faceInfo.neighbours = for edgeNum in faceInfo.faceEdges collect
|
|
(
|
|
neighbourNum += 1
|
|
|
|
-- Find faces sharing this face's edges:
|
|
adjFaceNum = undefined
|
|
for n = 1 to faceInfoArray.count
|
|
where faceEdgeBits[n][edgeNum] and (n != toDoNum)
|
|
while (adjFaceNum == undefined) do
|
|
(
|
|
adjFaceNum = n
|
|
)
|
|
|
|
-- Set up neighbour-face info, if it hasn't been done already:
|
|
if (adjFaceNum != undefined) and not doneFaces[adjFaceNum] and not toDofaces[adjFaceNum] do
|
|
(
|
|
toDofaces[adjFaceNum] = true
|
|
adjFaceInfo = faceInfoArray[adjFaceNum]
|
|
adjFaceEdges = adjFaceInfo.faceEdges
|
|
|
|
-- Rotate neighbour edge-lists to match source-face's alignment:
|
|
rotateVal = (findItem adjFaceEdges edgeNum) - #(3,4,1,2)[neighbourNum]
|
|
if (rotateVal != 0) do
|
|
(
|
|
rotateVal = (mod (4 + rotateVal) 4) as integer
|
|
newEdgeList = for n = (rotateVal + 1) to 4 collect adjFaceEdges[n]
|
|
join newEdgeList (for n = 1 to rotateVal collect adjFaceEdges[n])
|
|
|
|
adjFaceInfo.faceEdges = newEdgeList
|
|
|
|
adjFaceInfo.faceVerts = case rotateVal of
|
|
(
|
|
1:#(2,3,4,1)
|
|
2:#(3,4,1,2)
|
|
3:#(4,1,2,3)
|
|
)
|
|
)
|
|
|
|
-- Set neighbour's grid-position:
|
|
adjPos = faceInfo.pos + #([0,-1],[1,0],[0,1],[-1,0])[neighbourNum]
|
|
adjFaceInfo.pos = adjPos
|
|
|
|
if (adjPos.x < minPos.x) do (minPos.x = adjPos.x)
|
|
if (adjPos.y < minPos.y) do (minPos.y = adjPos.y)
|
|
if (adjPos.x > maxPos.x) do (maxPos.x = adjPos.x)
|
|
if (adjPos.y > maxPos.y) do (maxPos.y = adjPos.y)
|
|
)
|
|
|
|
adjFaceNum
|
|
)
|
|
)
|
|
)
|
|
|
|
-- Get rid of faces that weren't processed for some reason:
|
|
for item in faceInfoArray where item.pos == undefined do useFaces[item.faceNum] = false
|
|
faceInfoArray = for item in faceInfoArray where item.pos != undefined collect item
|
|
|
|
-- Shift face-array position-values so that minimum is at [1,1]
|
|
for item in faceInfoArray do
|
|
(
|
|
item.pos -= (minPos - [1,1])
|
|
)
|
|
maxPos -= (minPos - [1,1])
|
|
|
|
-- Get heights/widths for each quad column/row:
|
|
local columnWidths = for n = 1 to maxPos.x collect #()
|
|
local rowHeights = for n = 1 to maxPos.y collect #()
|
|
|
|
for item in faceInfoArray do
|
|
(
|
|
append columnWidths[item.pos.x] item.xSize
|
|
append rowHeights[item.pos.y] item.ySize
|
|
)
|
|
|
|
-- Average the quad colum/row sizes:
|
|
local sumSize
|
|
columnWidths = for n = 1 to columnWidths.count collect
|
|
(
|
|
sumSize = 0.0
|
|
for item in columnWidths[n] do
|
|
(
|
|
sumSize += item
|
|
)
|
|
sumSize / columnWidths[n].count
|
|
)
|
|
rowHeights = for n = 1 to rowHeights.count collect
|
|
(
|
|
sumSize = 0.0
|
|
for item in rowHeights[n] do
|
|
(
|
|
sumSize += item
|
|
)
|
|
sumSize / rowHeights[n].count
|
|
)
|
|
|
|
local xPositions = #(0.0)
|
|
local yPositions = #(0.0)
|
|
for n = 1 to columnWidths.count do
|
|
(
|
|
append xPositions (xPositions[n] + columnWidths[n])
|
|
)
|
|
for n = 1 to rowHeights.count do
|
|
(
|
|
append yPositions (yPositions[n] + rowHeights[n])
|
|
)
|
|
|
|
local vertsToWeld = #{}
|
|
|
|
-- Apply new grid-positions to UV verts:
|
|
local minVertPos, maxVertPos, vertPositions
|
|
for faceInfo in faceInfoArray do
|
|
(
|
|
minVertPos = [xPositions[faceInfo.pos.x], yPositions[faceInfo.pos.y],0]
|
|
maxVertPos = [xPositions[faceInfo.pos.x + 1], yPositions[faceInfo.pos.y + 1],0]
|
|
|
|
vertPositions = #(minVertPos, [maxVertPos.x ,minVertPos.y, 0], maxVertPos, [minVertPos.x ,maxVertPos.y, 0])
|
|
|
|
for n = 1 to 4 do
|
|
(
|
|
newUVmod.setFaceVertex vertPositions[n] faceInfo.faceNum faceInfo.faceVerts[n] false
|
|
|
|
vertsToWeld[newUVmod.getVertexIndexFromFace faceInfo.faceNum n] = true
|
|
)
|
|
)
|
|
|
|
newUVmod.selectVertices vertsToWeld
|
|
newUVmod.weldSelected()
|
|
)
|
|
|
|
-- Select the affected faces
|
|
newUVmod.selectPolygonsUpdate useFaces true
|
|
|
|
newUVmod.setTVSubObjectMode 3
|
|
redrawViews()
|
|
)
|
|
)
|
|
|
|
OK
|
|
)
|
|
|