Fork me on GitHub
#datavis
<
2015-12-05
>
meow16:12:30

After several rounds of refactoring I've gotten Catmull-Clark down to this (and I'm pretty happy with it):

(defn catmull-clark
  "Return a mesh with additional faces and edge points for a smoothing effect."
  [{:keys [faces edges vertices] :as mesh} & {:keys [get-f-point get-e-point get-v-point]}]
  (let [get-fp (fn [mesh face]
                 (calc-vertex face))
        get-ep (fn [edge e-faces f-points]
                 (gu/centroid (concat (vec edge) (mapv f-points e-faces))))
        get-vp (fn [mesh vertex]
                 (let [f (gu/centroid (mapv gu/centroid
                                            (gm/vertex-faces* mesh vertex)))
                       vn (gm/vertex-neighbors* mesh vertex)
                       n (count vn)
                       r (gu/centroid (mapv #(g/mix vertex %) vn))]
                   (g/addm (g/madd r 2.0 f) (g/* vertex (- n 3)) (/ 1.0 n))))
        get-f-point (or get-f-point get-fp)
        get-e-point (or get-e-point get-ep)
        get-v-point (or get-v-point get-vp)
        new-face (fn [[p c n] f-point e-points]
                   [(e-points #{p c}) c (e-points #{c n}) f-point])
        new-faces (fn [face f-point e-points]
                    (mapv #(new-face % f-point e-points) (face-loop-triples face)))
        subdivide (fn [[face f-point] e-points]
                    (new-faces face f-point e-points))
        v-replace (fn [face vert-map] (replace vert-map face))
        f-points (into {} (map (fn [face]
                                 [face (get-f-point mesh face)]) faces))
        e-points (into {} (map (fn [[edge e-faces]]
                                 [edge (get-e-point edge e-faces f-points)]) edges))
        v-points (into {} (map (fn [vertex]
                                 [vertex (get-v-point mesh vertex)]) (keys vertices)))]
    (->> (mapcat #(subdivide % e-points) f-points)
         (map #(v-replace % v-points))
         (g/into (g/clear* mesh)))))

meow16:12:51

And here is an example showing how to create a variant by supplying an alternate function:

(defn not-quite-catmull-clark
  "Return a mesh with additional faces and edge points for a smoothing effect."
  [mesh]
  (let [get-e-point (fn [edge _ _] (gu/centroid (vec edge)))]
    (catmull-clark mesh :get-e-point get-e-point)))

meow21:12:37

I wish @toxi were here to answer some basic question about http://thi.ng geom. 😞

meow21:12:12

It's frustrating trying to figure out how to do something I know is easy, I just haven't done it before so I'm not sure what particular method of which protocol is going to do the trick. I have a vertex and I have the centroid of the mesh and now I need to calculate a new vertex that is a certain distance closer to the mesh centroid by a fixed (not proportional) amount.

meow21:12:17

Should be easy, right? Aaarrrggghhh!!!

meow21:12:03

I've been using g/mix to get a certain percentage distance between two points.

meow21:12:08

I might get a clue from one of the extrusion functions, since basically I'm working on "skeletonizing" a mesh, which is kind of like a fancy extrusion of sorts.

eggsyntax21:12:03

I think we forgot to mention to @toxi that once you show your face in #C0F0V8DT5, you're obligated to be here at all times 😉

eggsyntax21:12:37

#datavisyoucancheckoutanytimeyoulike

meow21:12:45

Yeah, otherwise we'll post annoyingly animated parrot emoticons to take your place.

meow21:12:28

2D extrude didn't help because that's super easy as it just does a simple offset along the z axis

meow22:12:47

convex-hull on a polygon sounded like it might hold a clue, but it just looks like Greek to me... 😞

meow22:12:13

I feel like I'm missing something really basic and I just can't find what I need.

meow22:12:37

Maybe Line3?

meow22:12:45

It's probably just a simple vector math operation - guess I get to learn more about vec3

meow22:12:09

I think I'm going to give up until @toxi comes back because that matrix math stuff doesn't look fun.

meow22:12:37

Oh well, no skeletons today. 👻

meow23:12:31

except that requires me to tessellate the mesh, which I don't want to do at this point of the process...

meow23:12:56

@toxi: when you are here some time I might still need help with skeletonizing a mesh. To begin I'd be happy with just creating a shell or inset hull of the shape, then I won't have any trouble putting holes into each face.

meow23:12:01

But am I talking back? That's the important question.

meow23:12:35

I don't want to triangulate my faces until I have to. If I know the face is planar I want to be able to get a normal for it. I see vertices-planar? but it doesn't seem to be used anywhere.

meow23:12:15

Also, @toxi, is the inc here a bug:

(defn vertex-valence*
  [mesh v] (inc (count (get (:vertices mesh) v))))

meow23:12:25

Shouldn't it just be the count?

meow23:12:07

That's in gmesh.

meow23:12:11

I'm talking to toxi, but he's not here, that's why it seems like I'm talking to myself, but I'm really not. Really! I'm serious.