[Closed] average Up vector randomly flips
Why when i try to calculate the average upVector, it tends to flip. In the code snippet below, only one instance of this tends to occur and I’m not sure why and how to fix this. The Z is facing downwards and it should be facing up like the others.
fn plot_points pts wirecolor:yellow =
(
if pts.count >= 2 do
(
sp = splineshape wirecolor:wirecolor
addnewspline sp
for i=1 to pts.count do addknot sp 1 #corner #line pts[i]
close sp 1
updateshape sp
)
)
fn average_vecs pts =
(
local count = pts.count
for i = 2 to count-1 do
(
local prePt = pts[i-1]
local centerPt = pts[i]
local nextPt = pts[i+1]
/* find average up vector */
local upVec = [0,0,1]
local upVec = normalize (cross (normalize prePt-centerPt) (normalize centerPt-nextPt))
point dir:upVec pos:centerPt size:6 wirecolor:white axistripod:true
)
)
/* Test Setup */
delete objects
clearlistener()
/* test points */
seed 3
pts = #()
tm = rotateYMatrix 30
append pts ([60,10,0] * tm)
append pts ([40,10,0] * tm)
append pts ([20,10,0] * tm)
append pts ([-40,30,0] * tm)
append pts ([-30,0,0] * tm)
append pts ([-80,0,0] * tm)
append pts ([-80,-30,0] * tm)
append pts ([-20,-30,0] * tm)
append pts ([20,-15,0] * tm)
append pts ([40,-15,20] * tm)
plot_points pts displayText:false drawPath:false
/* points */
plot_points pts
average_vecs pts
according to your spline vert order…I find it odd that you do this
local upVec = normalize (cross (normalize prePt-centerPt) (normalize centerPt-nextPt))
instead of this
local upVec = normalize (cross (normalize centerPt-prePt) (normalize nextPt-centerPt))
so that the resultant vectors are pointing in the direction of the spline vert order…
so if you do the above…all is right except now the next vert after is inverted !!! is it because the angle is exactly 90deg ? dunno…not an expert with these things…matrices…
so what I did next is this
local upVec = normalize (cross (normalize centerPt-prePt) (normalize centerPt-nextPt))
ie. reverse only the first half of the equation…and voila…don’t ask…I did claim I’m not an expert with these things…(I’m confident for other weird cases…this won’t work…so there…)
The reason for your flip is because this is a concave vertex in your shape. The short angle between the edges is on the outer side of the shape. You could easily detect and fix this in most use cases by calculating the dot product between the current up vector and the previous up vector (the one you calculated for the previous point). If the dot product is negative, you need to flip the current up vector. Let my try to write some code example for you (I’m writing this on my phone so I can’t test it atm)
--add this line before the loop
local lastUpVec = [0,0,1]
--add these lines after you calculate the upVec
If dot lastUpVec upVec < 0 then
upVec = -upVec
lastUpVec = upVec