03-28-2014, 01:50 AM
This MIGHT be better approach for some folks.
Code:
normal(V, #we{}=We) ->
EL = wings_edge:from_vs([V], We),
case EL of
[_,_] -> normal0(V, We);
_ -> normal1(V, We)
end.
%% normal(Vertex, We) -> Normal
%% Calculate the normal for a vertex (based on the normals for all
%% surrounding faces).
normal0(V, We) ->
Ns = fold(fun(_, Face, _, A) ->
[wings_face:normal(Face, We)|A]
end, [], V, We),
e3d_vec:norm(e3d_vec:add(Ns)).
normal1(V, #we{vp=VPos, es=Etab}=We) ->
MyAcc = fun(Edge, _, _, A) ->
#edge{vs=VS,ve=VE}=array:get(Edge,Etab),
case VS of
V -> [VE|A];
_ -> [VS|A]
end
end,
Vs = fold(MyAcc, [], V, We), %% outer verts !
Len = length(Vs),
MyAcc2 = fun(Idx1, Acc) ->
Idx2 = (Idx1 + 1) rem Len,
Pt2 = array:get(lists:nth(Idx2+1,Vs), VPos),
Pt1 = array:get(lists:nth(Idx1+1,Vs), VPos),
Pt0 = array:get(V, VPos),
D1 = e3d_vec:sub(Pt2,Pt0),
D2 = e3d_vec:sub(Pt1,Pt0),
Cross0 = e3d_vec:cross(D1, D2),
Cross = e3d_vec:norm(Cross0),
[Cross|Acc]
end,
Ns = lists:foldl(MyAcc2, [], lists:seq(0,Len-1) ),
N1 = e3d_vec:norm(e3d_vec:add(Ns)),
N2 = normal0(V,We),
case e3d_vec:degrees(N1,N2) > 90.0 of
true -> e3d_vec:mul(N1,-1.0);
false -> N1
end.