[Closed] Size Object to Face?
Hello,
I’ve been trying to figure this one out for some days, and am stuck. I got something kind of working… but my math/the way I’m doing it is not right…
This is the first time I’m trying something like this, so am a bit out of my element. :banghead:
If the face I am sizing to, is more square, it seems to work…, but if it’s a longer triangle/face, it’s too large in the end.
I am very bad at math/dealing with these scale/rotate things usually, but am slowly picking things up… But this one is really confusing me.
I tried to look at the Face Area, and now in this case, was getting the average faces edge length and tried using that…
My goal is to size the object to the face/faces average size, really just in 1 Axis, like X, then ideally scale Y/Z proportionally to that.
So if the user started with a non-uniform scaled object, it would size to the face, but keep that non-uniform/proportions. Which might make things trickier yet…
Any thoughts?
Thank you!
Edit: I was not trying to keep non-uniform below, but like I mentioned above, ideally it would…
(
t1 = $Box001
t1.transform = (matrix3 [1,0,0] [0,1,0] [0,0,1] [0,0,0])
sel = selection[1]
face = (polyop.getFaceSelection sel as array)[1]
faceNormal = polyop.GetFaceNormal sel face
faceCenter = polyop.getFaceCenter sel face
edges = polyop.getEdgesUsingFace sel face
averageEdgeLength = 0
for edge in Edges do
(
verts = (polyop.getVertsUsingEdge sel edge) as array
averageEdgeLength += distance (polyop.GetVert sel verts[2] node:selection) (polyop.GetVert sel verts[1] node:selection)
)
averageEdgeLength = averageEdgeLength/(Edges as array).count
size_t0 = [averageEdgeLength,averageEdgeLength,averageEdgeLength]
size_t1 = t1.max - t1.min
in coordsys world about t1.pos scale t1 (size_t0/size_t1)
t1.pos = faceCenter
t1.dir = faceNormal
)
You can also google for a script by Vitus called minimalBoundingBox. It’s great for that type of tasks
delete objects
b = box()
t = Teapot()
convertToPoly t
index = random 1 t.numfaces
polyop.setFaceSelection t index
n = polyop.getFaceNormal t index
fc = polyop.getFaceCenter t index
verts = for v in polyop.getFaceVerts t index collect polyop.getVert t v
vecZ = n
vecX = normalize(verts[2] - verts[1])
vecY = normalize(cross vecX vecZ)
tm = Matrix3 vecX vecY vecZ fc
pts = for v in verts collect (
v * (inverse tm)
)
_min = [1,1,1] * 1e6
_max = [1,1,1] * -1e6
for p in pts do (
if p[1] < _min[1] do _min[1] = p[1]
if p[2] < _min[2] do _min[2] = p[2]
if p[3] < _min[3] do _min[3] = p[3]
if p[1] > _max[1] do _max[1] = p[1]
if p[2] > _max[2] do _max[2] = p[2]
if p[3] > _max[3] do _max[3] = p[3]
)
ptsScale = _max - _min
bScale = b.max - b.min
b.transform = tm
in coordsys #local scale b [ (ptsScale / bScale).x, (ptsScale / bScale).y, 1.0 ]
Cool! Thank you! 😮
I did notice when I run it, if you change out the Teapot for a Sphere, it seems like the rotation / size are still a little off.
Unless something here at work is messing with it.
But on the sphere, it is slightly off in local Z rotation, and the size is a bit too large yet, in some cases.
Edit: hmmm… Or is just the fact that the faces are skewing on the sphere/tapering in.
Edit: Ah, I changed the verts to 1/4 for the X Vector compute, and that seems to have a better alignment on the sphere anyways.
it was using the side/angled edge before, making it seem more off.
Although i guess that’s not always consistent either…
As you can see from the code first two face verts are used as a x vector which can be not an optimal vector for a further bounding box calculations.
That’s the reason behind misalignment and size variation as I understand it.
Yeah… hmmmm… I mean, overall it works pretty well. Better than I had for sure. Very close/right on, most of the time. :buttrock:
For what I am doing it doesn’t have to be EXACT I guess…, but ideally exact or close as possible.
It’s mainly to get the objects generally scaled to the faces/per face, so then the user can modify after that. So they could rotate/scale/etc after the initial AutoScale.
Maybe what I should say, is not fit to Bounds, but Face Area…?
So if you have a square bounds box, and Align to a Face, it gets the Face selection Average Size/area? and Sizes based on that…?
More like the Left one than Right. Since if the user has a round bolt or something, right now it would get skewed/stretched.
Edit:
I got something working that I am happy with/matches the box example I have on the left in the image above.
I just ended up using the sqrt (faceArea), and Scaled in Local space by the computed X value, in all Axis, so was proportional. To keep existing non-uniform.
This is not super accurate, but like I said, good enough for me. To be truley accurate to fitting inside a face, would be alot of math/much more complicated it seems.
I found the method how to fit a box in a Right Triangle, but that’s only a fraction of the overall problem then.
My code is something like:
local faceArea = sqrt(polyop.getFaceArea sel face) --Need to add together/average if want multi faces, but this is for 1 face only here.
local faceSize = [faceArea,faceArea,faceArea]
local theObjSize = localBB[2] - localBB[1] ---NodeLocalBoundingBox. To get this to work right, i have to temp. reset the Rotation on it as well.
local theSize = (faceSize / theObjSize).x
--Scale all Axis by X, to keep Proportions / Possible Non-Uniform Scale
in coordsys #local scale theObj [ theSize, theSize, theSize ]