欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

HTML5 3D衣服摇摆动画特效

程序员文章站 2022-10-15 18:07:54
这篇文章主要为大家分享了一款HTML5 3D衣服摇摆动画特效,一款基于HTML5 Canvas的3D动画杰作,感兴趣的小伙伴们可以参考一下... 16-03-17...

这又是一款基于html5 canvas的3d动画杰作,它是一个可以随风飘动的3d衣服摇摆动画特效,非常逼真。当我们将鼠标滑过衣服时,衣服将会出现摇摆的动画,点击鼠标时,衣服将会更加剧烈地摆动。

HTML5 3D衣服摇摆动画特效

 

html代码

xml/html code复制内容到剪贴板
  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效果的

javascript code复制内容到剪贴板
  1. window.p3d = {   
  2.  texture: null,   
  3.  g: null  
  4. };   
  5.   
  6. p3d.clear = function(f, w, h) {   
  7.  var g = this.g;   
  8.  g.beginpath();   
  9.  g.fillstyle = f;   
  10.  g.fillrect(0, 0, w, h);   
  11.   
  12. }   
  13.   
  14. p3d.num_cmp = function(a,b){return a-b;}   
  15.   
  16. p3d.drawtriangle = function(poss, uvs, shade_clr) {   
  17.  var w = this.texture.width;   
  18.  var h = this.texture.height;   
  19.   
  20.  var g = this.g;   
  21.   
  22.  var vad = [ poss[1].x - poss[0].x , poss[1].y - poss[0].y ];   
  23.  var vbd = [ poss[2].x - poss[0].x , poss[2].y - poss[0].y ];   
  24.   
  25.  var va = [ uvs[1].u - uvs[0].u , uvs[1].v - uvs[0].v ];   
  26.  var vb = [ uvs[2].u - uvs[0].u , uvs[2].v - uvs[0].v ];   
  27.   
  28.  va[0] *= w;   
  29.  va[1] *= h;   
  30.   
  31.  vb[0] *= w;   
  32.  vb[1] *= h;   
  33.   
  34.  var m = new m22();   
  35.  m._11 = va[0];   
  36.  m._12 = va[1];   
  37.  m._21 = vb[0];   
  38.  m._22 = vb[1];   
  39.   
  40.  var im = m.getinvert();   
  41.  if (!im) return false;   
  42.   
  43.  var a = im._11 * vad[0] + im._12 * vbd[0];   
  44.  var b = im._21 * vad[0] + im._22 * vbd[0];   
  45.   
  46.  var c = im._11 * vad[1] + im._12 * vbd[1];   
  47.  var d = im._21 * vad[1] + im._22 * vbd[1];   
  48.   
  49.  var wu = uvs[0].u * w;   
  50.  var hv = uvs[0].v * h;   
  51.  var du = wu * a + hv * b;   
  52.  var dv = wu * c + hv * d;   
  53.   
  54.  g.save();   
  55.   
  56.  g.beginpath();   
  57.  g.moveto(poss[0].x, poss[0].y);   
  58.  g.lineto(poss[1].x, poss[1].y);   
  59.  g.lineto(poss[2].x, poss[2].y);   
  60.  g.clip();   
  61.   
  62.  g.transform(a, c, b, d, poss[0].x - du, poss[0].y - dv);   
  63.   
  64.  // bounds   
  65.  var bx = [wu, wu+va[0], wu+vb[0]];   
  66.  var by = [hv, hv+va[1], hv+vb[1]];   
  67.   
  68.  bx.sort(p3d.num_cmp);   
  69.  by.sort(p3d.num_cmp);   
  70.   
  71.  var bw = bx[2] - bx[0];   
  72.  var bh = by[2] - by[0];   
  73.   
  74.  if ((bx[0]+bw) <= (w-1)) bw++;   
  75.  if ((by[0]+bh) <= (h-1)) bh++;   
  76.  if (bx[0] >= 1) {bx[0]--; bw++;}   
  77.  if (by[0] >= 1) {by[0]--; bh++;}   
  78.   
  79.  g.drawimage(this.texture, bx[0], by[0], bw, bh, bx[0], by[0], bw, bh);   
  80.   
  81.  if (shade_clr) {   
  82.   g.fillstyle = shade_clr;   
  83.   g.fillrect(bx[0], by[0], bw, bh);   
  84.  }   
  85.   
  86.  g.restore();   
  87.   
  88.  return true;   
  89. }   
  90.   
  91. p3d.drawtestbyindexbuffer = function(pos_buf, ix_buf, culling) {   
  92.  var g = this.g;   
  93.   
  94.  if ((ix_buf.length%3) != 0)   
  95.   throw "invalid index buffer length!";   
  96.   
  97.  var len = ix_buf.length/3;   
  98.   
  99.  var i, ibase, vbase;   
  100.  var poss = [{},{},{}];   
  101.  g.strokewidth = 1;   
  102.  for (i = 0, ibase = 0;i < len;++i)   
  103.  {   
  104.   vbase = ix_buf[ibase++] << 2;   
  105.   poss[0].x = pos_buf[vbase++];   
  106.   poss[0].y = pos_buf[vbase  ];   
  107.   
  108.   vbase = ix_buf[ibase++] << 2;   
  109.   poss[1].x = pos_buf[vbase++];   
  110.   poss[1].y = pos_buf[vbase  ];   
  111.   
  112.   vbase = ix_buf[ibase++] << 2;   
  113.   poss[2].x = pos_buf[vbase++];   
  114.   poss[2].y = pos_buf[vbase  ];   
  115.   
  116.   // z component of cross product < 0 ?   
  117.   
  118.   var ax = poss[1].x - poss[0].x;   
  119.   var ay = poss[1].y - poss[0].y;   
  120.   var cx = poss[2].x - poss[1].x;   
  121.   var cy = poss[2].y - poss[1].y;   
  122.   
  123.   var cull = ( (((ax * cy) - (ay * cx))*culling) < 0);   
  124.   
  125.   g.beginpath();   
  126.   g.strokestyle = cull ? "#592" : "#0f0";   
  127.   g.moveto(poss[0].x, poss[0].y);   
  128.   g.lineto(poss[1].x, poss[1].y);   
  129.   g.lineto(poss[2].x, poss[2].y);   
  130.   g.lineto(poss[0].x, poss[0].y);   
  131.   g.stroke();   
  132.  }   
  133. }   
  134.   
  135. p3d.drawbyindexbuffer = function(pos_buf, ix_buf, tx_buf, culling, z_clip) {   
  136.  var w, h;   
  137.  var color_polygon = !this.texture;   
  138.  if (this.texture) {   
  139.   w = this.texture.width;   
  140.   h = this.texture.height;   
  141.  }   
  142.   
  143.  var g = this.g;   
  144.  var m = new m22();   
  145.   
  146.  if (!culling) culling = 0;   
  147.   
  148.  if ((ix_buf.length%3) != 0)   
  149.   throw "invalid index buffer length!";   
  150.   
  151.  var i, ibase, vbase, tbase, poss = [{},{},{}];   
  152.  var len = ix_buf.length/3;   
  153.  var uv_0u, uv_0v, uv_1u, uv_1v, uv_2u, uv_2v;   
  154.   
  155.  for (i = 0, ibase = 0;i < len;++i)   
  156.  {   
  157.   tbase = ix_buf[ibase++] << 1   
  158.   vbase = tbase << 1;   
  159.   poss[0].x = pos_buf[vbase++]; uv_0u = tx_buf[tbase++];   
  160.   poss[0].y = pos_buf[vbase++]; uv_0v = tx_buf[tbase];   
  161.   if (z_clip && (pos_buf[vbase] < 0 || pos_buf[vbase] > 1)) {ibase += 2; continue;}   
  162.   
  163.   tbase = ix_buf[ibase++] << 1   
  164.   vbase = tbase << 1;   
  165.   poss[1].x = pos_buf[vbase++]; uv_1u = tx_buf[tbase++];   
  166.   poss[1].y = pos_buf[vbase++]; uv_1v = tx_buf[tbase];   
  167.   if (z_clip && (pos_buf[vbase] < 0 || pos_buf[vbase] > 1)) {++ibase; continue;}   
  168.   
  169.   tbase = ix_buf[ibase++] << 1   
  170.   vbase = tbase << 1;   
  171.   poss[2].x = pos_buf[vbase++]; uv_2u = tx_buf[tbase++];   
  172.   poss[2].y = pos_buf[vbase++]; uv_2v = tx_buf[tbase];   
  173.   if (z_clip && (pos_buf[vbase] < 0 || pos_buf[vbase] > 1)) {continue;}   
  174.   
  175.   var vad = [ poss[1].x - poss[0].x , poss[1].y - poss[0].y ];   
  176.   var vbd = [ poss[2].x - poss[0].x , poss[2].y - poss[0].y ];   
  177.   
  178.   var vcd = [ poss[2].x - poss[1].x , poss[2].y - poss[1].y ];   
  179.   
  180.   // z component of cross product < 0 ?   
  181.   if( (((vad[0] * vcd[1]) - (vad[1] * vcd[0]))*culling) < 0)   
  182.    continue;   
  183.   
  184.   if (color_polygon) {   
  185.    g.fillstyle = uv_0u;   
  186.   
  187.    g.beginpath();   
  188.    g.moveto(poss[0].x, poss[0].y);   
  189.    g.lineto(poss[1].x, poss[1].y);   
  190.    g.lineto(poss[2].x, poss[2].y);   
  191.    g.fill();   
  192.    continue;   
  193.   }   
  194.   
  195.   var va = [ uv_1u - uv_0u , uv_1v - uv_0v ];   
  196.   var vb = [ uv_2u - uv_0u , uv_2v - uv_0v ];   
  197.   
  198.   va[0] *= w;   
  199.   va[1] *= h;   
  200.   
  201.   vb[0] *= w;   
  202.   vb[1] *= h;   
  203.   
  204.   m._11 = va[0];   
  205.   m._12 = va[1];   
  206.   m._21 = vb[0];   
  207.   m._22 = vb[1];   
  208.   
  209.   var im = m.getinvert();   
  210.   if (!im) { continue;}   
  211.   
  212.   var a = im._11 * vad[0] + im._12 * vbd[0];   
  213.   var b = im._21 * vad[0] + im._22 * vbd[0];   
  214.   
  215.   var c = im._11 * vad[1] + im._12 * vbd[1];   
  216.   var d = im._21 * vad[1] + im._22 * vbd[1];   
  217.   
  218.   var wu = uv_0u * w;   
  219.   var hv = uv_0v * h;   
  220.   var du = wu * a + hv * b;   
  221.   var dv = wu * c + hv * d;   
  222.   
  223.   g.save();   
  224.   
  225.   g.beginpath();   
  226.   g.moveto(poss[0].x, poss[0].y);   
  227.   g.lineto(poss[1].x, poss[1].y);   
  228.   g.lineto(poss[2].x, poss[2].y);   
  229.   g.clip();   
  230.   g.transform(a, c, b, d, poss[0].x - du, poss[0].y - dv);   
  231.   
  232.   // bounds   
  233.   var bx = [wu, wu+va[0], wu+vb[0]];   
  234.   var by = [hv, hv+va[1], hv+vb[1]];   
  235.   
  236.   bx.sort(p3d.num_cmp);   
  237.   by.sort(p3d.num_cmp);   
  238.   
  239.   var bw = bx[2] - bx[0];   
  240.   var bh = by[2] - by[0];   
  241.   
  242.   if ((bx[0]+bw) <= (w-1)) bw++;   
  243.   if ((by[0]+bh) <= (h-1)) bh++;   
  244.   if (bx[0] >= 1) {bx[0]--; bw++;}   
  245.   if (by[0] >= 1) {by[0]--; bh++;}   
  246.   
  247.   g.drawimage(this.texture, bx[0], by[0], bw, bh, bx[0], by[0], bw, bh);   
  248. /*  
  249.   if (shade_clr) {  
  250.    g.fillstyle = shade_clr;  
  251.    g.fillrect(bx[0], by[0], bw, bh);  
  252.   }  
  253. */  
  254.   g.restore();   
  255.   
  256.  }   
  257.   
  258. }   
  259.   
  260. function vec3(_x, _y, _z)   
  261. {   
  262.  this.x = _x || 0;   
  263.  this.y = _y || 0;   
  264.  this.z = _z || 0;   
  265. }   
  266.   
  267. vec3.prototype = {   
  268.  zero: function() {   
  269.   this.x = this.y = this.z = 0;   
  270.  },   
  271.   
  272.  sub: function(v) {   
  273.   this.x -= v.x;   
  274.   this.y -= v.y;   
  275.   this.z -= v.z;   
  276.   
  277.   return this;   
  278.  },   
  279.   
  280.  add: function(v) {   
  281.   this.x += v.x;   
  282.   this.y += v.y;   
  283.   this.z += v.z;   
  284.   
  285.   return this;   
  286.  },   
  287.   
  288.  copyfrom: function(v) {   
  289.   this.x = v.x;   
  290.   this.y = v.y;   
  291.   this.z = v.z;   
  292.   
  293.   return this;   
  294.  },   
  295.   
  296.  norm:function() {   
  297.   return math.sqrt(this.x*this.x + this.y*this.y + this.z*this.z);   
  298.  },   
  299.   
  300.  normalize: function() {   
  301.   var nrm = math.sqrt(this.x*this.x + this.y*this.y + this.z*this.z);   
  302.   if (nrm != 0)   
  303.   {   
  304.    this.x /= nrm;   
  305.    this.y /= nrm;   
  306.    this.z /= nrm;   
  307.   }   
  308.   return this;   
  309.  },   
  310.   
  311.  smul: function(k) {   
  312.   this.x *= k;   
  313.   this.y *= k;   
  314.   this.z *= k;   
  315.   
  316.   return this;   
  317.  },   
  318.   
  319.  dpwith: function(v) {   
  320.   return this.x*v.x + this.y*v.y + this.z*v.z;   
  321.  },   
  322.   
  323.  cp: function(v, w) {   
  324.   this.x = (w.y * v.z) - (w.z * v.y);   
  325.   this.y = (w.z * v.x) - (w.x * v.z);   
  326.   this.z = (w.x * v.y) - (w.y * v.x);   
  327.   
  328.   return this;   
  329.  },   
  330.   
  331.  tostring: function() {   
  332.   return this.x + ", " + this.y + "," + this.z;   
  333.  }   
  334. }   
  335.   
  336. function m44(cpy)   
  337. {   
  338.  if (cpy)   
  339.   this.copyfrom(cpy);   
  340.  else {   
  341.   this.ident();   
  342.  }   
  343. }   
  344.   
  345. m44.prototype = {   
  346.  ident: function() {   
  347.      this._12 = this._13 = this._14 = 0;   
  348.   this._21 =       this._23 = this._24 = 0;   
  349.   this._31 = this._32 =       this._34 = 0;   
  350.   this._41 = this._42 = this._43 =       0;   
  351.   
  352.   this._11 = this._22 = this._33 = this._44 = 1;   
  353.   
  354.   return this;   
  355.  },   
  356.   
  357.  copyfrom: function(m) {   
  358.   this._11 = m._11;   
  359.   this._12 = m._12;   
  360.   this._13 = m._13;   
  361.   this._14 = m._14;   
  362.   
  363.   this._21 = m._21;   
  364.   this._22 = m._22;   
  365.   this._23 = m._23;   
  366.   this._24 = m._24;   
  367.   
  368.   this._31 = m._31;   
  369.   this._32 = m._32;   
  370.   this._33 = m._33;   
  371.   this._34 = m._34;   
  372.   
  373.   this._41 = m._41;   
  374.   this._42 = m._42;   
  375.   this._43 = m._43;   
  376.   this._44 = m._44;   
  377.   
  378.   return this;   
  379.  },   
  380.   
  381.  transvec3: function(out, x, y, z) {   
  382.   out[0] = x * this._11 + y * this._21 + z * this._31 + this._41;   
  383.   out[1] = x * this._12 + y * this._22 + z * this._32 + this._42;   
  384.   out[2] = x * this._13 + y * this._23 + z * this._33 + this._43;   
  385.   out[3] = x * this._14 + y * this._24 + z * this._34 + this._44;   
  386.  },   
  387.   
  388.  transvec3rot: function(out, x, y, z) {   
  389.   out[0] = x * this._11 + y * this._21 + z * this._31;   
  390.   out[1] = x * this._12 + y * this._22 + z * this._32;   
  391.   out[2] = x * this._13 + y * this._23 + z * this._33;   
  392.  },   
  393.   
  394.  perspectivelh: function(vw, vh, z_near, z_far) {   
  395.   this._11 = 2.0*z_near/vw;   
  396.   this._12 = 0;   
  397.   this._13 = 0;   
  398.   this._14 = 0;   
  399.   
  400.   this._21 = 0;   
  401.   this._22 = 2*z_near/vh;   
  402.   this._23 = 0;   
  403.   this._24 = 0;   
  404.   
  405.   this._31 = 0;   
  406.   this._32 = 0;   
  407.   this._33 = z_far/(z_far-z_near);   
  408.   this._34 = 1;   
  409.   
  410.   this._41 = 0;   
  411.   this._42 = 0;   
  412.   this._43 = z_near*z_far/(z_near-z_far);   
  413.   this._44 = 0;   
  414.   
  415.   return this;   
  416.  },   
  417.   
  418.  lookatlh: function(aup, afrom, aat) {   
  419.   var ax = new vec3();   
  420.   var ay = new vec3();   
  421.   
  422.   var az = new vec3(aat.x, aat.y, aat.z);   
  423.   az.sub(afrom).normalize();   
  424.   
  425.   ax.cp(aup, az).normalize();   
  426.   ay.cp(az, ax);   
  427.   
  428.   this._11 = ax.x;  this._12 = ay.x;  this._13 = az.x;  this._14 = 0;   
  429.   this._21 = ax.y;  this._22 = ay.y;  this._23 = az.y;  this._24 = 0;   
  430.   this._31 = ax.z;  this._32 = ay.z;  this._33 = az.z;  this._34 = 0;   
  431.   
  432.   this._41 = -afrom.dpwith(ax);   
  433.   this._42 = -afrom.dpwith(ay);   
  434.   this._43 = -afrom.dpwith(az);   
  435.   this._44 = 1;   
  436.   
  437.      return this;   
  438.  },   
  439.   
  440.  mul: function(a, b) {   
  441.   this._11 = a._11*b._11  +  a._12*b._21  +  a._13*b._31  +  a._14*b._41;   
  442.   this._12 = a._11*b._12  +  a._12*b._22  +  a._13*b._32  +  a._14*b._42;   
  443.   this._13 = a._11*b._13  +  a._12*b._23  +  a._13*b._33  +  a._14*b._43;   
  444.   this._14 = a._11*b._14  +  a._12*b._24  +  a._13*b._34  +  a._14*b._44;   
  445.   
  446.   this._21 = a._21*b._11  +  a._22*b._21  +  a._23*b._31  +  a._24*b._41;   
  447.   this._22 = a._21*b._12  +  a._22*b._22  +  a._23*b._32  +  a._24*b._42;   
  448.   this._23 = a._21*b._13  +  a._22*b._23  +  a._23*b._33  +  a._24*b._43;   
  449.   this._24 = a._21*b._14  +  a._22*b._24  +  a._23*b._34  +  a._24*b._44;   
  450.   
  451.   this._31 = a._31*b._11  +  a._32*b._21  +  a._33*b._31  +  a._34*b._41;   
  452.   this._32 = a._31*b._12  +  a._32*b._22  +  a._33*b._32  +  a._34*b._42;   
  453.   this._33 = a._31*b._13  +  a._32*b._23  +  a._33*b._33  +  a._34*b._43;   
  454.   this._34 = a._31*b._14  +  a._32*b._24  +  a._33*b._34  +  a._34*b._44;   
  455.   
  456.   this._41 = a._41*b._11  +  a._42*b._21  +  a._43*b._31  +  a._44*b._41;   
  457.   this._42 = a._41*b._12  +  a._42*b._22  +  a._43*b._32  +  a._44*b._42;   
  458.   this._43 = a._41*b._13  +  a._42*b._23  +  a._43*b._33  +  a._44*b._43;   
  459.   this._44 = a._41*b._14  +  a._42*b._24  +  a._43*b._34  +  a._44*b._44;   
  460.   
  461.   return this;   
  462.  },   
  463.   
  464.  translate: function(x, y, z) {   
  465.   this._11 = 1;  this._12 = 0;  this._13 = 0;  this._14 = 0;   
  466.   this._21 = 0;  this._22 = 1;  this._23 = 0;  this._24 = 0;   
  467.   this._31 = 0;  this._32 = 0;  this._33 = 1;  this._34 = 0;   
  468.   
  469.   this._41 = x;  this._42 = y;  this._43 = z;  this._44 = 1;   
  470.   return this;   
  471.  },   
  472.   
  473.  transpose33: function() {   
  474.   var t;   
  475.   
  476.   t = this._12;   
  477.   this._12 = this._21;   
  478.   this._21 = t;   
  479.   
  480.   t = this._13;   
  481.   this._13 = this._31;   
  482.   this._31 = t;   
  483.   
  484.   t = this._23;   
  485.   this._23 = this._32;   
  486.   this._32 = t;   
  487.   
  488.   return this;   
  489.  },   
  490.   
  491.  // opengl style rotation   
  492.  glrotate: function(angle, x, y, z) {   
  493.   var s = math.sin( angle );   
  494.   var c = math.cos( angle );   
  495.   
  496.   var xx = x * x;   
  497.   var yy = y * y;   
  498.   var zz = z * z;   
  499.   var xy = x * y;   
  500.   var yz = y * z;   
  501.   var zx = z * x;   
  502.   var xs = x * s;   
  503.   var ys = y * s;   
  504.   var zs = z * s;   
  505.   var one_c = 1.0 - c;   
  506. /*  
  507.   this._11 = (one_c * xx) + c;  
  508.   this._21 = (one_c * xy) - zs;  
  509.   this._31 = (one_c * zx) + ys;  
  510.   this._41 = 0;  
  511.  
  512.   this._12 = (one_c * xy) + zs;  
  513.   this._22 = (one_c * yy) + c;  
  514.   this._32 = (one_c * yz) - xs;  
  515.   this._42 = 0;  
  516.  
  517.   this._13 = (one_c * zx) - ys;  
  518.   this._23 = (one_c * yz) + xs;  
  519.   this._33 = (one_c * zz) + c;  
  520.   this._43 = 0;  
  521.  
  522.   this._14 = 0;  
  523.   this._24 = 0;  
  524.   this._34 = 0;  
  525.   this._44 = 1;  
  526. */  
  527.   
  528.   this._11 = (one_c * xx) + c;   
  529.   this._12 = (one_c * xy) - zs;   
  530.   this._13 = (one_c * zx) + ys;   
  531.   this._14 = 0;   
  532.   
  533.   this._21 = (one_c * xy) + zs;   
  534.   this._22 = (one_c * yy) + c;   
  535.   this._23 = (one_c * yz) - xs;   
  536.   this._24 = 0;   
  537.   
  538.   this._31 = (one_c * zx) - ys;   
  539.   this._32 = (one_c * yz) + xs;   
  540.   this._33 = (one_c * zz) + c;   
  541.   this._34 = 0;   
  542.   
  543.   this._41 = 0;   
  544.   this._42 = 0;   
  545.   this._43 = 0;   
  546.   this._44 = 1;   
  547.   
  548.   return this;   
  549.  }   
  550.   
  551. }   
  552.   
  553. // matrix 2x2   
  554. function m22()   
  555. {   
  556.  this._11 = 1;   
  557.  this._12 = 0;   
  558.  this._21 = 0;   
  559.  this._22 = 1;   
  560. }   
  561.   
  562. m22.prototype.getinvert = function()   
  563. {   
  564.  var out = new m22();   
  565.  var det = this._11 * this._22 - this._12 * this._21;   
  566.  if (det > -0.0001 && det < 0.0001)   
  567.   return null;   
  568.   
  569.  out._11 = this._22 / det;   
  570.  out._22 = this._11 / det;   
  571.   
  572.  out._12 = -this._12 / det;   
  573.  out._21 = -this._21 / det;   
  574.   
  575.  return out;   
  576. }   

3d衣服动画js代码

javascript code复制内容到剪贴板
  1. function clothapp()   
  2. {   
  3.  this.canvas = document.getelementbyid("cv");   
  4.   
  5.  p3d.g = this.canvas.getcontext("2d");   
  6.   
  7.  var tex = new image();   
  8.  this.texture1 = tex;   
  9.  tex.onload = function(){ _this.start(); };   
  10.  tex.src = "20090226032826.gif";   
  11.   
  12.  tex = new image();   
  13.  this.texture2 = tex;   
  14.  tex.onload = function(){ _this.start(); };   
  15.  tex.src = "20090226032825.png";   
  16.   
  17.  this.mloadcount = 2;   
  18.  this.mtickcount = 0;   
  19.   
  20.  this.g = 0.53;   
  21.  this.g1 = 0.45;   
  22.  this.mprojmat  = null;   
  23.  this.mviewmat  = null;   
  24.  this.mviewfrom = new vec3();   
  25.  this.mviewfrom.y = -150;   
  26.  this.mviewfrom.z = 1000;   
  27.  this.mviewfroma = (new vec3()).copyfrom(this.mviewfrom);   
  28.   
  29.  this.mviewangle = 0;   
  30.   
  31.  this.mnlen = 0;   
  32.  this.mnodes = [];   
  33.  this.mrendertris = null;   
  34.   
  35.  this.mltnode = null;   
  36.  this.mrtnode = null;   
  37.   
  38.  this.mltnodev = new vec3();   
  39.  this.mrtnodev = new vec3();   
  40.   
  41.  this.mwforce = new vec3();   
  42.  this.frate = 15;   
  43.   
  44.  var _this = this;   
  45. }   
  46.   
  47. clothapp.zsortcmp = function(t1, t2) {   
  48.  return t2.sortkey - t1.sortkey;   
  49. }   
  50.   
  51. clothapp.prototype = {   
  52.  start: function() {   
  53.   if (--this.mloadcount != 0) return;   
  54.   
  55.   this.vup = new vec3(0,  1, 0);   
  56.   this.vat = new vec3(0, 80, 0);   
  57.   
  58.   this.mviewport = {};   
  59.   this.mviewport.w = 480;   
  60.   this.mviewport.h = 300;   
  61.   this.mviewport.ow = 240;   
  62.   this.mviewport.oh = 150;   
  63.   this.setuptransforms();   
  64.   
  65.   this.generatecloth(180);   
  66.   this.generaterendertriangles();   
  67.   
  68.   var _this = this;   
  69.   this.canvas.addeventlistener("mousemove"function(e){_this.onmousemove(e);}, false);   
  70.   this.canvas.addeventlistener("mousedown"function(e){_this.onclick(e);}, false);   
  71.   
  72.   window.settimeout(function(){_this.oninterval();}, this.frate);   
  73.  },   
  74.   
  75.  oninterval: function() {   
  76.   this.mtickcount++;   
  77.   
  78.   // this.mltnodev.z = math.cos(this.mtickcount*0.1) * 2;   
  79.   
  80.   this.tick();   
  81.   this.updateposition();   
  82.   this.draw();   
  83.   
  84.   var _this = this;   
  85.   window.settimeout(function(){_this.oninterval();}, this.frate);   
  86.  },   
  87.   
  88.  onmousemove: function(e) {   
  89.   if (e.clientx || e.clientx == 0)   
  90.    this.mviewangle = (e.clientx - 240) * 0.004;   
  91.   
  92.   if (e.clienty || e.clienty == 0)   
  93.    this.mviewfroma.y = 90 - (e.clienty - 0) * 0.8;   
  94.  },   
  95.   
  96.  onclick: function(e) {   
  97.   if (e.clientx || e.clientx == 0)   
  98.   {   
  99.    this.mwforce.z = -4;   
  100.    this.mwforce.x = (e.clientx - 240) * -0.03;   
  101.   }   
  102.  },   
  103.   
  104.  tick: function() {   
  105.   this.updateviewtrans(this.mviewangle);   
  106.   
  107.   var nlen = this.mnodes.length;   
  108.   var i, nd;   
  109.   for(i = 0;i < nlen;i++)   
  110.   {   
  111.    nd = this.mnodes[i];   
  112.    nd.f.x = 0;   
  113.    nd.f.z = 0;   
  114.    if (nd.flags & 4)   
  115.     nd.f.y = -this.g1;   
  116.    else  
  117.     nd.f.y = -this.g;   
  118.   
  119.    nd.f.add(this.mwforce);   
  120.   }   
  121.   
  122.   this.mwforce.zero();   
  123.   this.applytension();   
  124.   
  125.   for(i = 0;i < nlen;i++)   
  126.   {   
  127.    nd = this.mnodes[i];   
  128.   
  129.    if ((nd.flags&1) != 0) {   
  130.     nd.f.sub(nd.f);   
  131.    }   
  132.   
  133.    nd.velo.add(nd.f);   
  134.   }   
  135.   
  136.   this.mltnode.velo.copyfrom(this.mltnodev);   
  137.   this.mrtnode.velo.copyfrom(this.mrtnodev);   
  138.  },   
  139.   
  140.  updateposition: function() {   
  141.   var nlen = this.mnodes.length;   
  142.   var i, nd;   
  143.   for(i = 0;i < nlen;i++)   
  144.   {   
  145.    nd = this.mnodes[i];   
  146.   
  147.    if ((nd.flags&1) != 0) {   
  148.     nd.cv.x = 0;   
  149.     nd.cv.y = 0;   
  150.     nd.cv.z = 0;   
  151.    }   
  152.   
  153.    nd.pos.add(nd.velo);   
  154.    nd.velo.sub(nd.cv);   
  155.    nd.cv.x = 0;   
  156.    nd.cv.y = 0;   
  157.    nd.cv.z = 0;   
  158.   
  159.    nd.velo.smul(0.95);   
  160.   }   
  161.  },   
  162.   
  163.  draw: function() {   
  164.   p3d.clear("#000"this.mviewport.w, this.mviewport.h);   
  165.   this.transformpolygons();   
  166.   
  167.   this.mrendertris.sort(clothapp.zsortcmp);   
  168.   var len = this.mrendertris.length;   
  169.   var t, sh;   
  170.   for (var i = 0;i < len;i++) {   
  171.    t = this.mrendertris[i];   
  172.   
  173.    if (p3d.texture != t.texture)   
  174.     p3d.texture = t.texture;   
  175.   
  176.    sh = undefined;   
  177.    if (t.lighting && t.shade > 0.01)   
  178.     sh = "rgba(0,0,0,"+t.shade+")";   
  179.    p3d.drawtriangle(t.tposs, t.uvs, sh);   
  180.   }   
  181.  },   
  182.   
  183.  applytension: function() {   
  184.   var i, k, nd;   
  185.   var v = new vec3();   
  186.   var nlen = this.mnodes.length;   
  187.   var naturallen = this.mnlen;   
  188.   
  189.   for (k = 0;k < nlen;k++)   
  190.   {   
  191.    nd = this.mnodes[k];   
  192.    var f = nd.f;   
  193.   
  194.    for (i = 0;i < 4;i++)   
  195.    {   
  196.     var nbr = nd.links[i];   
  197.     if (!nbr) continue;   
  198.   
  199.     var len = v.copyfrom(nbr.pos).sub(nd.pos).norm();   
  200.     var dlen = len - naturallen;   
  201.     if (dlen > 0) {   
  202.      v.smul(dlen * 0.5 / len);   
  203.   
  204.      f.x += v.x;   
  205.      f.y += v.y;   
  206.      f.z += v.z;   
  207.      nd.cv.add(v.smul(0.8));   
  208.     }   
  209.    }   
  210.   }    
  211.  },   
  212.   
  213.  setuptransforms: function() {   
  214.   this.mprojmat = new m44();   
  215.   this.mprojmat.perspectivelh(24, 15, 10, 9000);   
  216.   
  217.   this.mviewmat = new m44();   
  218.   this.updateviewtrans(0);   
  219.  },   
  220.   
  221.  updateviewtrans: function(ry) {   
  222.   this.mviewfroma.z = math.cos(ry) * 380;   
  223.   this.mviewfroma.x = math.sin(ry) * 380;   
  224.   
  225.   this.mviewfrom.smul(0.7);   
  226.   this.mviewfrom.x += this.mviewfroma.x * 0.3;   
  227.   this.mviewfrom.y += this.mviewfroma.y * 0.3;   
  228.   this.mviewfrom.z += this.mviewfroma.z * 0.3;   
  229.   
  230.   this.mviewmat.lookatlh(this.vup, this.mviewfrom, this.vat);   
  231.  },   
  232.   
  233.  generatecloth: function(base_y) {   
  234.   var cols = 9;   
  235.   var rows = 8;   
  236.   
  237.   var step   = 22;   
  238.   this.mnlen = step*0.9;   
  239.   var w = (cols-1) * step;   
  240.   
  241.   var i, k;   
  242.   for (k = 0;k < rows;k++)   
  243.   {   
  244.    for (i = 0;i < cols;i++)   
  245.    {   
  246.     var nd = new clothnode();   
  247.     nd.pos.x = -(w/2) + i*step;   
  248.     nd.pos.y = base_y -k*step/2;   
  249.     nd.pos.z = k*16;   
  250.   
  251.     nd.uv.u = i / (cols-1);   
  252.     nd.uv.v = k / (rows-1);   
  253.   
  254.     if (i > 0) {   
  255.      var prv_nd = this.mnodes[this.mnodes.length-1];   
  256.      prv_nd.links[1] = nd;   
  257.      nd.links[0] = prv_nd;   
  258.     }   
  259.   
  260.     if (k > 0) {   
  261.      var up_nd = this.mnodes[this.mnodes.length-cols];   
  262.      up_nd.links[4] = nd;   
  263.      nd.links[3] = up_nd;   
  264.     }   
  265.   
  266.     if (i != 0 && i != 4 && i != (cols-1))   
  267.      nd.flags |= 4;   
  268.   
  269.     this.mnodes.push(nd);   
  270.    }   
  271.   }   
  272.   
  273.   // fix left-top and right-top   
  274.   this.mnodes[0     ].flags |= 1;   
  275.   this.mnodes[4     ].flags |= 1;   
  276.   this.mnodes[cols-1].flags |= 1;   
  277.   
  278.   this.mltnode = this.mnodes[0     ];   
  279.   this.mrtnode = this.mnodes[cols-1];   
  280.  },   
  281.   
  282.  generaterendertriangles: function()   
  283.  {   
  284.   if (!this.mrendertris) this.mrendertris = [];   
  285.   
  286.   var i;   
  287.   var nd;   
  288.   var nlen = this.mnodes.length;   
  289.   
  290.   for(i = 0;i < nlen;i++)   
  291.   {   
  292.    nd = this.mnodes[i];   
  293.    if (nd.links[1] && nd.links[1].links[4]) {   
  294.     var t = new rendertriangle();   
  295.     t.texture = this.texture1;   
  296.   
  297.     t.poss[0] = nd.pos;   
  298.     t.poss[1] = nd.links[1].pos;   
  299.     t.poss[2] = nd.links[1].links[4].pos;   
  300.   
  301.     t.uvs[0]  = nd.uv;   
  302.     t.uvs[1]  = nd.links[1].uv;   
  303.     t.uvs[2]  = nd.links[1].links[4].uv;   
  304.   
  305.     this.mrendertris.push(t);   
  306.   
  307.     t = new rendertriangle();   
  308.     t.texture = this.texture1;   
  309.   
  310.     t.poss[0] = nd.pos;   
  311.     t.poss[1] = nd.links[1].links[4].pos;   
  312.     t.poss[2] = nd.links[4].pos;   
  313.   
  314.     t.uvs[0]  = nd.uv;   
  315.     t.uvs[1]  = nd.links[1].links[4].uv;   
  316.     t.uvs[2]  = nd.links[4].uv;   
  317.   
  318.     this.mrendertris.push(t);   
  319.    }   
  320.   }   
  321.   
  322.   this.addbgtriangles(this.mnodes[0].pos.y);   
  323.  },   
  324.   
  325.  addbgtriangles: function(by) {   
  326.   var cols = 4;   
  327.   var t, x, y, sz = 110;   
  328.   var ox = -(cols*sz)/2;   
  329.   var oz = -(cols*sz)/2;   
  330.   
  331.   for (y = 0;y < cols;y++) {   
  332.    for (x = 0;x < cols;x++) {   
  333.     var bv = ((x+y)&1) * 0.5;   
  334.     t = new rendertriangle();   
  335.     t.texture = this.texture2;   
  336.   
  337.     t.poss[0] = new vec3(ox + x*sz     , by, oz + y*sz     );   
  338.     t.poss[1] = new vec3(ox + x*sz + sz, by, oz + y*sz     );   
  339.     t.poss[2] = new vec3(ox + x*sz     , by, oz + y*sz + sz);   
  340.   
  341.     t.uvs[0]  = {u:0  , v:bv    };   
  342.     t.uvs[1]  = {u:0.5, v:bv    };   
  343.     t.uvs[2]  = {u:0  , v:bv+0.5};   
  344.   
  345.     if ((x==1 || x==2) && (y==1 || y==2))   
  346.      this.modifyroofuv(t, x == 2, bv);   
  347.   
  348.     t.lighting = false;   
  349.     t.zbias = 0.5;   
  350.     this.mrendertris.push(t);   
  351.   
  352.     t = new rendertriangle();   
  353.     t.texture = this.texture2;   
  354.   
  355.     t.poss[0] = new vec3(ox + x*sz     , by, oz + y*sz + sz);   
  356.     t.poss[1] = new vec3(ox + x*sz + sz, by, oz + y*sz    );   
  357.     t.poss[2] = new vec3(ox + x*sz + sz, by, oz + y*sz + sz);   
  358.   
  359.     t.uvs[0]  = {u:0  , v:bv+0.5};   
  360.     t.uvs[1]  = {u:0.5, v:bv    };   
  361.     t.uvs[2]  = {u:0.5, v:bv+0.5};   
  362.   
  363.     if ((x==1 || x==2) && (y==1 || y==2))   
  364.      this.modifyroofuv(t, x == 2, bv);   
  365.   
  366.     t.lighting = false;   
  367.     t.zbias = 0.5;   
  368.     this.mrendertris.push(t);   
  369.   
  370.    }   
  371.   }   
  372.  },   
  373.   
  374.  modifyroofuv: function(t, rv, bv) {   
  375.   if (rv) {   
  376.    t.uvs[0].u = 0.5 - t.uvs[0].u;   
  377.    t.uvs[1].u = 0.5 - t.uvs[1].u;   
  378.    t.uvs[2].u = 0.5 - t.uvs[2].u;   
  379.   }   
  380.   
  381.   t.uvs[0].u += 0.5;   
  382.   t.uvs[1].u += 0.5;   
  383.   t.uvs[2].u += 0.5;   
  384.   
  385.   if (rv) {   
  386.    t.uvs[0].v = 0.5 - t.uvs[0].v + bv + bv;   
  387.    t.uvs[1].v = 0.5 - t.uvs[1].v + bv + bv;   
  388.    t.uvs[2].v = 0.5 - t.uvs[2].v + bv + bv;   
  389.   }   
  390.   
  391.  },   
  392.   
  393.  transformpolygons: function() {   
  394.   var trans = new m44();   
  395.   trans.mul(this.mviewmat, this.mprojmat);   
  396.   
  397.   var hw = this.mviewport.ow;   
  398.   var hh = this.mviewport.oh;   
  399.   
  400.   var len = this.mrendertris.length;   
  401.   var t;   
  402.   var spos = [0, 0, 0, 0];   
  403.   for (var i = 0;i < len;i++) {   
  404.    t = this.mrendertris[i];   
  405.    for (var k = 0;k < 3;k++) {   
  406.     trans.transvec3(spos, t.poss[k].x, t.poss[k].y, t.poss[k].z);   
  407.   
  408.     var w = spos[3];   
  409.     spos[0] /= w;   
  410.     spos[1] /= w;   
  411.     spos[2] /= w;   
  412.   
  413.     spos[0] *= this.mviewport.w;   
  414.     spos[1] *= -this.mviewport.h;   
  415.     spos[0] += hw;   
  416.     spos[1] += hh;   
  417.   
  418.     t.tposs[k].x = spos[0];   
  419.     t.tposs[k].y = spos[1];   
  420.     t.tposs[k].z = spos[2];   
  421.    }   
  422.   
  423.    var v1 = (new vec3()).copyfrom(t.poss[1]).sub(t.poss[0]).normalize();   
  424.    var v2 = (new vec3()).copyfrom(t.poss[2]).sub(t.poss[1]).normalize();   
  425.    var n = (new vec3()).cp(v1, v2);   
  426.   
  427.    trans.transvec3rot(spos, n.x, n.y, n.z);   
  428.   
  429.    if (t.lighting) {   
  430.     if (spos[2] > 0)   
  431.      t.shade = 0.8   
  432.     else {   
  433.      t.shade = 0.1 - n.y * 0.6;   
  434.      if (t.shade < 0) t.shade = 0;   
  435.     }   
  436.    }   
  437.   
  438.    t.sortkey = math.floor( (t.tposs[0].z + t.tposs[1].z + t.tposs[2].z + t.zbias) *1000 );   
  439.   }   
  440.  }   
  441. }   
  442.   
  443. function clothnode()   
  444. {   
  445.  this.flags = 0;   
  446.  this.pos  = new vec3();   
  447.  this.velo = new vec3();   
  448.  this.cv   = new vec3();   
  449.  this.f    = new vec3();   
  450.  this.links = [nullnullnullnull];   
  451.  this.uv = {u:0, v:0};   
  452. }   
  453.   
  454. function rendertriangle()   
  455. {   
  456.  this.texture = null;   
  457.  this.poss  = new array(3);   
  458.  this.tposs = [new vec3(), new vec3(), new vec3()];   
  459.  this.uvs = [{u:0, v:0}, {u:0, v:0}, {u:0, v:0}];   
  460.  this.shade = 0;   
  461.  this.lighting = true;   
  462.  this.zbias = 0;   
  463.   
  464.  this.sortkey = 0;   
  465. }   

以上就是html5 3d衣服摇摆动画特效的源码介绍,需要更为深入学习的下载源代码来研究。