This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-01-02
Channels
- # admin-announcements (1)
- # alda (1)
- # aws (4)
- # boot (276)
- # cljs-dev (3)
- # cljsjs (1)
- # cljsrn (3)
- # clojars (22)
- # clojure (174)
- # clojure-austin (1)
- # clojure-italy (2)
- # clojure-russia (20)
- # clojurecup (1)
- # clojurescript (233)
- # cursive (4)
- # datavis (97)
- # datomic (122)
- # hoplon (80)
- # ldnclj (8)
- # leiningen (6)
- # om (82)
- # reagent (10)
- # spacemacs (8)
- # specter (5)
What I need is to do a linear interpolation from one vector to another by a normalized percentage.
I took it as far as I can and I'm burnt. I checked in the latest code, even though it doesn't work yet. Anyone interested can check it out here: https://github.com/pkobrien/cad/tree/master/src/cad/mesh
There are just a handful of functions that I don't know how to implement using core.matrix. They are in core.clj and face.clj
centroid and mix should be easy to fix by someone who knows core.matrix:
(defn centroid
[[x & xs :as coll]]
(case (count coll)
0 nil
1 x
2 (gc/mix x (first xs))
(let [s (/ 1.0 (count coll))
f (fn [x _] (* x s))]
(gc/reduce-vector x + f xs))))
(defn mix
[v1 v2 amount]
(gc/mix v1 v2 amount))
I have no idea what reduce-vector
is doing and the vector part of http://thi.ng is all but impenetrable to me, though I've tried.
In face.clj
I've got this function:
(defn- mag [[x y z]]
(Math/sqrt (mm/madd x x y y z z)))
Oh, and the catmull-clark in operator.clj
is still using this: (gc/addm (gc/madd r 2.0 f) (* vertex (- n 3)) (/ 1.0 n))
I'm done for the day, but this has been a super productive week and I'm really pleased with how this mesh library is shaping up.
I don't think I could have gotten to the end of this without the quirky dubstepesque Beats Antique blowing up my ears. 😉
@mikera: I'm so close to being done with this conversion to core.matrix - can I get a little bit of help?
Let's start with an easy one:
(defn mix
"Returns linear interpolation point at amount along the path from v1 to v2."
[v1 v2 amount]
(gc/mix v1 v2 amount))
I'm actually adding a lerp function to the next iteration of core.matrix, should be released today
I don't know what lerp is. Pretty funny how far I've gotten without brushing up on my maths.
(defn mix "Returns linear interpolation point at amount along the path from v1 to v2." [v1 v2 amount] (let [result (array :vectorz v1)] (scale-add! result (- 1.0 amount) v2 amount)))
Ok, the next one to fix is a centroid for more than 2 points:
(defn centroid
"Returns the point at the barycenter of the collection of points."
[[x & xs :as coll]]
(case (count coll)
0 nil
1 x
2 (mix x (first xs) 0.5)
(let [s (/ 1.0 (count coll))
f (fn [x _] (* x s))]
(gc/reduce-vector x + f xs))))
And here is what reduce-vector
is doing:
g/PVectorReduce
(reduce-vector
[_ f xs]
(let [^doubles buf' #?(:clj (double-array 3) :cljs (js/Float32Array. buf))]
#?@(:clj
[(aset buf' 0 (aget buf 0))
(aset buf' 1 (aget buf 1))
(aset buf' 2 (aget buf 2))])
(Vec3. (vec3-reduce* f buf' xs) nil _meta)))
(reduce-vector
[_ f f2 xs]
(let [^doubles buf' #?(:clj (double-array 3) :cljs (js/Float32Array. buf))]
#?@(:clj
[(aset buf' 0 (aget buf 0))
(aset buf' 1 (aget buf 1))
(aset buf' 2 (aget buf 2))])
(vec3-reduce* f buf' xs)
(aset buf' 0 (double (f2 (aget buf' 0) 0)))
(aset buf' 1 (double (f2 (aget buf' 1) 1)))
(aset buf' 2 (double (f2 (aget buf' 2) 2)))
(Vec3. buf' nil _meta)))
I'm reading about lerp, slerp and nlerp: https://keithmaggio.wordpress.com/2011/02/15/math-magician-lerp-slerp-and-nlerp/
Okay, this one works but you might have a better way to code it:
(defn normal
"Returns the ortho normal of the first three points passed in."
([[a b c]] (normal a b c))
([a b c] (apply point (mapv (comp mu/round2safe mu/abs-zero)
(mx/normalise (mx/cross (- b a) (- c a)))))))
I've been refactoring this code over time and sometimes it gets to the point that the stupidity becomes obvious.
I also added the rounding because I was having some issues with my meshes that it fixed. Will have to see if that is still needed or not.
Here comes the fun one because catmull-clark relies on this and I rely on catmull-clark:
(gc/addm (gc/madd r 2.0 f) (* vertex (- n 3)) (/ 1.0 n))
Some context might help. This is part of the function that calculates a new vertex point for the mesh subdivision smoothing:
get-vp (fn [mesh vertex]
(let [f (mc/centroid (mapv mf/centroid
(mv/faces mesh vertex)))
vn (mv/neighbors mesh vertex)
n (count vn)
r (mc/centroid (mapv #(mc/mix vertex % 0.5) vn))]
(gc/addm (gc/madd r 2.0 f) (* vertex (- n 3)) (/ 1.0 n))))
Let me see what the error is. In the mean time, when I do this:
(mx/normalise! (mx/cross (mx/sub b a) (mx/sub c a)))
I get CompilerException java.lang.RuntimeException: java.lang.Number instance is not mutable!
Okay, those addm
and madd
macros are protocols that aren't implemented on Vector3
CompilerException java.lang.IllegalArgumentException: No implementation of method: :madd of protocol: #'thi.ng.geom.core/PMathOps found for class: mikera.vectorz.Vector,
I think your args might not be vector3. I get that error if I try to do (normalise!...) on an immutable vector
(let [a (array :vectorz [1 2 3]) b (array :vectorz [2 3 1]) c (array :vectorz [3 1 2])] (normalise! (cross (sub b a) (sub c a))))
Then you don't need to worry about whether your vectors are mutable or not.... for a slight performance cost....
Probably. Might be wise to put some assertions on the return types of various functions in your unit tests
@mikera: Okay, those addm
and madd
macros are protocols that aren't implemented on Vector3
CompilerException java.lang.IllegalArgumentException: No implementation of method: :madd of protocol: #'thi.ng.geom.core/PMathOps found for class: mikera.vectorz.Vector,
So I need to figure out equivalent ways.
In order to get this to work:
get-vp (fn [mesh vertex]
(let [f (mc/centroid (mapv mf/centroid
(mv/faces mesh vertex)))
vn (mv/neighbors mesh vertex)
n (count vn)
r (mc/centroid (mapv #(mc/mix vertex % 0.5) vn))]
(gc/addm (gc/madd r 2.0 f) (* vertex (- n 3)) (/ 1.0 n))))
If "pairwise" means "elementwise" then madd is probably equivalent to add-product or add-scaled
does this help?
(madd [_ a b] (vm/v3-op2 #?(:clj (double-array) :cljs (new js/Float32Array)) * + buf a b 1.0 0.0 _meta))
(addm [_ a b] (vm/v3-op2 #?(:clj (double-array) :cljs (new js/Float32Array)) + * buf a b 0.0 1.0 _meta))
This is what the logic is supposed to be:
For each original point P, take the average F of all n (recently created) face points for faces touching P, and take the average R of all n edge midpoints for edges touching P, where each edge midpoint is the average of its two endpoint vertices. Move each original point to the point
\frac{F + 2R + (n-3)P}{n}.
This is the barycenter of P, R and F with respective weights (n − 3), 2 and 1.