HTML5 3D衣服摇摆动画特效

江山十日雪,雪深江雾浓。开时刻的牵绊,邀阳光作伴,约清风同行,收拾起行囊,咱们去亲近草原吧,去亲近辽阔无边的草原。

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

在线演示 源码下载

HTML代码

XML/HTML Code复制内容到剪贴板
  1. <divstyle="width:500px;margin:10pxauto">
  2. <canvasid="cv"width="480"height="300"></canvas>
  3. <p>"3Don2DCanvas"demo</p>
  4. <p>movecursortopan/clicktoswing</p>
  5. </div>

P3D库JS代码,主要用来处理3D效果的

JavaScript Code复制内容到剪贴板
  1. window.P3D={
  2. texture:null,
  3. g:null
  4. };
  5. P3D.clear=function(f,w,h){
  6. varg=this.g;
  7. g.beginPath();
  8. g.fillStyle=f;
  9. g.fillRect(0,0,w,h);
  10. }
  11. P3D.num_cmp=function(a,b){returna-b;}
  12. P3D.drawTriangle=function(poss,uvs,shade_clr){
  13. varw=this.texture.width;
  14. varh=this.texture.height;
  15. varg=this.g;
  16. varvAd=[poss[1].x-poss[0].x,poss[1].y-poss[0].y];
  17. varvBd=[poss[2].x-poss[0].x,poss[2].y-poss[0].y];
  18. varvA=[uvs[1].u-uvs[0].u,uvs[1].v-uvs[0].v];
  19. varvB=[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. varm=newM22();
  25. m._11=vA[0];
  26. m._12=vA[1];
  27. m._21=vB[0];
  28. m._22=vB[1];
  29. varim=m.getInvert();
  30. if(!im)returnfalse;
  31. vara=im._11*vAd[0]+im._12*vBd[0];
  32. varb=im._21*vAd[0]+im._22*vBd[0];
  33. varc=im._11*vAd[1]+im._12*vBd[1];
  34. vard=im._21*vAd[1]+im._22*vBd[1];
  35. varwu=uvs[0].u*w;
  36. varhv=uvs[0].v*h;
  37. vardu=wu*a+hv*b;
  38. vardv=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. varbx=[wu,wu+vA[0],wu+vB[0]];
  48. varby=[hv,hv+vA[1],hv+vB[1]];
  49. bx.sort(P3D.num_cmp);
  50. by.sort(P3D.num_cmp);
  51. varbw=bx[2]-bx[0];
  52. varbh=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. returntrue;
  64. }
  65. P3D.drawTestByIndexBuffer=function(pos_buf,ix_buf,culling){
  66. varg=this.g;
  67. if((ix_buf.length%3)!=0)
  68. throw"invalidindexbufferlength!";
  69. varlen=ix_buf.length/3;
  70. vari,ibase,vbase;
  71. varposs=[{},{},{}];
  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. //zcomponentofcrossproduct<0?
  85. varAx=poss[1].x-poss[0].x;
  86. varAy=poss[1].y-poss[0].y;
  87. varCx=poss[2].x-poss[1].x;
  88. varCy=poss[2].y-poss[1].y;
  89. varcull=((((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. varw,h;
  101. varcolor_polygon=!this.texture;
  102. if(this.texture){
  103. w=this.texture.width;
  104. h=this.texture.height;
  105. }
  106. varg=this.g;
  107. varm=newM22();
  108. if(!culling)culling=0;
  109. if((ix_buf.length%3)!=0)
  110. throw"invalidindexbufferlength!";
  111. vari,ibase,vbase,tbase,poss=[{},{},{}];
  112. varlen=ix_buf.length/3;
  113. varuv_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. varvAd=[poss[1].x-poss[0].x,poss[1].y-poss[0].y];
  132. varvBd=[poss[2].x-poss[0].x,poss[2].y-poss[0].y];
  133. varvCd=[poss[2].x-poss[1].x,poss[2].y-poss[1].y];
  134. //zcomponentofcrossproduct<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. varvA=[uv_1u-uv_0u,uv_1v-uv_0v];
  147. varvB=[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. varim=m.getInvert();
  157. if(!im){continue;}
  158. vara=im._11*vAd[0]+im._12*vBd[0];
  159. varb=im._21*vAd[0]+im._22*vBd[0];
  160. varc=im._11*vAd[1]+im._12*vBd[1];
  161. vard=im._21*vAd[1]+im._22*vBd[1];
  162. varwu=uv_0u*w;
  163. varhv=uv_0v*h;
  164. vardu=wu*a+hv*b;
  165. vardv=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. varbx=[wu,wu+vA[0],wu+vB[0]];
  175. varby=[hv,hv+vA[1],hv+vB[1]];
  176. bx.sort(P3D.num_cmp);
  177. by.sort(P3D.num_cmp);
  178. varbw=bx[2]-bx[0];
  179. varbh=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. functionVec3(_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. returnthis;
  209. },
  210. add:function(v){
  211. this.x+=v.x;
  212. this.y+=v.y;
  213. this.z+=v.z;
  214. returnthis;
  215. },
  216. copyFrom:function(v){
  217. this.x=v.x;
  218. this.y=v.y;
  219. this.z=v.z;
  220. returnthis;
  221. },
  222. norm:function(){
  223. returnMath.sqrt(this.x*this.x+this.y*this.y+this.z*this.z);
  224. },
  225. normalize:function(){
  226. varnrm=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. returnthis;
  234. },
  235. smul:function(k){
  236. this.x*=k;
  237. this.y*=k;
  238. this.z*=k;
  239. returnthis;
  240. },
  241. dpWith:function(v){
  242. returnthis.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. returnthis;
  249. },
  250. toString:function(){
  251. returnthis.x+","+this.y+","+this.z;
  252. }
  253. }
  254. functionM44(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. returnthis;
  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. returnthis;
  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. returnthis;
  319. },
  320. lookAtLH:function(aUp,aFrom,aAt){
  321. varaX=newVec3();
  322. varaY=newVec3();
  323. varaZ=newVec3(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. returnthis;
  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. returnthis;
  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. returnthis;
  361. },
  362. transpose33:function(){
  363. vart;
  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. returnthis;
  374. },
  375. //OpenGLstylerotation
  376. glRotate:function(angle,x,y,z){
  377. vars=Math.sin(angle);
  378. varc=Math.cos(angle);
  379. varxx=x*x;
  380. varyy=y*y;
  381. varzz=z*z;
  382. varxy=x*y;
  383. varyz=y*z;
  384. varzx=z*x;
  385. varxs=x*s;
  386. varys=y*s;
  387. varzs=z*s;
  388. varone_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. returnthis;
  424. }
  425. }
  426. //matrix2x2
  427. functionM22()
  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. varout=newM22();
  437. vardet=this._11*this._22-this._12*this._21;
  438. if(det>-0.0001&&det<0.0001)
  439. returnnull;
  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. returnout;
  445. }

3D衣服动画JS代码

JavaScript Code复制内容到剪贴板
  1. functionClothApp()
  2. {
  3. this.canvas=document.getElementById("cv");
  4. P3D.g=this.canvas.getContext("2d");
  5. vartex=newImage();
  6. this.texture1=tex;
  7. tex.onload=function(){_this.start();};
  8. tex.src="20090226032826.gif";
  9. tex=newImage();
  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=newVec3();
  20. this.mViewFrom.y=-150;
  21. this.mViewFrom.z=1000;
  22. this.mViewFromA=(newVec3()).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=newVec3();
  30. this.mRTNodeV=newVec3();
  31. this.mWForce=newVec3();
  32. this.frate=15;
  33. var_this=this;
  34. }
  35. ClothApp.zsortCmp=function(t1,t2){
  36. returnt2.sortKey-t1.sortKey;
  37. }
  38. ClothApp.prototype={
  39. start:function(){
  40. if(--this.mLoadCount!=0)return;
  41. this.vUP=newVec3(0,1,0);
  42. this.vAT=newVec3(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. varnlen=this.mNodes.length;
  81. vari,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. varnlen=this.mNodes.length;
  108. vari,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. varlen=this.mRenderTris.length;
  130. vart,sh;
  131. for(vari=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. vari,k,nd;
  143. varv=newVec3();
  144. varnlen=this.mNodes.length;
  145. varnaturalLen=this.mNLen;
  146. for(k=0;k<nlen;k++)
  147. {
  148. nd=this.mNodes[k];
  149. varF=nd.F;
  150. for(i=0;i<4;i++)
  151. {
  152. varnbr=nd.links[i];
  153. if(!nbr)continue;
  154. varlen=v.copyFrom(nbr.pos).sub(nd.pos).norm();
  155. vardlen=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=newM44();
  168. this.mProjMat.perspectiveLH(24,15,10,9000);
  169. this.mViewMat=newM44();
  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. varcols=9;
  183. varrows=8;
  184. varstep=22;
  185. this.mNLen=step*0.9;
  186. varw=(cols-1)*step;
  187. vari,k;
  188. for(k=0;k<rows;k++)
  189. {
  190. for(i=0;i<cols;i++)
  191. {
  192. varnd=newClothNode();
  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. varprv_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. varup_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. //fixleft-topandright-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. vari;
  224. varnd;
  225. varnlen=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. vart=newRenderTriangle();
  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=newRenderTriangle();
  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. varcols=4;
  254. vart,x,y,sz=110;
  255. varox=-(cols*sz)/2;
  256. varoz=-(cols*sz)/2;
  257. for(y=0;y<cols;y++){
  258. for(x=0;x<cols;x++){
  259. varbv=((x+y)&1)*0.5;
  260. t=newRenderTriangle();
  261. t.texture=this.texture2;
  262. t.poss[0]=newVec3(ox+x*sz,by,oz+y*sz);
  263. t.poss[1]=newVec3(ox+x*sz+sz,by,oz+y*sz);
  264. t.poss[2]=newVec3(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=newRenderTriangle();
  274. t.texture=this.texture2;
  275. t.poss[0]=newVec3(ox+x*sz,by,oz+y*sz+sz);
  276. t.poss[1]=newVec3(ox+x*sz+sz,by,oz+y*sz);
  277. t.poss[2]=newVec3(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. vartrans=newM44();
  306. trans.mul(this.mViewMat,this.mProjMat);
  307. varhw=this.mViewport.ow;
  308. varhh=this.mViewport.oh;
  309. varlen=this.mRenderTris.length;
  310. vart;
  311. varspos=[0,0,0,0];
  312. for(vari=0;i<len;i++){
  313. t=this.mRenderTris[i];
  314. for(vark=0;k<3;k++){
  315. trans.transVec3(spos,t.poss[k].x,t.poss[k].y,t.poss[k].z);
  316. varW=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. varv1=(newVec3()).copyFrom(t.poss[1]).sub(t.poss[0]).normalize();
  329. varv2=(newVec3()).copyFrom(t.poss[2]).sub(t.poss[1]).normalize();
  330. varN=(newVec3()).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. functionClothNode()
  345. {
  346. this.flags=0;
  347. this.pos=newVec3();
  348. this.velo=newVec3();
  349. this.cv=newVec3();
  350. this.F=newVec3();
  351. this.links=[null,null,null,null];
  352. this.uv={u:0,v:0};
  353. }
  354. functionRenderTriangle()
  355. {
  356. this.texture=null;
  357. this.poss=newArray(3);
  358. this.tposs=[newVec3(),newVec3(),newVec3()];
  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衣服摇摆动画特效的源码介绍,需要更为深入学习的下载源代码来研究。

标签: