forked from bartvdbraak/blender
fix [#36020] SmartUV Project is messy on a cube
was using very simple/stupid check to rotate us islands, replace with box_fit_2d() function. missed docstring last commit.
This commit is contained in:
parent
e0b2111942
commit
2f6c748bb9
@ -24,7 +24,6 @@ from bpy.types import Operator
|
|||||||
|
|
||||||
DEG_TO_RAD = 0.017453292519943295 # pi/180.0
|
DEG_TO_RAD = 0.017453292519943295 # pi/180.0
|
||||||
SMALL_NUM = 0.0000001 # see bug [#31598] why we dont have smaller values
|
SMALL_NUM = 0.0000001 # see bug [#31598] why we dont have smaller values
|
||||||
BIG_NUM = 1e15
|
|
||||||
|
|
||||||
global USER_FILL_HOLES
|
global USER_FILL_HOLES
|
||||||
global USER_FILL_HOLES_QUALITY
|
global USER_FILL_HOLES_QUALITY
|
||||||
@ -233,110 +232,16 @@ def islandIntersectUvIsland(source, target, SourceOffset):
|
|||||||
return 0 # NO INTERSECTION
|
return 0 # NO INTERSECTION
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Returns the X/y Bounds of a list of vectors.
|
|
||||||
def testNewVecLs2DRotIsBetter(vecs, mat=-1, bestAreaSoFar = -1):
|
|
||||||
|
|
||||||
# UV's will never extend this far.
|
|
||||||
minx = miny = BIG_NUM
|
|
||||||
maxx = maxy = -BIG_NUM
|
|
||||||
|
|
||||||
for i, v in enumerate(vecs):
|
|
||||||
|
|
||||||
# Do this along the way
|
|
||||||
if mat != -1:
|
|
||||||
v = vecs[i] = mat * v
|
|
||||||
x= v.x
|
|
||||||
y= v.y
|
|
||||||
if x<minx: minx= x
|
|
||||||
if y<miny: miny= y
|
|
||||||
if x>maxx: maxx= x
|
|
||||||
if y>maxy: maxy= y
|
|
||||||
|
|
||||||
# Specific to this algo, bail out if we get bigger then the current area
|
|
||||||
if bestAreaSoFar != -1 and (maxx-minx) * (maxy-miny) > bestAreaSoFar:
|
|
||||||
return (BIG_NUM, None), None
|
|
||||||
w = maxx-minx
|
|
||||||
h = maxy-miny
|
|
||||||
return (w*h, w,h), vecs # Area, vecs
|
|
||||||
|
|
||||||
def optiRotateUvIsland(faces):
|
def optiRotateUvIsland(faces):
|
||||||
global currentArea
|
uv_points = [uv for f in faces for uv in f.uv]
|
||||||
|
angle = geometry.box_fit_2d(uv_points)
|
||||||
|
|
||||||
# Best-fit Rotation
|
if angle != 0.0:
|
||||||
def best2dRotation(uvVecs, MAT1, MAT2):
|
mat = Matrix.Rotation(angle, 2)
|
||||||
global currentArea
|
|
||||||
|
|
||||||
newAreaPos, newfaceProjectionGroupListPos =\
|
|
||||||
testNewVecLs2DRotIsBetter(uvVecs[:], MAT1, currentArea[0])
|
|
||||||
|
|
||||||
|
|
||||||
# Why do I use newpos here? May as well give the best area to date for an early bailout
|
|
||||||
# some slight speed increase in this.
|
|
||||||
# If the new rotation is smaller then the existing, we can
|
|
||||||
# avoid copying a list and overwrite the old, crappy one.
|
|
||||||
|
|
||||||
if newAreaPos[0] < currentArea[0]:
|
|
||||||
newAreaNeg, newfaceProjectionGroupListNeg =\
|
|
||||||
testNewVecLs2DRotIsBetter(uvVecs, MAT2, newAreaPos[0]) # Reuse the old bigger list.
|
|
||||||
else:
|
|
||||||
newAreaNeg, newfaceProjectionGroupListNeg =\
|
|
||||||
testNewVecLs2DRotIsBetter(uvVecs[:], MAT2, currentArea[0]) # Cant reuse, make a copy.
|
|
||||||
|
|
||||||
|
|
||||||
# Now from the 3 options we need to discover which to use
|
|
||||||
# we have cerrentArea/newAreaPos/newAreaNeg
|
|
||||||
bestArea = min(currentArea[0], newAreaPos[0], newAreaNeg[0])
|
|
||||||
|
|
||||||
if currentArea[0] == bestArea:
|
|
||||||
return uvVecs
|
|
||||||
elif newAreaPos[0] == bestArea:
|
|
||||||
uvVecs = newfaceProjectionGroupListPos
|
|
||||||
currentArea = newAreaPos
|
|
||||||
elif newAreaNeg[0] == bestArea:
|
|
||||||
uvVecs = newfaceProjectionGroupListNeg
|
|
||||||
currentArea = newAreaNeg
|
|
||||||
|
|
||||||
return uvVecs
|
|
||||||
|
|
||||||
|
|
||||||
# Serialized UV coords to Vectors
|
|
||||||
uvVecs = [uv for f in faces for uv in f.uv]
|
|
||||||
|
|
||||||
# Theres a small enough number of these to hard code it
|
|
||||||
# rather then a loop.
|
|
||||||
|
|
||||||
# Will not modify anything
|
|
||||||
currentArea, dummy =\
|
|
||||||
testNewVecLs2DRotIsBetter(uvVecs)
|
|
||||||
|
|
||||||
|
|
||||||
# Try a 45d rotation
|
|
||||||
newAreaPos, newfaceProjectionGroupListPos = testNewVecLs2DRotIsBetter(uvVecs[:], ROTMAT_2D_POS_45D, currentArea[0])
|
|
||||||
|
|
||||||
if newAreaPos[0] < currentArea[0]:
|
|
||||||
uvVecs = newfaceProjectionGroupListPos
|
|
||||||
currentArea = newAreaPos
|
|
||||||
# 45d done
|
|
||||||
|
|
||||||
# Testcase different rotations and find the one that best fits in a square
|
|
||||||
for ROTMAT in RotMatStepRotation:
|
|
||||||
uvVecs = best2dRotation(uvVecs, ROTMAT[0], ROTMAT[1])
|
|
||||||
|
|
||||||
# Only if you want it, make faces verticle!
|
|
||||||
if currentArea[1] > currentArea[2]:
|
|
||||||
# Rotate 90d
|
|
||||||
# Work directly on the list, no need to return a value.
|
|
||||||
testNewVecLs2DRotIsBetter(uvVecs, ROTMAT_2D_POS_90D)
|
|
||||||
|
|
||||||
|
|
||||||
# Now write the vectors back to the face UV's
|
|
||||||
i = 0 # count the serialized uv/vectors
|
i = 0 # count the serialized uv/vectors
|
||||||
for f in faces:
|
for f in faces:
|
||||||
#f.uv = [uv for uv in uvVecs[i:len(f)+i] ]
|
|
||||||
for j, k in enumerate(range(i, len(f.v) + i)):
|
for j, k in enumerate(range(i, len(f.v) + i)):
|
||||||
f.uv[j][:] = uvVecs[k]
|
f.uv[j][:] = mat * uv_points[k]
|
||||||
i += len(f.v)
|
i += len(f.v)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1507,12 +1507,12 @@ static PyObject *M_Geometry_box_pack_2d(PyObject *UNUSED(self), PyObject *boxlis
|
|||||||
PyDoc_STRVAR(M_Geometry_box_fit_2d_doc,
|
PyDoc_STRVAR(M_Geometry_box_fit_2d_doc,
|
||||||
".. function:: box_fit_2d(points)\n"
|
".. function:: box_fit_2d(points)\n"
|
||||||
"\n"
|
"\n"
|
||||||
" Returns a list of indices into the list given\n"
|
" Returns an angle that best fits the points to an axis aligned rectangle\n"
|
||||||
"\n"
|
"\n"
|
||||||
" :arg points: list of 2d points.\n"
|
" :arg points: list of 2d points.\n"
|
||||||
" :type points: list\n"
|
" :type points: list\n"
|
||||||
" :return: a list of indices\n"
|
" :return: angle\n"
|
||||||
" :rtype: list of ints\n"
|
" :rtype: float\n"
|
||||||
);
|
);
|
||||||
static PyObject *M_Geometry_box_fit_2d(PyObject *UNUSED(self), PyObject *pointlist)
|
static PyObject *M_Geometry_box_fit_2d(PyObject *UNUSED(self), PyObject *pointlist)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user