角色动画算法——人有悲欢离合

题目:给出鹊桥会分手时,牛郎织女两人分别挥手告别

效果:

image.png

思路

根据教程,我们的思路是这样:

  1. 建立二叉树,用以保存角色的骨骼、关节的信息
  2. 运用正向运动学(FK)计算末端影响器的位置坐标
  3. 将人物各个部位的图片绑定在骨骼上
  4. 绘制
FK算法

难点

  • 确定旋转中心,glm的旋转函数中心实在(0,0,0)的位置,即VBO中保存的点的中心*(待测,也有可能是视口的中心,因为先前实验的两个中心是重合的)
  • 绑定骨骼,需要的函数还不清楚

方案

省去绑定骨骼的步骤,那么二叉树也不必建立了。
我们直接进行正向运动学计算坐标。
在准备阶段,有桌布坐标和纹理坐标,传入vertexShader可以改变桌布坐标。这样搭配起来,解决位置的改变有多种多样的方法。

1. 改变旋转中心进行旋转
2. 位移纹理,旋转,反位移纹理
3. 运用矩阵,进行任意轴旋转
4. PS时,把坐标中心放置于旋转中心

四种方法都可以但是都有困难点,先浅谈一下:
法一改变旋转中心的函数未知,法二必须把纹理在桌布上位移才可以,如果是把桌布在世界位移则没有意义,法四太蠢了,没有通用性。四种方案都要解决的是,顶点以像素尺度转换到(-1,1)的坐标确立。

法三

难点在于矩阵的寻找,以及矩阵的运算。尤其是网络上大部分方法的任意轴都是过坐标原点的,我们的轴是平行于z轴的另一条轴
找到了推导过程

{
    float a = v1->x;
    float b = v1->y;
    float c = v1->z;

    glm::vec3 p = *v2 - *v1;

    float u = p.x;
    float v = p.y;
    float w = 1;        //坐标标准化函数有问题,待解决


    float uu = u * u;
    float uv = u * v;
    float uw = u * w;
    float vv = v * v;
    float vw = v * w;
    float ww = w * w;
    float au = a * u;
    float av = a * v;
    float aw = a * w;
    float bu = b * u;
    float bv = b * v;
    float bw = b * w;
    float cu = c * u;
    float cv = c * v;
    float cw = c * w;

    float costheta = cosf(theta);
    float sintheta = sinf(theta);

    pOut[0][0] = uu + (vv + ww) * costheta;
    pOut[0][1] = uv * (1 - costheta) + w * sintheta;
    pOut[0][2] = uw * (1 - costheta) - v * sintheta;
    pOut[0][3] = 0;

    pOut[1][0] = uv * (1 - costheta) - w * sintheta;
    pOut[1][1] = vv + (uu + ww) * costheta;
    pOut[1][2] = vw * (1 - costheta) + u * sintheta;
    pOut[1][3] = 0;

    pOut[2][0] = uw * (1 - costheta) + v * sintheta;
    pOut[2][1] = vw * (1 - costheta) - u * sintheta;
    pOut[2][2] = ww + (uu + vv) * costheta;
    pOut[2][3] = 0;

    pOut[3][0] = (a * (vv + ww) - u * (bv + cw)) * (1 - costheta) + (bw - cv) * sintheta;
    pOut[3][1] = (b * (uu + ww) - v * (au + cw)) * (1 - costheta) + (cu - aw) * sintheta;
    pOut[3][2] = (c * (uu + vv) - w * (au + bv)) * (1 - costheta) + (av - bu) * sintheta;
    pOut[3][3] = 1;
}

通过矩阵运算,此法实质上也是FK算法:

        tran_hand = tran_hand*tran_ arm ;

矩阵赋值:

        glm::mat4 tran_hand =
        {   trans[0][0],trans[0][1],trans[0][2],trans[0][3],
            trans[1][0],trans[1][1],trans[1][2],trans[1][3],
            trans[2][0],trans[2][1],trans[2][2],trans[2][3],
            trans[3][0],trans[3][1],trans[3][2],trans[3][3]
        };

时间紧迫,此法仍有许多待改进和值得深究的地方。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。