[Closed] Align and Size a Plane() to EPoly Quads…
could you post the image that shows how planes should be aligned and deformed in your sample?
Attached is an example … on the left is where the planes are aligned to quads only… whereas on the right is how those planes should be.
It’s something I thought about… but the functions I am using already presume Plane() primitives as input objects (later down the road) … so if I can figure out how to properly apply the FFD it will serve to 1) save me recoding other things and 2) teach me a little more about how the FFD works.
Well I would like help… as I’ve already pounded my head on the issue quite a bit. Sometimes seeing a solution is just as educational as figuring it out.
Because I could not figure out how to properly align the FFD control points, I started down another avenue (which is promising but has one major problem). I decided that I could just detach the faces as individual objects and tesselate them to my needs as the tesselation can create the same kind of geometry*.
*The problem is that the ordering of the vertices is very important and must match those of a Plane() that is converted to EPoly (where the bottom row is verts 1…5, row 2 is 6…10, etc). Unfortunately, when I use tessellate, that ordering is entirely wrong. And I know of no way to re-order verts.
So my next step was to do that tesselation and also create a plane (which is where the code below stops). The next step is going to be mapping the verts from tesselated quads to corresponding verts in the Plane… then moving the plane verts to those positions and deleting the tessellated mesh. That seems like a lot of steps (and depends on the tessellation providing consistent vertex ordering… which I have to test and figure out).
In the end, I am leaning toward the FFD being the easiest method (except that I cannot properly place the FFD control points… which is why I have been experimenting with other ideas).
clearlistener()
a = Box length: 64 width:64 height:64
a.wirecolor = green
tp = Taper amount:-0.7
addmodifier a tp
convertToPoly a
power = 2
for p = 1 to polyop.getNumFaces a do (
newName = UniqueName "CutFace"
polyop.detachFaces a #{p} asNode:true delete:false name:(newName)
thenode = getNodeByName newName
thenode.wirecolor = red
thenode.tesselateBy = 0
thenode.tessTension = 0.0
base = 1
for its = 1 to power do (
polyop.tessellateByFace thenode #all
base *= 2 -- set the lengthsegs of plane below
)
vv = polyop.getfaceverts a p
v1 = polyop.getvert a vv[1]
v2 = polyop.getvert a vv[2]
v3 = polyop.getvert a vv[3]
v4 = polyop.getvert a vv[4]
front = normalize (v1-v2)
side = normalize (v2-v3)
up = normalize (cross front side)
side = normalize (cross up front)
tm = matrix3 front side up v1
w = (v2*(inverse tm)).x
l = (v3*(inverse tm)).y
tm = pretranslate tm [w/2, l/2, 0]
p = plane width:w length:l widthsegs:base lengthsegs:base transform:tm
p.name = uniqueName "PlaneAligned"
p.wirecolor = blue
convertToPoly p
)
fn worldPointToFFD p ffd pos =
(
otm = p.objecttransform
mtm = (getModContextTM p ffd)*ffd.lattice_transform.value
bmin = getModContextBBoxMin p ffd
bmax = getModContextBBoxMax p ffd
v = (pos * (inverse otm) * mtm - bmin)/(bmax - bmin)
v.z = 0
v
)
fn alignPlaneToQuad node:selection[1] face:undefined planeDimension:[1,1] = if iskindof node Editable_Poly do
(
if face == undefined and node.selectedfaces.count > 0 do face = node.selectedfaces[1].index
if face != undefined and (vv = polyop.getfaceverts node face).count == 4 do
(
v1 = polyop.getvert node vv[1]
v2 = polyop.getvert node vv[2]
v3 = polyop.getvert node vv[3]
v4 = polyop.getvert node vv[4]
front = normalize (v1-v2)
side = normalize (v2-v3)
up = polyop.getfacenormal node face
center = polyop.getfacecenter node face
tm = orthogonalize (matrix3 front side up center)
tm = pretranslate tm [0.5, 0.5, 0]
p = plane width:1 length:1 widthsegs:planeDimension.x lengthsegs:planeDimension.y transform:tm
ffd = FFDBox deformType:1 tension:25.0 continuity:0.0
setDimensions ffd [2,2,2]
animateall ffd
addmodifier p ffd
modpanel.setcurrentobject ffd
ffd.control_point_1 = ffd.control_point_5 = worldPointToFFD p ffd v3
ffd.control_point_2 = ffd.control_point_6 = worldPointToFFD p ffd v4
ffd.control_point_3 = ffd.control_point_7 = worldPointToFFD p ffd v2
ffd.control_point_4 = ffd.control_point_8 = worldPointToFFD p ffd v1
p
)
)
/*
delete objects
b = box length:64 width:64 height:32
addmodifier b (taper amount:-0.7)
convertToPoly b
--polyop.deletefaces b #{1..5}
update b
max modify mode
for f in b.faces do alignPlaneToQuad node:b face:f.index planeDimension:[4,4]
*/
all FFD operations have to be in Modify Panel. you can find a code in this forum how to disable the panel redraw.
Denis… you a true Master! Thank you for your expertise
Now I have to absorb it.
Can you explain the function worldPointToFFD ? what is this line:
for k=1 to 3 where not (bit.isFinite v[k]) do v[k] = 0
This is when max prints 1.23456e-5 or 1.#INF. In this case bit.isFinite sets the value of the variable to 0.
Wow… I wish I knew that a year ago. I have had problems detecting 1.#INF in a couple circumstances in the past.
That’s OK. That it works is all I care about and it’s up to the user to be mindful of not applying this to a 10,000 quad object In my own use, it will generally only be processing a few dozen quads at a time at most… so it works just great!
Thank you again!
PS. When are you going to Program the Matrix interface (from the movie) where we can all just download knowledge!?!?
i’ve changed this line. i set only v.z to ZERO. which only makes sense. bbox in Z axis is 0
the thing becomes more complicated if we try to align to not flatten quad. the algorithm stops work in this case:
delete objects
b = box length:64 width:64 height:32
addmodifier b (taper amount:-0.7)
addmodifier b (bend angle:45)
convertToPoly b
--polyop.deletefaces b #{1..5}
update b
max modify mode
pp = for f in b.faces collect alignPlaneToQuad node:b face:f.index planeDimension:[4,4]
Yes… this is definitely an issue … that is something for me to consider later as this helpful as is for the moment.
the old algorithm stops, but the new one works great.
there are some hints:
do we really need to align the plane to the quad if we use FFD anyway?
if we nevertheless want to have the ‘aligned-like’ transform for our plane could we do it after the FFD applied?
but you have to understand that it’s really slow(!) algorithm. any moving FFD points is slow!
Are the FFD modified Planes still Planar in this? That would be spectacular! For what I needed this the planes must remain planar or they won’t be valid geometry for the game engine exporter. If so, I’d love to see the new algorithm!
BTW, I’ve updated the WW Credits to reflect your contribution with this specific script. I also shared mention of your excellence in the 1.869 entry into the changelog.
Your consistent and insightful help is always deeply appreciated Denis!