Align and Size a Plane() to EPoly Quads...

Become a member of the CGSociety

Connect, Share, and Learn with our Large Growing CG Art Community. It's Free!

THREAD CLOSED
 
Thread Tools Search this Thread Display Modes
Old 10 October 2012   #1
Align and Size a Plane() to EPoly Quads...

I have a MXS function that is supposed to create Plane() primitives that align with rectangular quads on EPoly objects and make the Plane match the size of the quad. My problem is determining the the Length/Width of the Plane--I can get the correct values for length and width I cannot figure out how to determine which is actually the length and the width (for example, the value I get for width sometimes belongs to length and vice versa).

Here is the function:


function wallworm_create_plane_from_polygon polynode faceId forceQuad:true power:2 = (
 if ww_wwdt_control_mesh == undefined then (
  in coordsys world (
   if classOf polynode == editable_poly then (
 
	--verts = polyop.getVertsUsingFace polynode #{faceId}
	verts = polyop.getFaceVerts polynode faceId
 
	if verts.count == 4 OR forceQuad==false then (
 
 
	 v1 = polyop.getVert polynode verts[1] node:polynode
	 v2 = polyop.getVert polynode verts[2] node:polynode
	 v3 = polyop.getVert polynode verts[3] node:polynode
 
	 v4 = polyop.getVert polynode verts[4] node:polynode
 
	 d1 = distance (v1) (v2) 
	 d2 = distance (v2) (v3) 
 
	 --segs = ww_wwdt_vmfpowertosegs power
	 --func not present in sample... assign manually
	 segs = 4
 
	 l = d2
	 w=d1
 
	 faceNormal = in coordsys polynode (polyop.getFaceNormal polynode faceId node:polynode)
	 local brsh = Plane length:l width:w isSelected:off lengthsegs:1 widthsegs:1 pos:(polyop.getSafeFaceCenter polynode faceId node:polynode)
 
	 /*
	 worldUpVector = [0,0,1] 
	 rightVector = normalize (cross worldUpVector faceNormal) 
	 upVector = normalize ( cross rightVector faceNormal )
	 theMatrix = matrix3 rightVector upVector faceNormal [0,0,0] 
	 brsh.transform =  theMatrix
	 */
 
 
	 --Move the new mesh to the center of the face.
	 brsh.pos = (polyop.getSafeFaceCenter polynode faceId node:polynode) 
 
	 --Make the new mesh face in the direction of the face
	 brsh.dir = faceNormal
 
	 --make a copy of the new mesh to determine if the verts of the mesh are aligned to verts of the original face.
	 --This does assume rectangular faces.
	 tmp = copy brsh
	 convertToPoly tmp
 
	 tmpverts = polyop.getFaceVerts tmp 1
 
	 tmpv1 = polyop.getVert tmp tmpverts[1] node:tmp
	 nverts = #(v1,v2,v3,v4)
 
	 format "\n###############\nFace Verts: % % % %\n" v1 v2 v3 v4
	 format "New Verts: %\n" tmpv1 
 
	 /*
	 See if the first vert in the tmp mesh aligns with a vert in the original face.
	 If none, swap the length and width.
	 */	 
	 if  findItem nverts tmpv1 == 0  then (
	  print "changing l/w"
	  brsh.length = w
	  brsh.width = l
	 )
	 delete tmp
	 brsh.lengthsegs = segs
	 brsh.widthsegs = segs
 
	 if polynode.mat != undefined then brsh.mat = polynode.mat
	 return brsh
 
	) else (
	 format "The selected face % has % verts!\n" faceId verts.count
 
	)  
 
 
   ) else (
 
 
 
   )
  )
 )
 undefined
)
 
 


I have assumed that the following code would determine if the plane dimensions match the face... but it simply fails sometimes:


 
 if  findItem nverts tmpv1 == 0  then (
      print "changing l/w"
      brsh.length = w
      brsh.width = l
     )
 


What is odd is that the findItem sometimes (but not always) fails when the values look identical to me... for example, here is a line in the listener from a failure:


###############
Face Verts: [-70,146,128] [-70,146,256] [-70,274,256] [-70,274,128]
New Verts: [-70,274,256]
"changing l/w"
 


But as you can see, the Point in New Verts [-70,274,256] does exist in the Face Verts... but the findItem function returns 0 (and the script fails).

Maybe I should try another approach altogehter... but I still want to know how that fails.

Question 2:

Also, while discussing this, which of the following two methods is best for the orientation? I always see docs mentioning the first but the second seems to produce the same results:

Method 1:

worldUpVector = [0,0,1] 
     rightVector = normalize (cross worldUpVector faceNormal) 
     upVector = normalize ( cross rightVector faceNormal )
     theMatrix = matrix3 rightVector upVector faceNormal [0,0,0] 
     brsh.transform =  theMatrix
 
 --Move the new mesh to the center of the face.
     brsh.pos = (polyop.getSafeFaceCenter polynode faceId node:polynode)  


Method 2:

--Move the new mesh to the center of the face.
     brsh.pos = (polyop.getSafeFaceCenter polynode faceId node:polynode) 
 
     --Make the new mesh face in the direction of the face
     brsh.dir = faceNormal
__________________
Shawn Olson
Autodesk Expert Elite
3ds Max Charter Member

Developer of:
Wall Worm Tools for the Source Game Engine
CorVex Level Design Plugin

Last edited by wallworm : 10 October 2012 at 07:40 PM. Reason: clarification
 
Old 10 October 2012   #2
Hi, Shawn!
This
findItem sometimes (but not always) fails

happens to me sometimes. I think(but I am not sure) that max prints
[-70,274,256], but the real values is
[-70.0001,274,256] or something like this. And when two point3 values are compared, the findItem fails.
The maxscript Pro guys will give you the best advice, but you can try to compare values, using
close_enough
 
Old 10 October 2012   #3
Another stupid idea - convert the positions of the verts to strings and then use findItem.
 
Old 10 October 2012   #4
Originally Posted by wallworm: I have a MXS function that is supposed to create Plane() primitives that align with rectangular quads on EPoly objects and make the Plane match the size of the quad.

what if the quad is not a perfect rectangle (not-flat or oblique-angled)? how should the plane be aligned in this case? what priorities are?
 
Old 10 October 2012   #5
@Kostadin ... thanks for those ideas. I started to use the close_enough() approach but while doing it I thought of just checking to see if the distance is closer than 0.5 ... so in the example above, I used this:


if distance v1 tmpv1 < 0.1 OR distance v2 tmpv1 < 0.1 OR distance v3 tmpv1  < 0.1   OR distance v4 tmpv1  < 0.1  then (
  --the length and width are correct
) else (
  --the length and width need to be swapped
)


Of course, it makes assumptions. For example... if the length and width are within 0.1 units it will probably fail. But for the moment it meets my needs.

@Denis ... I'm not really certain about what to do in the case of a non-flat surface. But I do want to find a way to get the Plane object to match the shape of the underlying face (but always remain planar). Off the top of my head, I might apply a FFD2x2x2 and make the corners align.

The reason I am starting with a Plane primitive is that the target geometry needs to always be a plane with 4, 8 or 16 widthsegs and lengthsegs ... and I think it will be easier to make a plane and deform the outline to a quad face with FFD than to try and calculate where the positions of the verts would be for an object created from scratch; plus... all of the functions used for this geometry all assume a certain ordering of the verts--which matches that of a Plane converted to EPoly.
__________________
Shawn Olson
Autodesk Expert Elite
3ds Max Charter Member

Developer of:
Wall Worm Tools for the Source Game Engine
CorVex Level Design Plugin

Last edited by wallworm : 10 October 2012 at 12:26 AM. Reason: fixed typo
 
Old 10 October 2012   #6
Yeah, FFD sounds like a good idea/approach.

If u did it that way, Length and Width might not matter as much, but then its more of just putting the FFD points in the right spots/getting the plane facing the right direction.
__________________
http://matthewlichy.com

 
Old 10 October 2012   #7
Originally Posted by Kickflipkid687: Yeah, FFD sounds like a good idea/approach.

If u did it that way, Length and Width might not matter as much, but then its more of just putting the FFD points in the right spots/getting the plane facing the right direction.


Yeah... that's what I'm thinking. I played with it a little earlier today and think it should be straight forward.
__________________
Shawn Olson
Autodesk Expert Elite
3ds Max Charter Member

Developer of:
Wall Worm Tools for the Source Game Engine
CorVex Level Design Plugin
 
Old 10 October 2012   #8
The hard part, maybe, might be getting the points to form a square/rectangle and not criss-cross at the end and form an X.

I had this issue before when trying to create new polys from verts. I'm not sure how u can easily fix that, but maybe you know.
__________________
http://matthewlichy.com

 
Old 10 October 2012   #9
Using the FFD concept has become a little trickier than I thought. I found this nifty set of functions ( http://forums.cgsociety.org/archive...p/t-704392.html ) to help along the project, and I see that there is already a script on SP called FFD2Quad that has the functionality that I want generally. After looking through the code for FFD2Quad I see he used the functions linked above also.

FFD2Quad has a lot more going on that what I need... so I'm trying to filter it down to the simplest form. But I cannot seem to figure it out...

Here is the sample code I have so far (warning ... script deletes all object in current scene):


 

-- these functions from http://forums.cgsociety.org/archive...p/t-704392.html
-- convert world coordinates to FFD local (normalized) coordinates
-- obj = object containing the modifier
-- ffdmod = the actual modifier
-- pos = the world coordinate
fn wallworm_ffdWorldToLocalPos obj ffdmod pos = (
 objTM = obj.objecttransform
 modTM =  (getModContextTM obj ffdmod) * ffdmod.lattice_transform.value
 modBBMin = getModContextBBoxMin obj ffdmod
 modBBMax = getModContextBBoxMax obj ffdmod
 (pos - modBBMin) * (inverse objTM) * inverse modTM / (modBBMax-modBBMin)
)
-- set an FFD mod's control point's world coordinate
-- obj = object containing the modifier
-- ffdmod = the actual modifier
-- i = control point index
-- pos = new world position
fn wallworm_ffdSetWorldPos obj ffdmod i pos = (
 cp = ffdmod["Master"][i]
 ps = wallworm_ffdWorldToLocalPos obj ffdmod pos
 cp.value = ps
)
/*End  funcs from ZeBoxx2*/
 
actionMan.executeAction 0 "40021"  -- Selection: Select All
delete $

clearlistener()
a = Box length: 64 width:64 height:64 
tp = Taper amount:-0.7
addmodifier a tp
convertToPoly a
 
for f = 1 to a.numfaces do (
pos = polyop.getFaceCenter a f node:a
 
b=Plane pos:pos mapCoords:true lengthsegs:4 widthsegs:4
b.dir = polyop.getFaceNormal a f node:a
 
ffd=FFD2x2x2 ()
 
addModifier b ffd
 
--conformToShape ffd
--ffd.deformType  = 1
 
animateVertex ffd #all 
face = polyop.getFaceVerts a f
 
in coordsys world ( 
v1 = polyop.getVert a face[1] node:a
v2 = polyop.getVert a face[2] node:a
v3 = polyop.getVert a face[3] node:a
v4 = polyop.getVert a face[4] node:a
)
format "############\nFace %\t%\nv1\t%\nv2\t%\nv3\t%\nv4\t%\n\n" f face v1 v2 v3 v4
wallworm_ffdSetWorldPos b ffd 1 v1
/*
wallworm_ffdSetWorldPos b ffd 1 v2
wallworm_ffdSetWorldPos b ffd 1 v3
wallworm_ffdSetWorldPos b ffd 1 v4
*/
format "Control Points\n1\t%\n2\t%\n3\t%\n4\t%\n5\t%\n6\t%\n7\t%\n  8\t%\n"  ffd.control_point_1  ffd.control_point_2  ffd.control_point_3  ffd.control_point_4  ffd.control_point_5  ffd.control_point_6  ffd.control_point_7  ffd.control_point_8
)

 


No matter which FFD control point I choose, it never aligns to the verts (v1, v2, v3 and v4). Any input?
__________________
Shawn Olson
Autodesk Expert Elite
3ds Max Charter Member

Developer of:
Wall Worm Tools for the Source Game Engine
CorVex Level Design Plugin
 
Old 10 October 2012   #10
i really don't understand the idea with FFD. everything seems overcomplicated.
here is how i see it:

 fn alignToQuad node:selection[1] face:undefined = 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]
 		
 		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:1 lengthsegs:1 transform:tm
 	)
 )
 
 /*
 delete objects
 b = box length:64 width:64 height:32
 addmodifier b (taper amount:-0.7)
 convertToPoly b
 for f in b.faces do alignToQuad node:b face:f.index
 */
 


you can add some extra logic... let's say the width is always shorter than length. in this case you have to check distances between v1,v2,v3.

Last edited by denisT : 10 October 2012 at 03:23 PM.
 
Old 10 October 2012   #11
but the correct way is to find the best BBOX around the quad and use its min/max as values for width/length
 
Old 10 October 2012   #12
Denis,

Thanks for responding. Aligning the planes isn't the issue now... I am trying to take it a step further and force the plane to match the shape of the quad too. That is where the FFD comes in.
__________________
Shawn Olson
Autodesk Expert Elite
3ds Max Charter Member

Developer of:
Wall Worm Tools for the Source Game Engine
CorVex Level Design Plugin
 
Old 10 October 2012   #13
Originally Posted by wallworm: Aligning the planes isn't the issue now... I am trying to take it a step further and force the plane to match the shape of the quad too. That is where the FFD comes in.

could you post the image that shows how planes should be aligned and deformed in your sample?
 
Old 10 October 2012   #14
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.
Attached Images
File Type: jpg quadplaneexample.jpg (37.7 KB, 18 views)
__________________
Shawn Olson
Autodesk Expert Elite
3ds Max Charter Member

Developer of:
Wall Worm Tools for the Source Game Engine
CorVex Level Design Plugin
 
Old 10 October 2012   #15
Originally Posted by wallworm: 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.

is it not easier to equally divide the quad and flatten it?
 
Thread Closed share thread



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
CGSociety
Society of Digital Artists
www.cgsociety.org

Powered by vBulletin
Copyright 2000 - 2006,
Jelsoft Enterprises Ltd.
Minimize Ads
Forum Jump
Miscellaneous

All times are GMT. The time now is 02:43 PM.


Powered by vBulletin
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.