How to do a space-partitioning of the Utah Teapot?

蹲街弑〆低调 提交于 2020-01-13 16:55:37

问题


Having dealt with converting the Bezier Patches into triangles, I need to do a Binary Space Partition in order to draw the projected triangles using the Painter's Algorithm.

I've implemented the algorithm from Wikipedia with much help with the math.

But it's making a Charlie Brown tree! That is most of the nodes have one branch completely empty. The whole strategy is all wrong. Since the teapot is essentially spherical, the entire shape is only on one "side" of any particular component triangle.

So I'm thinking I need partitioning planes arranged more like an apple-corer: all passing through the line of the y-axis. But I'm kind of going off book, you know? What's the best way to partition the teapot?

Here's my bsp-tree generator. It uses other functions posted in the linked question.

Edit: Extra juggling to avoid dictstackoverflow. Complete program available here (requires mat.ps and teapot). The numerical output shows the depth of the tree node under construction.

% helper functions to insert and remove triangles in lists
/unshift { % [ e1 .. eN ] e0  .  [ e0 e1 .. eN ]
    exch aload length 1 add array astore
} def
/shift { % [ e0 e1 .. eN ]  .  [ e1 .. eN ] e0
    aload length 1 sub array astore exch
} def


/makebsp { % [ triangles ]  .  bsptree
    count =
%5 dict  %This is the tree node data structure
<</P[]/PM[]/plane[]/front[]/behind[]/F<<>>/B<<>>>>
begin

    dup length 1 le{ % If 0 or 1 triangles
        dup length 0 eq { % If 0 triangles
            pop           %    discard
        }{                % If 1 triangle
            aload pop /P exch def  % put triangle in tree node
        }ifelse
    }{ % length>1

    shift /P exch def  % P: Partitioning Polygon (triangle)
    P transpose aload pop
    [1 1 1] 4 array astore % make column vectors of homogeneous coords
    /PM exch def

    [ % Compute equation of the plane defined by P
      PM 0 3 getinterval det
      [ PM 0 get PM 2 get PM 3 get ] det
      [ PM 0 get PM 1 get PM 3 get ] det
      PM 1 3 getinterval det 3 mul
    ] /plane exch def

    % iterate through remaining triangles, testing against plane, adding to lists
    /front [] def
    /behind [] def
    { %forall  [P4 P5 P6] = [[x4 y4 z4][x5 y5 z5][x6 y6 z6]]
        /T exch def
        T transpose % [[x4 x5 x6][y4 y5 y6][z4 z5 z6]]
        {aload pop add add} forall % (x4+x5+x6) (y4+y5+y6) (z4+z5+z6)

        plane 2 get mul 3 1 roll % z|C| (x) (y)
        plane 1 get mul 3 1 roll % y|B| z|C| (x)
        plane 0 get mul          % y|B| z|C| x|A|
        plane 3 get add add add  % Ax+By+Cz+D

        0 le { /front front
        }{ /behind behind
        } ifelse
        T unshift def
    } forall

    %front == ()= behind == flush (%lineedit)(r)file pop

    % recursively build F and B nodes from front and behind lists
    %/F front makebsp def
    front currentdict end exch
        makebsp
    exch begin /F exch def
    %/B behind makebsp def
    behind currentdict end exch
        makebsp
    exch begin /B exch def
    /front [] def
    /behind [] def

    } ifelse
currentdict end
} def

Output:


回答1:


BSP was invented for geometries like levels in Quake-like games and it may be hard to use for some specific geometry sets. BSP uses one of the existing triangles to split your level, so just imagine how it would behave when you want to use it on a sphere...

For the teapot you could get better results using OCTree, which doesn't need to split your geometry along existing triangles. But I'm not sure how well does it work with the Painter Algorithm.

If you really need to use BSP tree here, then you should pick your triangles carefully. I don't understand all of your code but I don't see this part here. Just iterate over all triangles in your current tree branch and for each of them compute the number of triangles in front of it and at the back. The one that has similar number of front-triangles and back-triangles is usually the best one to be used as a split plane.




回答2:


I didn't quite do an octree, but I modified the bsp-tree builder to use an explicit list of planes which I filled with axis-aligned planes slicing the space -4 < x,y,z < 4.

/planelist [
    0 .2 4 { /x exch def
        [ 1 0 0 x ]
        [ 1 0 0 x neg ]
        [ 0 1 0 x ]
        [ 0 1 0 x neg ]
        [ 0 0 1 x ]
        [ 0 0 1 x neg ]
    } for
] def

Postscript program available here (requires mat.ps).

The lighter green artifact is the result of a "preview" shown during construction of the bsp. Once built, subsequent pages (images) are drawn quickly and with no artifact as the camera revolves around the teapot.

The join of the body with the spout and handles (not shown from this angle) still needs work.

With the bsp better behaved, backface culling isn't strictly necessary. But it makes the preview nicer.




回答3:


Another way to improve the BSP for this image is to use a hierarchical decomposition. The teapot isn't just a bunch of bezier surfaces, it has some surfaces that describe the body, some others that describe the handle, the spout, the lid (, the bottom? ).

So the first few levels of the tree ought to be the top-level pieces. Is the handle in front of or behind the body? Is the spout in front of the body? Answers to these questions would be a useful guide for the painter's algorithm.



来源:https://stackoverflow.com/questions/14807341/how-to-do-a-space-partitioning-of-the-utah-teapot

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!