笔刷

作者: 昵称好多想不出来 | 来源:发表于2019-12-29 13:13 被阅读0次

    接下来我选择4个作品逐步完成上述图片,在processing上写,并做出一些代码优化。

    难度一:

    原理很简单,追踪鼠标坐标画圆就是了。

    void draw1(){
      if(mousePressed) {
        strokeWeight( 3 );
        circle( mouseX, mouseY, size );
      }
    }
    

    难度二:根据速度改变圆的大小

    定义圆的大小与速度成反比

     v += sqrt( Veloc.x*Veloc.x + Veloc.y*Veloc.y ) - v;  // ADD
     v *= 0.6;  
    float r = size - v;  // ADD  
    

    定义画笔速度同当前帧与上一帧的位置差成正比

    Veloc.x += ( mouseX - Pos.x ) * spring;
        Veloc.y += ( mouseY - Pos.y ) * spring;
        Veloc.x *= friction;
        Veloc.y *= friction;
    

    代码中spring参数与friction参数分别模拟了笔刷的惯性与摩擦力,但是效果不怎么理想,两个参数效果的区别不明显,都是值小了画笔运动慢,值大了画笔运动快。。。可能是我太顿感了吧,看不出区别。

    下图中上方的笔迹是摩檫力较大的时候,下方笔记是较小的时候,可以看出画圆的数量不同


    难度三:模拟毛笔刷,实现连贯

    最初看例子的时候玩到这里就一直很好奇要如何让圆连续地生成,这么想是因为看到前面画圆的Demo里,当鼠标运动慢时,多个圆彼此重叠,就很有毛笔笔迹的效果,所以猜测后面的笔迹应当让圆生成地更连贯,类似于插值操作,但怎么做呢?

    答案是:直接画线就行了,那么麻烦干什么![/黑脸]
    当然,插值还是要做的,主要的工作是平滑笔刷的大小变化,让两帧的笔刷大小有一定数量的过渡值,代码如下:

        for( int i = 0; i < splitNum; ++i ) {  // ADD
          oldX = Pos.x;
          oldY = Pos.y;
          Pos.x += Veloc.x/splitNum;  // AMEND: vx -> vx/splitNum
          Pos.y += Veloc.y/splitNum;  // AMEND: vy -> vy/splitNum
          oldR += (r-oldR)/splitNum;  // ADD
          if(oldR < 1) { oldR = 1; }  // AMEND: r -> oldR
          strokeWeight( oldR );  // AMEND: r -> oldR
          line( Pos.x, Pos.y, oldX, oldY );
        }  // ADD
        
    
    QQ截图20191229122745.png

    但这个画笔的变化也不是那么平滑。。

    难度四:模拟笔刷分叉
    这个是当时看起来最炫酷的效果,但了解后,原理很简单,只要细心观察一下分叉部分线的数量,都是三。。。。
    那就很简单了,将上面画线的函数复制两个,定义一个位移变量,令该变量同速度成正比,也就是说当速度小时,位移小,三条线混合在一起,当速度增大,位移增大,三条线分离开就有分叉的效果辽

    for( int i = 0; i < splitNum; ++i ) {  // ADD
          oldX = Pos.x;
          oldY = Pos.y;
          Pos.x += Veloc.x/splitNum;  // AMEND: vx -> vx/splitNum
          Pos.y += Veloc.y/splitNum;  // AMEND: vy -> vy/splitNum
          oldR += (r-oldR)/splitNum;  // ADD
          if(oldR < 1) { oldR = 1; }  // AMEND: r -> oldR
          strokeWeight( oldR+diff );  // AMEND: r -> oldR
          line( Pos.x, Pos.y, oldX, oldY );
          strokeWeight( oldR );  // ADD
          line( Pos.x+diff*2, Pos.y+diff*2, oldX+diff*2, oldY+diff*2 );  // ADD
          line( Pos.x-diff, Pos.y-diff, oldX-diff, oldY-diff );  
        }  // ADD
    

    效果如下:


    QQ截图20191229123245.png

    至此目标达成,但还有一些问题:
    1.笔刷不够平滑,三条分叉也太僵硬了点
    2.代码也不够简洁
    有时间再优化吧。。。好累,作业好多。。

    相关文章

      网友评论

          本文标题:笔刷

          本文链接:https://www.haomeiwen.com/subject/sjsyoctx.html