Wings 3D Development Forum
wings_body and weld function ... - Printable Version

+- Wings 3D Development Forum (https://www.wings3d.com/forum)
+-- Forum: Wings 3D (https://www.wings3d.com/forum/forumdisplay.php?fid=1)
+--- Forum: Gripes & Grumbles (https://www.wings3d.com/forum/forumdisplay.php?fid=4)
+--- Thread: wings_body and weld function ... (/showthread.php?tid=927)



wings_body and weld function ... - ggaliens - 11-02-2014

wings_body and weld function ...

Somehow this feature is iterating over empty parts of a vertex array and getting an "undefined" element sent to e3d_vec:average

I think I have circumvented the problem by save and then reload which should PACK the WEDS object. I don't want to just add a renumber into the weld process willy nilly if the fix should really be done elsewhere.

Code:
Dump written 2014-11-2_11-43
Version: v1.5.3.2014-11-01---18-53.mlab
Window: geom
Reason: function_clause

Short stack trace:
[]

Long stack trace:
[{e3d_vec,average,
          [[undefined,
            {-0.15802236128456365,0.8708992967066219,-0.716667850800668}],
           -0.13996215906055837,2.4105054922393405,-1.847832768311414,4],
          [{file,"e3d_vec.erl"},{line,352}]},
{wings_body,qualified_fs,4,[{file,"wings_body.erl"},{line,940}]},
{wings_body,weld_1,3,[{file,"wings_body.erl"},{line,921}]},
{wings_body,'-weld_objects/4-fun-0-',7,[{file,"wings_body.erl"},{line,900}]},
{wings_sel,mapfold_1,6,[{file,"wings_sel.erl"},{line,98}]},
{wings_sel,mapfold,3,[{file,"wings_sel.erl"},{line,93}]},
{wings_body,weld_objects,4,[{file,"wings_body.erl"},{line,899}]},
{wings_develop,time_command,2,[{file,"wings_develop.erl"},{line,81}]}]



RE: wings_body and weld function ... - micheus - 11-02-2014

Wouldn't this be caused by garbage left from one of your previous operations? Maybe using body cleanup can fix it before you use weld.
Which circumstances this happens? Any .wings file available?


RE: wings_body and weld function ... - ggaliens - 11-02-2014

I was thinking about sharing a .wings file with you.

When I looked at the stack trace ... it seemed like somehow wings_face:center( ) was finding an undefined value rather than a {X,Y,Z}. Which would be extremely odd. (Deep in qualified_fs).


RE: wings_body and weld function ... - ggaliens - 11-05-2014

Maybe we can LURK around the problem a bit and find it ...

Why would wings_face:fold be used here in wings_body ?
Code:
qualified_fs([F|Fs], Tol, We, Acc) ->
    Vs = wings_face:fold(
       fun(V, _, _, Acc0) ->
           [V|Acc0]
       end, [], F, We),
    {X,Y,Z} = wings_vertex:center(Vs, We),
    Center = {granularize(X, Tol),granularize(Y, Tol),granularize(Z, Tol)},
    qualified_fs(Fs, Tol, We, [{{length(Vs),Center},F}|Acc]);
qualified_fs([], _, _, Acc) -> Acc.

It almost seems like the could have simplified a bunch my calling wings_face:center(F, We) ... I doubt it would be that much slower.

Also ... the name is a MISNOMER here because there is nothing qualified about the faces. I happen to think there should be meaning in words here. It really should be called granularized_fs ... instead. But that's a bit of an aside.

Probably the face fold is just fine ... but so is this one ... and in a single trial ... it came out faster (don't know why).

Code:
qualified_fs([F|Fs], Tol, We, Acc) ->
    Vs = wings_face:vertices_ccw(F,We),
    {X,Y,Z} = wings_vertex:center(Vs, We),
    Center = {granularize(X, Tol),granularize(Y, Tol),granularize(Z, Tol)},
    qualified_fs(Fs, Tol, We, [{{length(Vs),Center},F}|Acc]);
qualified_fs([], _, _, Acc) -> Acc.



RE: wings_body and weld function ... - ggaliens - 11-05-2014

I rewrote this function in wings_body to be more than 10% faster. Maybe 15% faster.
This is my rewrite. I didn't know module sofs ... but when I got familiar with it ... I decided
it was at very least overkill. It's cool ... but overkill and slower ... and for me ... hard to read.

I think the issue is simple ... someone was trying to handle a case with multiple coincident faces to
be potentially welded. AKAIK ... and can see ... that's not reasonable possibility. The coinicident faces to weld should ultimately be in tuples like [{Fa,Fb}] but right now are in list like [[Fa,Fb]]

Code:
weld_1(Tol, #we{id=Id,fs=Fs0}=We0, {Sel,Status0}) ->
    Fs = qualified_fs(gb_trees:keys(Fs0), Tol, We0, []),
    %% Don't use sofs module ... that's WAY OVERKILL and slower.
    %% Not to mention ... harder to read
    MyAcc = fun({Center,F}, Acc) ->
        case gb_trees:is_defined(Center,Acc) of
            true ->
                Val = gb_trees:get(Center,Acc),
                gb_trees:enter(Center, lists:append(Val,[F]), Acc);
            false -> gb_trees:enter(Center,[F],Acc)
        end
    end,
    Tree = lists:foldl(MyAcc, gb_trees:empty(), Fs),
    Part = gb_trees:values(Tree),
    case weld_part(Part, Tol, We0, Status0) of
    {We0,Status} ->
        {We0,{[{Id,gb_sets:singleton(0)}],Status}}; % Nothing to weld or done
    {We,Status} ->
        {We,{[{Id,weld_selection(lists:append(Part), We0, We)}|Sel],Status}}
    end.



RE: wings_body and weld function ... - ggaliens - 11-06-2014

OK ... I backed way way off on this to use the core version of the weld (not my new code) ... just to keep debugging simple ...
I do a tetgen tet substitution into a dodecahedron and then ... save / load (to pack) and then I try
weld ... which mostly works on simpler things ... and I get ....

Code:
1> --------------=---------------------
Using GPU shaders.
1> {'EXIT',{{case_clause,{edge,9288,6122,9683,8173,6462,9684,5128,4379}},[{wings_vertex,fold,7,[{file,"wings_vertex.erl"},{line,
59}]},{wings_face,from_vs_1,4,[{file,"wings_face.erl"},{line,60}]},{wings_collapse,collapse_edge_1,5,[{file,"wings_collapse.erl"
},{line,269}]},{lists,foldl,3,[{file,"lists.erl"},{line,1261}]},{wings_body,try_weld,5,[{file,"wings_body.erl"},{line,981}]},{wi
ngs_body,weld_part_2,6,[{file,"wings_body.erl"},{line,957}]},{wings_body,weld_part,4,[{file,"wings_body.erl"},{line,948}]},{wing
s_body,weld_1,3,[{file,"wings_body.erl"},{line,928}]}]}}

All I did here is add erlang:display( ) just before call to weld_error() so that I might see what Erlang and WINGS is imagining to go wrong. And what I get is the case_clause issue shown above.

So then I come back into the code wings_vertex:fold and add some debug like ...
(see extra just in case clause ... match anything)

Code:
fold(F, Acc0, V, Face, Edge, LastEdge, Etab) ->
    Acc = case array:get(Edge, Etab) of
          #edge{vs=V,lf=Face,rf=Other,rtpr=NextEdge}=E ->
          F(Edge, Face, E, Acc0);
          #edge{ve=V,lf=Face,rf=Other,rtsu=NextEdge}=E ->
          F(Edge, Face, E, Acc0);
          #edge{vs=V,rf=Face,lf=Other,ltsu=NextEdge}=E ->
          F(Edge, Face, E, Acc0);
          #edge{ve=V,rf=Face,lf=Other,ltpr=NextEdge}=E ->
          F(Edge, Face, E, Acc0);
              #edge{}=E ->
              erlang:display('{vs, ve, lf, rf, ltpr, ltsu, rtpr, rtsu}'),
                    erlang:display(E),
                    io:format("V = ~p , Face = ~p , Edge = ~p\n", [ V, Face, Edge ]),
                    NextEdge = nil,
                    Other = nill,
                    wings_u:error_msg("YIKES !")
      end,
    fold(F, Acc, V, Other, NextEdge, LastEdge, Etab).


And I know now that seems like at least VERTEX is not a match at all ... so maybe the iterator things got messed up in the welding code.