[Closed] Please help me out, basic matrix maths
I’m trying to learn how to work with matrices. My idea is to write a small script that takes in a poly face (quads only) and returns an array of the vertices in a sorted order (topleft, topright, bottomleft, bottomright). Originally I tried to us UV space to avoid dealing with matrices, but I didn’t realize it was too hard to get geom vertices from UV verts. So, I’m thinking the easiest way now would be to check the xyz positign of each geom vertex against the faceCenter with regards to its normal. But this is beyond my comprehension, Could some one explain (or show) how I would go about comparing/rotating a point3 array around the faceCenter/normal so that they can be easily compared relative to eachother?
follow the steps:
#1. use the face normal as matrix Up vector (Z)
#2. use vector from vertex #1 to vertex #2 (in the face build order) as matrix Front vector (Y)
#3. cross product of Front vector and Up vector gives you Right vector
#4. use the face center as matrix position, and Right, Front, Up vectors as axis
#5. following these steps you will get the face vertices in order: bottom-right, top-right, top-left, bottom-left.
If you got a poly created from plane primitive, the verts will be nicely numbered.
If you use the quadrify mesh modifier for example, the face numbers are shuffled and so are the normals per face. You can’t really reconstruct grid rows and columns only with the local face properties in this situation.
May be this is what you need:
(
if selection.count == 1 and classof selection[1] == Editable_poly do
(
local curObj = selection[1]
local selFace = polyOp.getFaceSelection curObj
local faceVerts = polyOp.getVertsUsingFace curObj selFace
gw.setTransform(Matrix3 1)
local vertPos2pX = #()
local vertPos2pY = #()
for v in faceVerts do
(
append vertPos2pX #(v,(gw.wTransPoint (polyOp.getVert curObj v))[1])
append vertPos2pY #(v,(gw.wTransPoint (polyOp.getVert curObj v))[2])
)
format "vertPos2pX: %
" vertPos2pX
format "vertPos2pY: %
" vertPos2pY
)
)
vertPos2pX contain arrays that contains vertex index and the screen X position of the vertex.
vertPos2pY contain arrays that contains vertex index and the screen Y position of the vertex.
Example:
vertPos2pX: #(#(19, 261.0), #(20, 319.0), #(24, 234.0), #(25, 291.0))
the first element of vertPos2pX meen:
vertex 19 with position of the screen x = 261.0
the second element:
vertex 20 with position of the screen x = 319.0
The screen 0,0 is in upper top left of the viewport.
Note that gw.wTransPoint wich convert world position of the vertex to screen position not work in max2012.
Thanks so much for the replies. I’ve been playing around with what the code can do. I had no idea I sort by the user viewport, this is a far better solution then anything I could of thought up. I’m also working on it using matrices, which is coming along slowly (I don’t exactly study mathematics in my free time). Thanks for the input! I ‘ll see what I can come up with.
okay, I got back to this script. It is working now how I envisioned. I am using 2012 so I had to wrap everything in redrawCallbacks, (also I think this won’t work in any previous max versions). I can’t imagine what sort of functionality the script could ever be used for, however I have plans on reusing the the quadSort function later on. Matrices…I’m still not getting it. Miauu great tip on the gw.wTransPoint
struct vertWithScreenPosition( screenPosition, geometryIndex)
XsortedVertices = #()
YsortedVertices = #()
clockworksort = #()
vertices = #()
fn sortClockwise = (
case of (
( YsortedVertices[1] == XsortedVertices[2] and YsortedVertices[2] == XsortedVertices[1]):
(
clockworksort[1] = YsortedVertices[2]
clockworksort[2] = YsortedVertices[1]
)
( YsortedVertices[1] == XsortedVertices[3] and YsortedVertices[2] == XsortedVertices[4]):
(
clockworksort[1] = YsortedVertices[1]
clockworksort[2] = YsortedVertices[2]
)
( YsortedVertices[1] == XsortedVertices[1] or YsortedVertices[1] == XsortedVertices[2]):
(
clockworksort[1] = YsortedVertices[1]
clockworksort[2] = YsortedVertices[2]
)
( YsortedVertices[1] == XsortedVertices[3] or YsortedVertices[1] == XsortedVertices[4]):
(
clockworksort[1] = YsortedVertices[2]
clockworksort[2] = YsortedVertices[1]
)
)
case of (
(YsortedVertices[3] == XsortedVertices[2] and YsortedVertices[4] == XsortedVertices[4]):
(
clockworksort[4] = YsortedVertices[3]
clockworksort[3] = YsortedVertices[4]
)
(YsortedVertices[3] == XsortedVertices[2] and YsortedVertices[4] == XsortedVertices[3]):
(
clockworksort[4] = YsortedVertices[3]
clockworksort[3] = YsortedVertices[4]
)
(YsortedVertices[3] == XsortedVertices[4] and YsortedVertices[4] == XsortedVertices[1]):
(
clockworksort[4] = YsortedVertices[4]
clockworksort[3] = YsortedVertices[3]
)
( YsortedVertices[3] == XsortedVertices[4] and YsortedVertices[4] == XsortedVertices[2]):
(
clockworksort[4] = YsortedVertices[4]
clockworksort[3] = YsortedVertices[3]
)
( YsortedVertices[3] == XsortedVertices[1] or YsortedVertices[3] == XsortedVertices[4]):
(
clockworksort[4] = YsortedVertices[3]
clockworksort[3] = YsortedVertices[4]
)
( YsortedVertices[3] == XsortedVertices[3] or YsortedVertices[3] == XsortedVertices[2]):
(
clockworksort[4] = YsortedVertices[4]
clockworksort[3] = YsortedVertices[3]
)
)
)
fn sortByScreenPositionX v1 v2 = (
case (v1.screenPosition[1] < v2.screenPosition[1]) of
(
true: -1
false: 1
)
)
fn sortByScreenPositionY v1 v2 = (
case (v1.screenPosition[2] < v2.screenPosition[2]) of
(
true: -1
false: 1
)
)
fn setVertexSelectionByScreenPositionX vertices = (
local sortedArray = #()
qsort vertices sortByScreenPositionX
for i = 1 to vertices.count do
sortedArray[i] = vertices[i].geometryIndex
return sortedArray
)
fn setVertexSelectionByScreenPositionY vertices = (
local sortedArray = #()
qsort vertices sortByScreenPositionY
for i = 1 to vertices.count do
sortedArray[i] = vertices[i].geometryIndex
return sortedArray
)
fn updatesortedverticesX vertices= (
XsortedVertices = setVertexSelectionByScreenPositionX vertices
)
fn updatesortedverticesY vertices= (
YsortedVertices = setVertexSelectionByScreenPositionY vertices
)
--to sort from left to right run this code
unregisterRedrawViewsCallback GW_showVertArrayPositionX
fn GW_showVertArrayPositionX = (
for i = 1 to (polyop.getvertselection $ as array).count do (
gw.text (polyop.getvert $ (Xsortedvertices)[i]) (i as string) color:yellow
)
)
--registerRedrawViewsCallback GW_showVertArrayPositionX
--to sort from top to bottom run this code
unregisterRedrawViewsCallback GW_showVertArrayPositionY
fn GW_showVertArrayPositionY = (
for i = 1 to (polyop.getvertselection $ as array).count do (
gw.text (polyop.getvert $ (Ysortedvertices)[i]) (i as string ) color:yellow
)
)
--registerRedrawViewsCallback GW_showVertArrayPositionY
unregisterRedrawViewsCallback GW_showVertNumber
fn GW_showVertNumber = (
for i in (polyop.getvertselection $) do
gw.text (polyop.getvert $ i) (i as string ) color:yellow
)
--registerRedrawViewsCallback GW_showVertNumber
unregisterRedrawViewsCallback GW_getVertArrayPosition
fn GW_getVertArrayPosition = (
vertices = #()
for i = 1 to (polyop.getvertselection $ as array).count do
append vertices (vertWithScreenPosition screenposition:(gw.wTransPoint ( polyop.getVert $ (polyop.getvertselection $ as array)[i] )) geometryindex:(polyop.getvertselection $ as array)[i])
gw.enlargeUpdateRect #whole
updatesortedverticesX vertices
updatesortedverticesY vertices
)
--registerRedrawViewsCallback GW_getVertArrayPosition
unregisterRedrawViewsCallback GW_showQuadVertsSortedClockwise
fn GW_showQuadVertsSortedClockwise = (
if (polyop.getvertselection $ as array).count == 4 then (
sortClockwise()
for i = 1 to clockworksort.count do (
gw.text (polyop.getvert $ (clockworksort)[i]) (i as string ) color:yellow
)
)
)
--registerRedrawViewsCallback GW_showQuadVertsSortedClockwise
fn unregistercustomRedraws = (
unregisterRedrawViewsCallback GW_showQuadVertsSortedClockwise
unregisterRedrawViewsCallback GW_getVertArrayPosition
unregisterRedrawViewsCallback GW_showVertNumber
unregisterRedrawViewsCallback GW_showVertArrayPositionY
unregisterRedrawViewsCallback GW_showVertArrayPositionX
)
rollout jpRedrawCallbacksRollout "Callbacks" width:135 height:184
(
button btn_sortX "Sort by X" pos:[6,33] width:56 height:35
button btn_sortY "Sort by Y" pos:[67,32] width:58 height:35
button btn_sortQuad "Sort Clockwise" pos:[9,70] width:112 height:35
button btn_showVertNum "Show Vertices Index" pos:[11,106] width:112 height:35
label lbl1 "Examples of of redrawViewportCallbacks" pos:[5,3] width:141 height:41
button btn_restore "Remove CallBacks" pos:[10,143] width:112 height:35
on btn_restore pressed do (
unregistercustomRedraws()
)
on btn_sortX pressed do
(
unregistercustomRedraws()
registerRedrawViewsCallback GW_getVertArrayPosition
registerRedrawViewsCallback GW_showVertArrayPositionX
)
on btn_sortY pressed do
(
unregistercustomRedraws()
registerRedrawViewsCallback GW_getVertArrayPosition
registerRedrawViewsCallback GW_showVertArrayPositionY
)
on btn_sortQuad pressed do (
unregistercustomRedraws()
registerRedrawViewsCallback GW_getVertArrayPosition
registerRedrawViewsCallback GW_showQuadVertsSortedClockwise
)
on btn_showVertNum pressed do
(
unregistercustomRedraws()
registerRedrawViewsCallback GW_showVertNumber
)
on btn_restore pressed do
(
unregistercustomRedraws()
)
)
newRollout = newRolloutFloater "callBack tests" 140 220
addrollout jpRedrawCallbacksRollout newRollout