请选择 进入手机版 | 继续访问电脑版
查看: 362|回复: 0

HTML5 3D衣服摇摆动画特效

[复制链接]

1306

主题

1306

帖子

4336

积分

超级版主

Rank: 8Rank: 8

积分
4336
发表于 2018-1-22 16:31:27 | 显示全部楼层 |阅读模式
这又是一款基于HTML5 Canvas的3D动画杰作,它是一个可以随风飘动的3D衣服摇摆动画特效,非常逼真。当我们将鼠标滑过衣服时,衣服将会出现摇摆的动画,点击鼠标时,衣服将会更加剧烈地摆动。

HTML代码
  1. <div style="width:500px;margin:10px auto">
  2.         <canvas id="cv" width="480" height="300"></canvas>
  3.         <p>"3D on 2D Canvas" demo</p>
  4.         <p>move cursor to pan / click to swing</p>
  5. </div>
复制代码
P3D库JS代码,主要用来处理3D效果的
  1. window.P3D = {
  2.         texture: null,
  3.         g: null
  4. };

  5. P3D.clear = function(f, w, h) {
  6.         var g = this.g;
  7.         g.beginPath();
  8.         g.fillStyle = f;
  9.         g.fillRect(0, 0, w, h);

  10. }

  11. P3D.num_cmp = function(a,b){return a-b;}

  12. P3D.drawTriangle = function(poss, uvs, shade_clr) {
  13.         var w = this.texture.width;
  14.         var h = this.texture.height;

  15.         var g = this.g;

  16.         var vAd = [ poss[1].x - poss[0].x , poss[1].y - poss[0].y ];
  17.         var vBd = [ poss[2].x - poss[0].x , poss[2].y - poss[0].y ];

  18.         var vA = [ uvs[1].u - uvs[0].u , uvs[1].v - uvs[0].v ];
  19.         var vB = [ uvs[2].u - uvs[0].u , uvs[2].v - uvs[0].v ];

  20.         vA[0] *= w;
  21.         vA[1] *= h;

  22.         vB[0] *= w;
  23.         vB[1] *= h;

  24.         var m = new M22();
  25.         m._11 = vA[0];
  26.         m._12 = vA[1];
  27.         m._21 = vB[0];
  28.         m._22 = vB[1];

  29.         var im = m.getInvert();
  30.         if (!im) return false;

  31.         var a = im._11 * vAd[0] + im._12 * vBd[0];
  32.         var b = im._21 * vAd[0] + im._22 * vBd[0];

  33.         var c = im._11 * vAd[1] + im._12 * vBd[1];
  34.         var d = im._21 * vAd[1] + im._22 * vBd[1];

  35.         var wu = uvs[0].u * w;
  36.         var hv = uvs[0].v * h;
  37.         var du = wu * a + hv * b;
  38.         var dv = wu * c + hv * d;

  39.         g.save();

  40.         g.beginPath();
  41.         g.moveTo(poss[0].x, poss[0].y);
  42.         g.lineTo(poss[1].x, poss[1].y);
  43.         g.lineTo(poss[2].x, poss[2].y);
  44.         g.clip();

  45.         g.transform(a, c, b, d, poss[0].x - du, poss[0].y - dv);

  46.         // bounds
  47.         var bx = [wu, wu+vA[0], wu+vB[0]];
  48.         var by = [hv, hv+vA[1], hv+vB[1]];

  49.         bx.sort(P3D.num_cmp);
  50.         by.sort(P3D.num_cmp);

  51.         var bw = bx[2] - bx[0];
  52.         var bh = by[2] - by[0];

  53.         if ((bx[0]+bw) <= (w-1)) bw++;
  54.         if ((by[0]+bh) <= (h-1)) bh++;
  55.         if (bx[0] >= 1) {bx[0]--; bw++;}
  56.         if (by[0] >= 1) {by[0]--; bh++;}

  57.         g.drawImage(this.texture, bx[0], by[0], bw, bh, bx[0], by[0], bw, bh);

  58.         if (shade_clr) {
  59.                 g.fillStyle = shade_clr;
  60.                 g.fillRect(bx[0], by[0], bw, bh);
  61.         }

  62.         g.restore();

  63.         return true;
  64. }

  65. P3D.drawTestByIndexBuffer = function(pos_buf, ix_buf, culling) {
  66.         var g = this.g;

  67.         if ((ix_buf.length%3) != 0)
  68.                 throw "invalid index buffer length!";

  69.         var len = ix_buf.length/3;

  70.         var i, ibase, vbase;
  71.         var poss = [{},{},{}];
  72.         g.strokeWidth = 1;
  73.         for (i = 0, ibase = 0;i < len;++i)
  74.         {
  75.                 vbase = ix_buf[ibase++] << 2;
  76.                 poss[0].x = pos_buf[vbase++];
  77.                 poss[0].y = pos_buf[vbase  ];

  78.                 vbase = ix_buf[ibase++] << 2;
  79.                 poss[1].x = pos_buf[vbase++];
  80.                 poss[1].y = pos_buf[vbase  ];

  81.                 vbase = ix_buf[ibase++] << 2;
  82.                 poss[2].x = pos_buf[vbase++];
  83.                 poss[2].y = pos_buf[vbase  ];

  84.                 // z component of cross product < 0 ?

  85.                 var Ax = poss[1].x - poss[0].x;
  86.                 var Ay = poss[1].y - poss[0].y;
  87.                 var Cx = poss[2].x - poss[1].x;
  88.                 var Cy = poss[2].y - poss[1].y;

  89.                 var cull = ( (((Ax * Cy) - (Ay * Cx))*culling) < 0);

  90.                 g.beginPath();
  91.                 g.strokeStyle = cull ? "#592" : "#0f0";
  92.                 g.moveTo(poss[0].x, poss[0].y);
  93.                 g.lineTo(poss[1].x, poss[1].y);
  94.                 g.lineTo(poss[2].x, poss[2].y);
  95.                 g.lineTo(poss[0].x, poss[0].y);
  96.                 g.stroke();
  97.         }
  98. }

  99. P3D.drawByIndexBuffer = function(pos_buf, ix_buf, tx_buf, culling, z_clip) {
  100.         var w, h;
  101.         var color_polygon = !this.texture;
  102.         if (this.texture) {
  103.                 w = this.texture.width;
  104.                 h = this.texture.height;
  105.         }

  106.         var g = this.g;
  107.         var m = new M22();

  108.         if (!culling) culling = 0;

  109.         if ((ix_buf.length%3) != 0)
  110.                 throw "invalid index buffer length!";

  111.         var i, ibase, vbase, tbase, poss = [{},{},{}];
  112.         var len = ix_buf.length/3;
  113.         var uv_0u, uv_0v, uv_1u, uv_1v, uv_2u, uv_2v;

  114.         for (i = 0, ibase = 0;i < len;++i)
  115.         {
  116.                 tbase = ix_buf[ibase++] << 1
  117.                 vbase = tbase << 1;
  118.                 poss[0].x = pos_buf[vbase++]; uv_0u = tx_buf[tbase++];
  119.                 poss[0].y = pos_buf[vbase++]; uv_0v = tx_buf[tbase];
  120.                 if (z_clip && (pos_buf[vbase] < 0 || pos_buf[vbase] > 1)) {ibase += 2; continue;}

  121.                 tbase = ix_buf[ibase++] << 1
  122.                 vbase = tbase << 1;
  123.                 poss[1].x = pos_buf[vbase++]; uv_1u = tx_buf[tbase++];
  124.                 poss[1].y = pos_buf[vbase++]; uv_1v = tx_buf[tbase];
  125.                 if (z_clip && (pos_buf[vbase] < 0 || pos_buf[vbase] > 1)) {++ibase; continue;}

  126.                 tbase = ix_buf[ibase++] << 1
  127.                 vbase = tbase << 1;
  128.                 poss[2].x = pos_buf[vbase++]; uv_2u = tx_buf[tbase++];
  129.                 poss[2].y = pos_buf[vbase++]; uv_2v = tx_buf[tbase];
  130.                 if (z_clip && (pos_buf[vbase] < 0 || pos_buf[vbase] > 1)) {continue;}

  131.                 var vAd = [ poss[1].x - poss[0].x , poss[1].y - poss[0].y ];
  132.                 var vBd = [ poss[2].x - poss[0].x , poss[2].y - poss[0].y ];

  133.                 var vCd = [ poss[2].x - poss[1].x , poss[2].y - poss[1].y ];

  134.                 // z component of cross product < 0 ?
  135.                 if( (((vAd[0] * vCd[1]) - (vAd[1] * vCd[0]))*culling) < 0)
  136.                         continue;

  137.                 if (color_polygon) {
  138.                         g.fillStyle = uv_0u;

  139.                         g.beginPath();
  140.                         g.moveTo(poss[0].x, poss[0].y);
  141.                         g.lineTo(poss[1].x, poss[1].y);
  142.                         g.lineTo(poss[2].x, poss[2].y);
  143.                         g.fill();
  144.                         continue;
  145.                 }

  146.                 var vA = [ uv_1u - uv_0u , uv_1v - uv_0v ];
  147.                 var vB = [ uv_2u - uv_0u , uv_2v - uv_0v ];

  148.                 vA[0] *= w;
  149.                 vA[1] *= h;

  150.                 vB[0] *= w;
  151.                 vB[1] *= h;

  152.                 m._11 = vA[0];
  153.                 m._12 = vA[1];
  154.                 m._21 = vB[0];
  155.                 m._22 = vB[1];

  156.                 var im = m.getInvert();
  157.                 if (!im) { continue;}

  158.                 var a = im._11 * vAd[0] + im._12 * vBd[0];
  159.                 var b = im._21 * vAd[0] + im._22 * vBd[0];

  160.                 var c = im._11 * vAd[1] + im._12 * vBd[1];
  161.                 var d = im._21 * vAd[1] + im._22 * vBd[1];

  162.                 var wu = uv_0u * w;
  163.                 var hv = uv_0v * h;
  164.                 var du = wu * a + hv * b;
  165.                 var dv = wu * c + hv * d;

  166.                 g.save();

  167.                 g.beginPath();
  168.                 g.moveTo(poss[0].x, poss[0].y);
  169.                 g.lineTo(poss[1].x, poss[1].y);
  170.                 g.lineTo(poss[2].x, poss[2].y);
  171.                 g.clip();
  172.                 g.transform(a, c, b, d, poss[0].x - du, poss[0].y - dv);

  173.                 // bounds
  174.                 var bx = [wu, wu+vA[0], wu+vB[0]];
  175.                 var by = [hv, hv+vA[1], hv+vB[1]];

  176.                 bx.sort(P3D.num_cmp);
  177.                 by.sort(P3D.num_cmp);

  178.                 var bw = bx[2] - bx[0];
  179.                 var bh = by[2] - by[0];

  180.                 if ((bx[0]+bw) <= (w-1)) bw++;
  181.                 if ((by[0]+bh) <= (h-1)) bh++;
  182.                 if (bx[0] >= 1) {bx[0]--; bw++;}
  183.                 if (by[0] >= 1) {by[0]--; bh++;}

  184.                 g.drawImage(this.texture, bx[0], by[0], bw, bh, bx[0], by[0], bw, bh);
  185. /*
  186.                 if (shade_clr) {
  187.                         g.fillStyle = shade_clr;
  188.                         g.fillRect(bx[0], by[0], bw, bh);
  189.                 }
  190. */
  191.                 g.restore();

  192.         }

  193. }

  194. function Vec3(_x, _y, _z)
  195. {
  196.         this.x = _x || 0;
  197.         this.y = _y || 0;
  198.         this.z = _z || 0;
  199. }

  200. Vec3.prototype = {
  201.         zero: function() {
  202.                 this.x = this.y = this.z = 0;
  203.         },

  204.         sub: function(v) {
  205.                 this.x -= v.x;
  206.                 this.y -= v.y;
  207.                 this.z -= v.z;

  208.                 return this;
  209.         },

  210.         add: function(v) {
  211.                 this.x += v.x;
  212.                 this.y += v.y;
  213.                 this.z += v.z;

  214.                 return this;
  215.         },

  216.         copyFrom: function(v) {
  217.                 this.x = v.x;
  218.                 this.y = v.y;
  219.                 this.z = v.z;

  220.                 return this;
  221.         },

  222.         norm:function() {
  223.                 return Math.sqrt(this.x*this.x + this.y*this.y + this.z*this.z);
  224.         },

  225.         normalize: function() {
  226.                 var nrm = Math.sqrt(this.x*this.x + this.y*this.y + this.z*this.z);
  227.                 if (nrm != 0)
  228.                 {
  229.                         this.x /= nrm;
  230.                         this.y /= nrm;
  231.                         this.z /= nrm;
  232.                 }
  233.                 return this;
  234.         },

  235.         smul: function(k) {
  236.                 this.x *= k;
  237.                 this.y *= k;
  238.                 this.z *= k;

  239.                 return this;
  240.         },

  241.         dpWith: function(v)        {
  242.                 return this.x*v.x + this.y*v.y + this.z*v.z;
  243.         },

  244.         cp: function(v, w) {
  245.                 this.x = (w.y * v.z) - (w.z * v.y);
  246.                 this.y = (w.z * v.x) - (w.x * v.z);
  247.                 this.z = (w.x * v.y) - (w.y * v.x);

  248.                 return this;
  249.         },

  250.         toString: function() {
  251.                 return this.x + ", " + this.y + "," + this.z;
  252.         }
  253. }

  254. function M44(cpy)
  255. {
  256.         if (cpy)
  257.                 this.copyFrom(cpy);
  258.         else {
  259.                 this.ident();
  260.         }
  261. }

  262. M44.prototype = {
  263.         ident: function() {
  264.                           this._12 = this._13 = this._14 = 0;
  265.                 this._21 =       this._23 = this._24 = 0;
  266.                 this._31 = this._32 =       this._34 = 0;
  267.                 this._41 = this._42 = this._43 =       0;

  268.                 this._11 = this._22 = this._33 = this._44 = 1;

  269.                 return this;
  270.         },

  271.         copyFrom: function(m) {
  272.                 this._11 = m._11;
  273.                 this._12 = m._12;
  274.                 this._13 = m._13;
  275.                 this._14 = m._14;

  276.                 this._21 = m._21;
  277.                 this._22 = m._22;
  278.                 this._23 = m._23;
  279.                 this._24 = m._24;

  280.                 this._31 = m._31;
  281.                 this._32 = m._32;
  282.                 this._33 = m._33;
  283.                 this._34 = m._34;

  284.                 this._41 = m._41;
  285.                 this._42 = m._42;
  286.                 this._43 = m._43;
  287.                 this._44 = m._44;

  288.                 return this;
  289.         },

  290.         transVec3: function(out, x, y, z) {
  291.                 out[0] = x * this._11 + y * this._21 + z * this._31 + this._41;
  292.                 out[1] = x * this._12 + y * this._22 + z * this._32 + this._42;
  293.                 out[2] = x * this._13 + y * this._23 + z * this._33 + this._43;
  294.                 out[3] = x * this._14 + y * this._24 + z * this._34 + this._44;
  295.         },

  296.         transVec3Rot: function(out, x, y, z) {
  297.                 out[0] = x * this._11 + y * this._21 + z * this._31;
  298.                 out[1] = x * this._12 + y * this._22 + z * this._32;
  299.                 out[2] = x * this._13 + y * this._23 + z * this._33;
  300.         },

  301.         perspectiveLH: function(vw, vh, z_near, z_far) {
  302.                 this._11 = 2.0*z_near/vw;
  303.                 this._12 = 0;
  304.                 this._13 = 0;
  305.                 this._14 = 0;

  306.                 this._21 = 0;
  307.                 this._22 = 2*z_near/vh;
  308.                 this._23 = 0;
  309.                 this._24 = 0;

  310.                 this._31 = 0;
  311.                 this._32 = 0;
  312.                 this._33 = z_far/(z_far-z_near);
  313.                 this._34 = 1;

  314.                 this._41 = 0;
  315.                 this._42 = 0;
  316.                 this._43 = z_near*z_far/(z_near-z_far);
  317.                 this._44 = 0;

  318.                 return this;
  319.         },

  320.         lookAtLH: function(aUp, aFrom, aAt) {
  321.                 var aX = new Vec3();
  322.                 var aY = new Vec3();

  323.                 var aZ = new Vec3(aAt.x, aAt.y, aAt.z);
  324.                 aZ.sub(aFrom).normalize();

  325.                 aX.cp(aUp, aZ).normalize();
  326.                 aY.cp(aZ, aX);

  327.                 this._11 = aX.x;  this._12 = aY.x;  this._13 = aZ.x;  this._14 = 0;
  328.                 this._21 = aX.y;  this._22 = aY.y;  this._23 = aZ.y;  this._24 = 0;
  329.                 this._31 = aX.z;  this._32 = aY.z;  this._33 = aZ.z;  this._34 = 0;

  330.                 this._41 = -aFrom.dpWith(aX);
  331.                 this._42 = -aFrom.dpWith(aY);
  332.                 this._43 = -aFrom.dpWith(aZ);
  333.                 this._44 = 1;

  334.             return this;
  335.         },

  336.         mul: function(A, B) {
  337.                 this._11 = A._11*B._11  +  A._12*B._21  +  A._13*B._31  +  A._14*B._41;
  338.                 this._12 = A._11*B._12  +  A._12*B._22  +  A._13*B._32  +  A._14*B._42;
  339.                 this._13 = A._11*B._13  +  A._12*B._23  +  A._13*B._33  +  A._14*B._43;
  340.                 this._14 = A._11*B._14  +  A._12*B._24  +  A._13*B._34  +  A._14*B._44;

  341.                 this._21 = A._21*B._11  +  A._22*B._21  +  A._23*B._31  +  A._24*B._41;
  342.                 this._22 = A._21*B._12  +  A._22*B._22  +  A._23*B._32  +  A._24*B._42;
  343.                 this._23 = A._21*B._13  +  A._22*B._23  +  A._23*B._33  +  A._24*B._43;
  344.                 this._24 = A._21*B._14  +  A._22*B._24  +  A._23*B._34  +  A._24*B._44;

  345.                 this._31 = A._31*B._11  +  A._32*B._21  +  A._33*B._31  +  A._34*B._41;
  346.                 this._32 = A._31*B._12  +  A._32*B._22  +  A._33*B._32  +  A._34*B._42;
  347.                 this._33 = A._31*B._13  +  A._32*B._23  +  A._33*B._33  +  A._34*B._43;
  348.                 this._34 = A._31*B._14  +  A._32*B._24  +  A._33*B._34  +  A._34*B._44;

  349.                 this._41 = A._41*B._11  +  A._42*B._21  +  A._43*B._31  +  A._44*B._41;
  350.                 this._42 = A._41*B._12  +  A._42*B._22  +  A._43*B._32  +  A._44*B._42;
  351.                 this._43 = A._41*B._13  +  A._42*B._23  +  A._43*B._33  +  A._44*B._43;
  352.                 this._44 = A._41*B._14  +  A._42*B._24  +  A._43*B._34  +  A._44*B._44;

  353.                 return this;
  354.         },

  355.         translate: function(x, y, z) {
  356.                 this._11 = 1;  this._12 = 0;  this._13 = 0;  this._14 = 0;
  357.                 this._21 = 0;  this._22 = 1;  this._23 = 0;  this._24 = 0;
  358.                 this._31 = 0;  this._32 = 0;  this._33 = 1;  this._34 = 0;

  359.                 this._41 = x;  this._42 = y;  this._43 = z;  this._44 = 1;
  360.                 return this;
  361.         },

  362.         transpose33: function() {
  363.                 var t;

  364.                 t = this._12;
  365.                 this._12 = this._21;
  366.                 this._21 = t;

  367.                 t = this._13;
  368.                 this._13 = this._31;
  369.                 this._31 = t;

  370.                 t = this._23;
  371.                 this._23 = this._32;
  372.                 this._32 = t;

  373.                 return this;
  374.         },

  375.         // OpenGL style rotation
  376.         glRotate: function(angle, x, y, z) {
  377.                 var s = Math.sin( angle );
  378.                 var c = Math.cos( angle );

  379.                 var xx = x * x;
  380.                 var yy = y * y;
  381.                 var zz = z * z;
  382.                 var xy = x * y;
  383.                 var yz = y * z;
  384.                 var zx = z * x;
  385.                 var xs = x * s;
  386.                 var ys = y * s;
  387.                 var zs = z * s;
  388.                 var one_c = 1.0 - c;
  389. /*
  390.                 this._11 = (one_c * xx) + c;
  391.                 this._21 = (one_c * xy) - zs;
  392.                 this._31 = (one_c * zx) + ys;
  393.                 this._41 = 0;

  394.                 this._12 = (one_c * xy) + zs;
  395.                 this._22 = (one_c * yy) + c;
  396.                 this._32 = (one_c * yz) - xs;
  397.                 this._42 = 0;

  398.                 this._13 = (one_c * zx) - ys;
  399.                 this._23 = (one_c * yz) + xs;
  400.                 this._33 = (one_c * zz) + c;
  401.                 this._43 = 0;

  402.                 this._14 = 0;
  403.                 this._24 = 0;
  404.                 this._34 = 0;
  405.                 this._44 = 1;
  406. */

  407.                 this._11 = (one_c * xx) + c;
  408.                 this._12 = (one_c * xy) - zs;
  409.                 this._13 = (one_c * zx) + ys;
  410.                 this._14 = 0;

  411.                 this._21 = (one_c * xy) + zs;
  412.                 this._22 = (one_c * yy) + c;
  413.                 this._23 = (one_c * yz) - xs;
  414.                 this._24 = 0;

  415.                 this._31 = (one_c * zx) - ys;
  416.                 this._32 = (one_c * yz) + xs;
  417.                 this._33 = (one_c * zz) + c;
  418.                 this._34 = 0;

  419.                 this._41 = 0;
  420.                 this._42 = 0;
  421.                 this._43 = 0;
  422.                 this._44 = 1;

  423.                 return this;
  424.         }

  425. }

  426. // matrix 2x2
  427. function M22()
  428. {
  429.         this._11 = 1;
  430.         this._12 = 0;
  431.         this._21 = 0;
  432.         this._22 = 1;
  433. }

  434. M22.prototype.getInvert = function()
  435. {
  436.         var out = new M22();
  437.         var det = this._11 * this._22 - this._12 * this._21;
  438.         if (det > -0.0001 && det < 0.0001)
  439.                 return null;

  440.         out._11 = this._22 / det;
  441.         out._22 = this._11 / det;

  442.         out._12 = -this._12 / det;
  443.         out._21 = -this._21 / det;

  444.         return out;
  445. }
复制代码
3D衣服动画JS代码
  1. function ClothApp()
  2. {
  3.         this.canvas = document.getElementById("cv");

  4.         P3D.g = this.canvas.getContext("2d");

  5.         var tex = new Image();
  6.         this.texture1 = tex;
  7.         tex.onload = function(){ _this.start(); };
  8.         tex.src = "20090226032826.gif";

  9.         tex = new Image();
  10.         this.texture2 = tex;
  11.         tex.onload = function(){ _this.start(); };
  12.         tex.src = "20090226032825.png";

  13.         this.mLoadCount = 2;
  14.         this.mTickCount = 0;

  15.         this.G = 0.53;
  16.         this.G1 = 0.45;
  17.         this.mProjMat  = null;
  18.         this.mViewMat  = null;
  19.         this.mViewFrom = new Vec3();
  20.         this.mViewFrom.y = -150;
  21.         this.mViewFrom.z = 1000;
  22.         this.mViewFromA = (new Vec3()).copyFrom(this.mViewFrom);

  23.         this.mViewAngle = 0;

  24.         this.mNLen = 0;
  25.         this.mNodes = [];
  26.         this.mRenderTris = null;

  27.         this.mLTNode = null;
  28.         this.mRTNode = null;

  29.         this.mLTNodeV = new Vec3();
  30.         this.mRTNodeV = new Vec3();

  31.         this.mWForce = new Vec3();
  32.         this.frate = 15;

  33.         var _this = this;
  34. }

  35. ClothApp.zsortCmp = function(t1, t2) {
  36.         return t2.sortKey - t1.sortKey;
  37. }

  38. ClothApp.prototype = {
  39.         start: function() {
  40.                 if (--this.mLoadCount != 0) return;

  41.                 this.vUP = new Vec3(0,  1, 0);
  42.                 this.vAT = new Vec3(0, 80, 0);

  43.                 this.mViewport = {};
  44.                 this.mViewport.w = 480;
  45.                 this.mViewport.h = 300;
  46.                 this.mViewport.ow = 240;
  47.                 this.mViewport.oh = 150;
  48.                 this.setupTransforms();

  49.                 this.generateCloth(180);
  50.                 this.generateRenderTriangles();

  51.                 var _this = this;
  52.                 this.canvas.addEventListener("mousemove", function(e){_this.onMouseMove(e);}, false);
  53.                 this.canvas.addEventListener("mousedown", function(e){_this.onClick(e);}, false);

  54.                 window.setTimeout(function(){_this.onInterval();}, this.frate);
  55.         },

  56.         onInterval: function() {
  57.                 this.mTickCount++;

  58.                 // this.mLTNodeV.z = Math.cos(this.mTickCount*0.1) * 2;

  59.                 this.tick();
  60.                 this.updatePosition();
  61.                 this.draw();

  62.                 var _this = this;
  63.                 window.setTimeout(function(){_this.onInterval();}, this.frate);
  64.         },

  65.         onMouseMove: function(e) {
  66.                 if (e.clientX || e.clientX == 0)
  67.                         this.mViewAngle = (e.clientX - 240) * 0.004;

  68.                 if (e.clientY || e.clientY == 0)
  69.                         this.mViewFromA.y = 90 - (e.clientY - 0) * 0.8;
  70.         },

  71.         onClick: function(e) {
  72.                 if (e.clientX || e.clientX == 0)
  73.                 {
  74.                         this.mWForce.z = -4;
  75.                         this.mWForce.x = (e.clientX - 240) * -0.03;
  76.                 }
  77.         },

  78.         tick: function() {
  79.                 this.updateViewTrans(this.mViewAngle);

  80.                 var nlen = this.mNodes.length;
  81.                 var i, nd;
  82.                 for(i = 0;i < nlen;i++)
  83.                 {
  84.                         nd = this.mNodes[i];
  85.                         nd.F.x = 0;
  86.                         nd.F.z = 0;
  87.                         if (nd.flags & 4)
  88.                                 nd.F.y = -this.G1;
  89.                         else
  90.                                 nd.F.y = -this.G;

  91.                         nd.F.add(this.mWForce);
  92.                 }

  93.                 this.mWForce.zero();
  94.                 this.applyTension();

  95.                 for(i = 0;i < nlen;i++)
  96.                 {
  97.                         nd = this.mNodes[i];

  98.                         if ((nd.flags&1) != 0) {
  99.                                 nd.F.sub(nd.F);
  100.                         }

  101.                         nd.velo.add(nd.F);
  102.                 }

  103.                 this.mLTNode.velo.copyFrom(this.mLTNodeV);
  104.                 this.mRTNode.velo.copyFrom(this.mRTNodeV);
  105.         },

  106.         updatePosition: function() {
  107.                 var nlen = this.mNodes.length;
  108.                 var i, nd;
  109.                 for(i = 0;i < nlen;i++)
  110.                 {
  111.                         nd = this.mNodes[i];

  112.                         if ((nd.flags&1) != 0) {
  113.                                 nd.cv.x = 0;
  114.                                 nd.cv.y = 0;
  115.                                 nd.cv.z = 0;
  116.                         }

  117.                         nd.pos.add(nd.velo);
  118.                         nd.velo.sub(nd.cv);
  119.                         nd.cv.x = 0;
  120.                         nd.cv.y = 0;
  121.                         nd.cv.z = 0;

  122.                         nd.velo.smul(0.95);
  123.                 }
  124.         },

  125.         draw: function() {
  126.                 P3D.clear("#000", this.mViewport.w, this.mViewport.h);
  127.                 this.transformPolygons();

  128.                 this.mRenderTris.sort(ClothApp.zsortCmp);
  129.                 var len = this.mRenderTris.length;
  130.                 var t, sh;
  131.                 for (var i = 0;i < len;i++) {
  132.                         t = this.mRenderTris[i];

  133.                         if (P3D.texture != t.texture)
  134.                                 P3D.texture = t.texture;

  135.                         sh = undefined;
  136.                         if (t.lighting && t.shade > 0.01)
  137.                                 sh = "rgba(0,0,0,"+t.shade+")";
  138.                         P3D.drawTriangle(t.tposs, t.uvs, sh);
  139.                 }
  140.         },

  141.         applyTension: function() {
  142.                 var i, k, nd;
  143.                 var v = new Vec3();
  144.                 var nlen = this.mNodes.length;
  145.                 var naturalLen = this.mNLen;

  146.                 for (k = 0;k < nlen;k++)
  147.                 {
  148.                         nd = this.mNodes[k];
  149.                         var F = nd.F;

  150.                         for (i = 0;i < 4;i++)
  151.                         {
  152.                                 var nbr = nd.links[i];
  153.                                 if (!nbr) continue;

  154.                                 var len = v.copyFrom(nbr.pos).sub(nd.pos).norm();
  155.                                 var dlen = len - naturalLen;
  156.                                 if (dlen > 0) {
  157.                                         v.smul(dlen * 0.5 / len);

  158.                                         F.x += v.x;
  159.                                         F.y += v.y;
  160.                                         F.z += v.z;
  161.                                         nd.cv.add(v.smul(0.8));
  162.                                 }
  163.                         }
  164.                 }       
  165.         },

  166.         setupTransforms: function() {
  167.                 this.mProjMat = new M44();
  168.                 this.mProjMat.perspectiveLH(24, 15, 10, 9000);

  169.                 this.mViewMat = new M44();
  170.                 this.updateViewTrans(0);
  171.         },

  172.         updateViewTrans: function(ry) {
  173.                 this.mViewFromA.z = Math.cos(ry) * 380;
  174.                 this.mViewFromA.x = Math.sin(ry) * 380;

  175.                 this.mViewFrom.smul(0.7);
  176.                 this.mViewFrom.x += this.mViewFromA.x * 0.3;
  177.                 this.mViewFrom.y += this.mViewFromA.y * 0.3;
  178.                 this.mViewFrom.z += this.mViewFromA.z * 0.3;

  179.                 this.mViewMat.lookAtLH(this.vUP, this.mViewFrom, this.vAT);
  180.         },

  181.         generateCloth: function(base_y) {
  182.                 var cols = 9;
  183.                 var rows = 8;

  184.                 var step   = 22;
  185.                 this.mNLen = step*0.9;
  186.                 var w = (cols-1) * step;

  187.                 var i, k;
  188.                 for (k = 0;k < rows;k++)
  189.                 {
  190.                         for (i = 0;i < cols;i++)
  191.                         {
  192.                                 var nd = new ClothNode();
  193.                                 nd.pos.x = -(w/2) + i*step;
  194.                                 nd.pos.y = base_y -k*step/2;
  195.                                 nd.pos.z = k*16;

  196.                                 nd.uv.u = i / (cols-1);
  197.                                 nd.uv.v = k / (rows-1);

  198.                                 if (i > 0) {
  199.                                         var prv_nd = this.mNodes[this.mNodes.length-1];
  200.                                         prv_nd.links[1] = nd;
  201.                                         nd.links[0] = prv_nd;
  202.                                 }

  203.                                 if (k > 0) {
  204.                                         var up_nd = this.mNodes[this.mNodes.length-cols];
  205.                                         up_nd.links[4] = nd;
  206.                                         nd.links[3] = up_nd;
  207.                                 }

  208.                                 if (i != 0 && i != 4 && i != (cols-1))
  209.                                         nd.flags |= 4;

  210.                                 this.mNodes.push(nd);
  211.                         }
  212.                 }

  213.                 // fix left-top and right-top
  214.                 this.mNodes[0     ].flags |= 1;
  215.                 this.mNodes[4     ].flags |= 1;
  216.                 this.mNodes[cols-1].flags |= 1;

  217.                 this.mLTNode = this.mNodes[0     ];
  218.                 this.mRTNode = this.mNodes[cols-1];
  219.         },

  220.         generateRenderTriangles: function()
  221.         {
  222.                 if (!this.mRenderTris) this.mRenderTris = [];

  223.                 var i;
  224.                 var nd;
  225.                 var nlen = this.mNodes.length;

  226.                 for(i = 0;i < nlen;i++)
  227.                 {
  228.                         nd = this.mNodes[i];
  229.                         if (nd.links[1] && nd.links[1].links[4]) {
  230.                                 var t = new RenderTriangle();
  231.                                 t.texture = this.texture1;

  232.                                 t.poss[0] = nd.pos;
  233.                                 t.poss[1] = nd.links[1].pos;
  234.                                 t.poss[2] = nd.links[1].links[4].pos;

  235.                                 t.uvs[0]  = nd.uv;
  236.                                 t.uvs[1]  = nd.links[1].uv;
  237.                                 t.uvs[2]  = nd.links[1].links[4].uv;

  238.                                 this.mRenderTris.push(t);

  239.                                 t = new RenderTriangle();
  240.                                 t.texture = this.texture1;

  241.                                 t.poss[0] = nd.pos;
  242.                                 t.poss[1] = nd.links[1].links[4].pos;
  243.                                 t.poss[2] = nd.links[4].pos;

  244.                                 t.uvs[0]  = nd.uv;
  245.                                 t.uvs[1]  = nd.links[1].links[4].uv;
  246.                                 t.uvs[2]  = nd.links[4].uv;

  247.                                 this.mRenderTris.push(t);
  248.                         }
  249.                 }

  250.                 this.addBGTriangles(this.mNodes[0].pos.y);
  251.         },

  252.         addBGTriangles: function(by) {
  253.                 var cols = 4;
  254.                 var t, x, y, sz = 110;
  255.                 var ox = -(cols*sz)/2;
  256.                 var oz = -(cols*sz)/2;

  257.                 for (y = 0;y < cols;y++) {
  258.                         for (x = 0;x < cols;x++) {
  259.                                 var bv = ((x+y)&1) * 0.5;
  260.                                 t = new RenderTriangle();
  261.                                 t.texture = this.texture2;

  262.                                 t.poss[0] = new Vec3(ox + x*sz     , by, oz + y*sz     );
  263.                                 t.poss[1] = new Vec3(ox + x*sz + sz, by, oz + y*sz     );
  264.                                 t.poss[2] = new Vec3(ox + x*sz     , by, oz + y*sz + sz);

  265.                                 t.uvs[0]  = {u:0  , v:bv    };
  266.                                 t.uvs[1]  = {u:0.5, v:bv    };
  267.                                 t.uvs[2]  = {u:0  , v:bv+0.5};

  268.                                 if ((x==1 || x==2) && (y==1 || y==2))
  269.                                         this.modifyRoofUV(t, x == 2, bv);

  270.                                 t.lighting = false;
  271.                                 t.zBias = 0.5;
  272.                                 this.mRenderTris.push(t);

  273.                                 t = new RenderTriangle();
  274.                                 t.texture = this.texture2;

  275.                                 t.poss[0] = new Vec3(ox + x*sz     , by, oz + y*sz + sz);
  276.                                 t.poss[1] = new Vec3(ox + x*sz + sz, by, oz + y*sz    );
  277.                                 t.poss[2] = new Vec3(ox + x*sz + sz, by, oz + y*sz + sz);

  278.                                 t.uvs[0]  = {u:0  , v:bv+0.5};
  279.                                 t.uvs[1]  = {u:0.5, v:bv    };
  280.                                 t.uvs[2]  = {u:0.5, v:bv+0.5};

  281.                                 if ((x==1 || x==2) && (y==1 || y==2))
  282.                                         this.modifyRoofUV(t, x == 2, bv);

  283.                                 t.lighting = false;
  284.                                 t.zBias = 0.5;
  285.                                 this.mRenderTris.push(t);

  286.                         }
  287.                 }
  288.         },

  289.         modifyRoofUV: function(t, rv, bv) {
  290.                 if (rv) {
  291.                         t.uvs[0].u = 0.5 - t.uvs[0].u;
  292.                         t.uvs[1].u = 0.5 - t.uvs[1].u;
  293.                         t.uvs[2].u = 0.5 - t.uvs[2].u;
  294.                 }

  295.                 t.uvs[0].u += 0.5;
  296.                 t.uvs[1].u += 0.5;
  297.                 t.uvs[2].u += 0.5;

  298.                 if (rv) {
  299.                         t.uvs[0].v = 0.5 - t.uvs[0].v + bv + bv;
  300.                         t.uvs[1].v = 0.5 - t.uvs[1].v + bv + bv;
  301.                         t.uvs[2].v = 0.5 - t.uvs[2].v + bv + bv;
  302.                 }

  303.         },

  304.         transformPolygons: function() {
  305.                 var trans = new M44();
  306.                 trans.mul(this.mViewMat, this.mProjMat);

  307.                 var hw = this.mViewport.ow;
  308.                 var hh = this.mViewport.oh;

  309.                 var len = this.mRenderTris.length;
  310.                 var t;
  311.                 var spos = [0, 0, 0, 0];
  312.                 for (var i = 0;i < len;i++) {
  313.                         t = this.mRenderTris[i];
  314.                         for (var k = 0;k < 3;k++) {
  315.                                 trans.transVec3(spos, t.poss[k].x, t.poss[k].y, t.poss[k].z);

  316.                                 var W = spos[3];
  317.                                 spos[0] /= W;
  318.                                 spos[1] /= W;
  319.                                 spos[2] /= W;

  320.                                 spos[0] *= this.mViewport.w;
  321.                                 spos[1] *= -this.mViewport.h;
  322.                                 spos[0] += hw;
  323.                                 spos[1] += hh;

  324.                                 t.tposs[k].x = spos[0];
  325.                                 t.tposs[k].y = spos[1];
  326.                                 t.tposs[k].z = spos[2];
  327.                         }

  328.                         var v1 = (new Vec3()).copyFrom(t.poss[1]).sub(t.poss[0]).normalize();
  329.                         var v2 = (new Vec3()).copyFrom(t.poss[2]).sub(t.poss[1]).normalize();
  330.                         var N = (new Vec3()).cp(v1, v2);

  331.                         trans.transVec3Rot(spos, N.x, N.y, N.z);

  332.                         if (t.lighting) {
  333.                                 if (spos[2] > 0)
  334.                                         t.shade = 0.8
  335.                                 else {
  336.                                         t.shade = 0.1 - N.y * 0.6;
  337.                                         if (t.shade < 0) t.shade = 0;
  338.                                 }
  339.                         }

  340.                         t.sortKey = Math.floor( (t.tposs[0].z + t.tposs[1].z + t.tposs[2].z + t.zBias) *1000 );
  341.                 }
  342.         }
  343. }

  344. function ClothNode()
  345. {
  346.         this.flags = 0;
  347.         this.pos  = new Vec3();
  348.         this.velo = new Vec3();
  349.         this.cv   = new Vec3();
  350.         this.F    = new Vec3();
  351.         this.links = [null, null, null, null];
  352.         this.uv = {u:0, v:0};
  353. }

  354. function RenderTriangle()
  355. {
  356.         this.texture = null;
  357.         this.poss  = new Array(3);
  358.         this.tposs = [new Vec3(), new Vec3(), new Vec3()];
  359.         this.uvs = [{u:0, v:0}, {u:0, v:0}, {u:0, v:0}];
  360.         this.shade = 0;
  361.         this.lighting = true;
  362.         this.zBias = 0;

  363.         this.sortKey = 0;
  364. }
复制代码
以上就是HTML5 3D衣服摇摆动画特效的源码介绍,需要更为深入学习的下载源代码来研究。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

快速回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

站长推荐上一条 /1 下一条

快速回复 扫码关注微信二维码 返回顶部 返回列表