Face in Circle

上面的三个圆环有什么特殊吗?有一定抽象能力的人在离屏幕适当距离的时候可以看到以下三张脸(跟看码一样,离得越远越清晰,近视眼超过400度的请摘掉眼镜):



原始创意来自于一个视频,用小钉钉成一个环,然后就可以不停的绕黑线,我只不过用Houdini实现了下,惭愧。

最核心的原理是这样的:在数学上这些线叫“弦”。一条弦可以由过这个弦的一个点,和这条弦的方向矢量来表示,因为有了这俩我们就可以求出交点来了。所以不管要形成什么图案,我们无非是要解答俩问题:在哪里定这个点,穿过这个点的弦的方向如何。

容易想到的是1.点洒在黑的地方 2.弦尽量朝着可以穿过最多黑色的方向

问题1很好解决,scatter直接可以做到,问题2其实也容易,把弦离散化成N个点,把点对应的图片位置的像素采样加起来比较就可以了。

测试后发现如果点也往黑处撒弦也往黑处穿,会导致图像过于黑白分明,摘掉眼镜看时混合的不好,于是把点改成了均匀撒,效果改善很明显。

以下是唯一的代码:

float r = ch('r');
vector p1 = point(1, "P", 0);
vector p2 = @P;
vector a = p2 - p1, b = -p1;
vector a_n = normalize(a);
vector c = dot(normalize(a),b)*a_n - b;
vector delta = sqrt(r*r - dot(c, c))*a_n;
vector intersect0 = c + delta, intersect1 = c - delta;
if (length(intersect0 - intersect1)<ch('min_len'))
    return;

int pts[] = {};
vector l = intersect1 - intersect0;
for(int i=0; i<=chi('segment'); i++) {
    vector p = lerp(intersect0, intersect1, float(i)/chi('segment'));
    append(pts, addpoint(geoself(), p));
}
int prim = addprim(geoself(), "polyline", pts);

上面的代码的作用就是定下俩点后求出和圆的交点,并分成segment段。因为是vex所以执行效率相当高。

确保wrangle执行方式是point后,input1连任意个可能要穿过的方向(我用了一个低段数的圆,相当于uniform sample),input2连一个点,这段代码就会生成所有通过input1和input2的弦。下一步就是比较然后选择这些弦里压黑最多的那根保留了。经过这个之后就会对一个点(input2)选出一根线。对所有的点for一次后就可以生成图像了。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章