这又是一款基于HTML5 Canvas的3D动画杰作,它是一个可以随风飘动的3D衣服摇摆动画特效,非常逼真。当我们将鼠标滑过衣服时,衣服将会出现摇摆的动画,点击鼠标时,衣服将会更加剧烈地摆动。
在线演示 源码下载
HTML代码
XML/HTML Code复制内容到剪贴板 <divstyle="width:500px;margin:10pxauto"> <canvasid="cv"width="480"height="300"></canvas> <p>"3Don2DCanvas"demo</p> <p>movecursortopan/clicktoswing</p> </div>
P3D库JS代码,主要用来处理3D效果的
JavaScript Code复制内容到剪贴板 window.P3D={ texture:null, g:null }; P3D.clear=function(f,w,h){ varg=this.g; g.beginPath(); g.fillStyle=f; g.fillRect(0,0,w,h); } P3D.num_cmp=function(a,b){returna-b;} P3D.drawTriangle=function(poss,uvs,shade_clr){ varw=this.texture.width; varh=this.texture.height; varg=this.g; varvAd=[poss[1].x-poss[0].x,poss[1].y-poss[0].y]; varvBd=[poss[2].x-poss[0].x,poss[2].y-poss[0].y]; varvA=[uvs[1].u-uvs[0].u,uvs[1].v-uvs[0].v]; varvB=[uvs[2].u-uvs[0].u,uvs[2].v-uvs[0].v]; vA[0]*=w; vA[1]*=h; vB[0]*=w; vB[1]*=h; varm=newM22(); m._11=vA[0]; m._12=vA[1]; m._21=vB[0]; m._22=vB[1]; varim=m.getInvert(); if(!im)returnfalse; vara=im._11*vAd[0]+im._12*vBd[0]; varb=im._21*vAd[0]+im._22*vBd[0]; varc=im._11*vAd[1]+im._12*vBd[1]; vard=im._21*vAd[1]+im._22*vBd[1]; varwu=uvs[0].u*w; varhv=uvs[0].v*h; vardu=wu*a+hv*b; vardv=wu*c+hv*d; g.save(); g.beginPath(); g.moveTo(poss[0].x,poss[0].y); g.lineTo(poss[1].x,poss[1].y); g.lineTo(poss[2].x,poss[2].y); g.clip(); g.transform(a,c,b,d,poss[0].x-du,poss[0].y-dv); //bounds varbx=[wu,wu+vA[0],wu+vB[0]]; varby=[hv,hv+vA[1],hv+vB[1]]; bx.sort(P3D.num_cmp); by.sort(P3D.num_cmp); varbw=bx[2]-bx[0]; varbh=by[2]-by[0]; if((bx[0]+bw)<=(w-1))bw++; if((by[0]+bh)<=(h-1))bh++; if(bx[0]>=1){bx[0]--;bw++;} if(by[0]>=1){by[0]--;bh++;} g.drawImage(this.texture,bx[0],by[0],bw,bh,bx[0],by[0],bw,bh); if(shade_clr){ g.fillStyle=shade_clr; g.fillRect(bx[0],by[0],bw,bh); } g.restore(); returntrue; } P3D.drawTestByIndexBuffer=function(pos_buf,ix_buf,culling){ varg=this.g; if((ix_buf.length%3)!=0) throw"invalidindexbufferlength!"; varlen=ix_buf.length/3; vari,ibase,vbase; varposs=[{},{},{}]; g.strokeWidth=1; for(i=0,ibase=0;i<len;++i) { vbase=ix_buf[ibase++]<<2; poss[0].x=pos_buf[vbase++]; poss[0].y=pos_buf[vbase]; vbase=ix_buf[ibase++]<<2; poss[1].x=pos_buf[vbase++]; poss[1].y=pos_buf[vbase]; vbase=ix_buf[ibase++]<<2; poss[2].x=pos_buf[vbase++]; poss[2].y=pos_buf[vbase]; //zcomponentofcrossproduct<0? varAx=poss[1].x-poss[0].x; varAy=poss[1].y-poss[0].y; varCx=poss[2].x-poss[1].x; varCy=poss[2].y-poss[1].y; varcull=((((Ax*Cy)-(Ay*Cx))*culling)<0); g.beginPath(); g.strokeStyle=cull?"#592":"#0f0"; g.moveTo(poss[0].x,poss[0].y); g.lineTo(poss[1].x,poss[1].y); g.lineTo(poss[2].x,poss[2].y); g.lineTo(poss[0].x,poss[0].y); g.stroke(); } } P3D.drawByIndexBuffer=function(pos_buf,ix_buf,tx_buf,culling,z_clip){ varw,h; varcolor_polygon=!this.texture; if(this.texture){ w=this.texture.width; h=this.texture.height; } varg=this.g; varm=newM22(); if(!culling)culling=0; if((ix_buf.length%3)!=0) throw"invalidindexbufferlength!"; vari,ibase,vbase,tbase,poss=[{},{},{}]; varlen=ix_buf.length/3; varuv_0u,uv_0v,uv_1u,uv_1v,uv_2u,uv_2v; for(i=0,ibase=0;i<len;++i) { tbase=ix_buf[ibase++]<<1 vbase=tbase<<1; poss[0].x=pos_buf[vbase++];uv_0u=tx_buf[tbase++]; poss[0].y=pos_buf[vbase++];uv_0v=tx_buf[tbase]; if(z_clip&&(pos_buf[vbase]<0||pos_buf[vbase]>1)){ibase+=2;continue;} tbase=ix_buf[ibase++]<<1 vbase=tbase<<1; poss[1].x=pos_buf[vbase++];uv_1u=tx_buf[tbase++]; poss[1].y=pos_buf[vbase++];uv_1v=tx_buf[tbase]; if(z_clip&&(pos_buf[vbase]<0||pos_buf[vbase]>1)){++ibase;continue;} tbase=ix_buf[ibase++]<<1 vbase=tbase<<1; poss[2].x=pos_buf[vbase++];uv_2u=tx_buf[tbase++]; poss[2].y=pos_buf[vbase++];uv_2v=tx_buf[tbase]; if(z_clip&&(pos_buf[vbase]<0||pos_buf[vbase]>1)){continue;} varvAd=[poss[1].x-poss[0].x,poss[1].y-poss[0].y]; varvBd=[poss[2].x-poss[0].x,poss[2].y-poss[0].y]; varvCd=[poss[2].x-poss[1].x,poss[2].y-poss[1].y]; //zcomponentofcrossproduct<0? if((((vAd[0]*vCd[1])-(vAd[1]*vCd[0]))*culling)<0) continue; if(color_polygon){ g.fillStyle=uv_0u; g.beginPath(); g.moveTo(poss[0].x,poss[0].y); g.lineTo(poss[1].x,poss[1].y); g.lineTo(poss[2].x,poss[2].y); g.fill(); continue; } varvA=[uv_1u-uv_0u,uv_1v-uv_0v]; varvB=[uv_2u-uv_0u,uv_2v-uv_0v]; vA[0]*=w; vA[1]*=h; vB[0]*=w; vB[1]*=h; m._11=vA[0]; m._12=vA[1]; m._21=vB[0]; m._22=vB[1]; varim=m.getInvert(); if(!im){continue;} vara=im._11*vAd[0]+im._12*vBd[0]; varb=im._21*vAd[0]+im._22*vBd[0]; varc=im._11*vAd[1]+im._12*vBd[1]; vard=im._21*vAd[1]+im._22*vBd[1]; varwu=uv_0u*w; varhv=uv_0v*h; vardu=wu*a+hv*b; vardv=wu*c+hv*d; g.save(); g.beginPath(); g.moveTo(poss[0].x,poss[0].y); g.lineTo(poss[1].x,poss[1].y); g.lineTo(poss[2].x,poss[2].y); g.clip(); g.transform(a,c,b,d,poss[0].x-du,poss[0].y-dv); //bounds varbx=[wu,wu+vA[0],wu+vB[0]]; varby=[hv,hv+vA[1],hv+vB[1]]; bx.sort(P3D.num_cmp); by.sort(P3D.num_cmp); varbw=bx[2]-bx[0]; varbh=by[2]-by[0]; if((bx[0]+bw)<=(w-1))bw++; if((by[0]+bh)<=(h-1))bh++; if(bx[0]>=1){bx[0]--;bw++;} if(by[0]>=1){by[0]--;bh++;} g.drawImage(this.texture,bx[0],by[0],bw,bh,bx[0],by[0],bw,bh); /* if(shade_clr){ g.fillStyle=shade_clr; g.fillRect(bx[0],by[0],bw,bh); } */ g.restore(); } } functionVec3(_x,_y,_z) { this.x=_x||0; this.y=_y||0; this.z=_z||0; } Vec3.prototype={ zero:function(){ this.x=this.y=this.z=0; }, sub:function(v){ this.x-=v.x; this.y-=v.y; this.z-=v.z; returnthis; }, add:function(v){ this.x+=v.x; this.y+=v.y; this.z+=v.z; returnthis; }, copyFrom:function(v){ this.x=v.x; this.y=v.y; this.z=v.z; returnthis; }, norm:function(){ returnMath.sqrt(this.x*this.x+this.y*this.y+this.z*this.z); }, normalize:function(){ varnrm=Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z); if(nrm!=0) { this.x/=nrm; this.y/=nrm; this.z/=nrm; } returnthis; }, smul:function(k){ this.x*=k; this.y*=k; this.z*=k; returnthis; }, dpWith:function(v){ returnthis.x*v.x+this.y*v.y+this.z*v.z; }, cp:function(v,w){ this.x=(w.y*v.z)-(w.z*v.y); this.y=(w.z*v.x)-(w.x*v.z); this.z=(w.x*v.y)-(w.y*v.x); returnthis; }, toString:function(){ returnthis.x+","+this.y+","+this.z; } } functionM44(cpy) { if(cpy) this.copyFrom(cpy); else{ this.ident(); } } M44.prototype={ ident:function(){ this._12=this._13=this._14=0; this._21=this._23=this._24=0; this._31=this._32=this._34=0; this._41=this._42=this._43=0; this._11=this._22=this._33=this._44=1; returnthis; }, copyFrom:function(m){ this._11=m._11; this._12=m._12; this._13=m._13; this._14=m._14; this._21=m._21; this._22=m._22; this._23=m._23; this._24=m._24; this._31=m._31; this._32=m._32; this._33=m._33; this._34=m._34; this._41=m._41; this._42=m._42; this._43=m._43; this._44=m._44; returnthis; }, transVec3:function(out,x,y,z){ out[0]=x*this._11+y*this._21+z*this._31+this._41; out[1]=x*this._12+y*this._22+z*this._32+this._42; out[2]=x*this._13+y*this._23+z*this._33+this._43; out[3]=x*this._14+y*this._24+z*this._34+this._44; }, transVec3Rot:function(out,x,y,z){ out[0]=x*this._11+y*this._21+z*this._31; out[1]=x*this._12+y*this._22+z*this._32; out[2]=x*this._13+y*this._23+z*this._33; }, perspectiveLH:function(vw,vh,z_near,z_far){ this._11=2.0*z_near/vw; this._12=0; this._13=0; this._14=0; this._21=0; this._22=2*z_near/vh; this._23=0; this._24=0; this._31=0; this._32=0; this._33=z_far/(z_far-z_near); this._34=1; this._41=0; this._42=0; this._43=z_near*z_far/(z_near-z_far); this._44=0; returnthis; }, lookAtLH:function(aUp,aFrom,aAt){ varaX=newVec3(); varaY=newVec3(); varaZ=newVec3(aAt.x,aAt.y,aAt.z); aZ.sub(aFrom).normalize(); aX.cp(aUp,aZ).normalize(); aY.cp(aZ,aX); this._11=aX.x;this._12=aY.x;this._13=aZ.x;this._14=0; this._21=aX.y;this._22=aY.y;this._23=aZ.y;this._24=0; this._31=aX.z;this._32=aY.z;this._33=aZ.z;this._34=0; this._41=-aFrom.dpWith(aX); this._42=-aFrom.dpWith(aY); this._43=-aFrom.dpWith(aZ); this._44=1; returnthis; }, mul:function(A,B){ this._11=A._11*B._11+A._12*B._21+A._13*B._31+A._14*B._41; this._12=A._11*B._12+A._12*B._22+A._13*B._32+A._14*B._42; this._13=A._11*B._13+A._12*B._23+A._13*B._33+A._14*B._43; this._14=A._11*B._14+A._12*B._24+A._13*B._34+A._14*B._44; this._21=A._21*B._11+A._22*B._21+A._23*B._31+A._24*B._41; this._22=A._21*B._12+A._22*B._22+A._23*B._32+A._24*B._42; this._23=A._21*B._13+A._22*B._23+A._23*B._33+A._24*B._43; this._24=A._21*B._14+A._22*B._24+A._23*B._34+A._24*B._44; this._31=A._31*B._11+A._32*B._21+A._33*B._31+A._34*B._41; this._32=A._31*B._12+A._32*B._22+A._33*B._32+A._34*B._42; this._33=A._31*B._13+A._32*B._23+A._33*B._33+A._34*B._43; this._34=A._31*B._14+A._32*B._24+A._33*B._34+A._34*B._44; this._41=A._41*B._11+A._42*B._21+A._43*B._31+A._44*B._41; this._42=A._41*B._12+A._42*B._22+A._43*B._32+A._44*B._42; this._43=A._41*B._13+A._42*B._23+A._43*B._33+A._44*B._43; this._44=A._41*B._14+A._42*B._24+A._43*B._34+A._44*B._44; returnthis; }, translate:function(x,y,z){ this._11=1;this._12=0;this._13=0;this._14=0; this._21=0;this._22=1;this._23=0;this._24=0; this._31=0;this._32=0;this._33=1;this._34=0; this._41=x;this._42=y;this._43=z;this._44=1; returnthis; }, transpose33:function(){ vart; t=this._12; this._12=this._21; this._21=t; t=this._13; this._13=this._31; this._31=t; t=this._23; this._23=this._32; this._32=t; returnthis; }, //OpenGLstylerotation glRotate:function(angle,x,y,z){ vars=Math.sin(angle); varc=Math.cos(angle); varxx=x*x; varyy=y*y; varzz=z*z; varxy=x*y; varyz=y*z; varzx=z*x; varxs=x*s; varys=y*s; varzs=z*s; varone_c=1.0-c; /* this._11=(one_c*xx)+c; this._21=(one_c*xy)-zs; this._31=(one_c*zx)+ys; this._41=0; this._12=(one_c*xy)+zs; this._22=(one_c*yy)+c; this._32=(one_c*yz)-xs; this._42=0; this._13=(one_c*zx)-ys; this._23=(one_c*yz)+xs; this._33=(one_c*zz)+c; this._43=0; this._14=0; this._24=0; this._34=0; this._44=1; */ this._11=(one_c*xx)+c; this._12=(one_c*xy)-zs; this._13=(one_c*zx)+ys; this._14=0; this._21=(one_c*xy)+zs; this._22=(one_c*yy)+c; this._23=(one_c*yz)-xs; this._24=0; this._31=(one_c*zx)-ys; this._32=(one_c*yz)+xs; this._33=(one_c*zz)+c; this._34=0; this._41=0; this._42=0; this._43=0; this._44=1; returnthis; } } //matrix2x2 functionM22() { this._11=1; this._12=0; this._21=0; this._22=1; } M22.prototype.getInvert=function() { varout=newM22(); vardet=this._11*this._22-this._12*this._21; if(det>-0.0001&&det<0.0001) returnnull; out._11=this._22/det; out._22=this._11/det; out._12=-this._12/det; out._21=-this._21/det; returnout; }
3D衣服动画JS代码
JavaScript Code复制内容到剪贴板 functionClothApp() { this.canvas=document.getElementById("cv"); P3D.g=this.canvas.getContext("2d"); vartex=newImage(); this.texture1=tex; tex.onload=function(){_this.start();}; tex.src="20090226032826.gif"; tex=newImage(); this.texture2=tex; tex.onload=function(){_this.start();}; tex.src="20090226032825.png"; this.mLoadCount=2; this.mTickCount=0; this.G=0.53; this.G1=0.45; this.mProjMat=null; this.mViewMat=null; this.mViewFrom=newVec3(); this.mViewFrom.y=-150; this.mViewFrom.z=1000; this.mViewFromA=(newVec3()).copyFrom(this.mViewFrom); this.mViewAngle=0; this.mNLen=0; this.mNodes=[]; this.mRenderTris=null; this.mLTNode=null; this.mRTNode=null; this.mLTNodeV=newVec3(); this.mRTNodeV=newVec3(); this.mWForce=newVec3(); this.frate=15; var_this=this; } ClothApp.zsortCmp=function(t1,t2){ returnt2.sortKey-t1.sortKey; } ClothApp.prototype={ start:function(){ if(--this.mLoadCount!=0)return; this.vUP=newVec3(0,1,0); this.vAT=newVec3(0,80,0); this.mViewport={}; this.mViewport.w=480; this.mViewport.h=300; this.mViewport.ow=240; this.mViewport.oh=150; this.setupTransforms(); this.generateCloth(180); this.generateRenderTriangles(); var_this=this; this.canvas.addEventListener("mousemove",function(e){_this.onMouseMove(e);},false); this.canvas.addEventListener("mousedown",function(e){_this.onClick(e);},false); window.setTimeout(function(){_this.onInterval();},this.frate); }, onInterval:function(){ this.mTickCount++; //this.mLTNodeV.z=Math.cos(this.mTickCount*0.1)*2; this.tick(); this.updatePosition(); this.draw(); var_this=this; window.setTimeout(function(){_this.onInterval();},this.frate); }, onMouseMove:function(e){ if(e.clientX||e.clientX==0) this.mViewAngle=(e.clientX-240)*0.004; if(e.clientY||e.clientY==0) this.mViewFromA.y=90-(e.clientY-0)*0.8; }, onClick:function(e){ if(e.clientX||e.clientX==0) { this.mWForce.z=-4; this.mWForce.x=(e.clientX-240)*-0.03; } }, tick:function(){ this.updateViewTrans(this.mViewAngle); varnlen=this.mNodes.length; vari,nd; for(i=0;i<nlen;i++) { nd=this.mNodes[i]; nd.F.x=0; nd.F.z=0; if(nd.flags&4) nd.F.y=-this.G1; else nd.F.y=-this.G; nd.F.add(this.mWForce); } this.mWForce.zero(); this.applyTension(); for(i=0;i<nlen;i++) { nd=this.mNodes[i]; if((nd.flags&1)!=0){ nd.F.sub(nd.F); } nd.velo.add(nd.F); } this.mLTNode.velo.copyFrom(this.mLTNodeV); this.mRTNode.velo.copyFrom(this.mRTNodeV); }, updatePosition:function(){ varnlen=this.mNodes.length; vari,nd; for(i=0;i<nlen;i++) { nd=this.mNodes[i]; if((nd.flags&1)!=0){ nd.cv.x=0; nd.cv.y=0; nd.cv.z=0; } nd.pos.add(nd.velo); nd.velo.sub(nd.cv); nd.cv.x=0; nd.cv.y=0; nd.cv.z=0; nd.velo.smul(0.95); } }, draw:function(){ P3D.clear("#000",this.mViewport.w,this.mViewport.h); this.transformPolygons(); this.mRenderTris.sort(ClothApp.zsortCmp); varlen=this.mRenderTris.length; vart,sh; for(vari=0;i<len;i++){ t=this.mRenderTris[i]; if(P3D.texture!=t.texture) P3D.texture=t.texture; sh=undefined; if(t.lighting&&t.shade>0.01) sh="rgba(0,0,0,"+t.shade+")"; P3D.drawTriangle(t.tposs,t.uvs,sh); } }, applyTension:function(){ vari,k,nd; varv=newVec3(); varnlen=this.mNodes.length; varnaturalLen=this.mNLen; for(k=0;k<nlen;k++) { nd=this.mNodes[k]; varF=nd.F; for(i=0;i<4;i++) { varnbr=nd.links[i]; if(!nbr)continue; varlen=v.copyFrom(nbr.pos).sub(nd.pos).norm(); vardlen=len-naturalLen; if(dlen>0){ v.smul(dlen*0.5/len); F.x+=v.x; F.y+=v.y; F.z+=v.z; nd.cv.add(v.smul(0.8)); } } } }, setupTransforms:function(){ this.mProjMat=newM44(); this.mProjMat.perspectiveLH(24,15,10,9000); this.mViewMat=newM44(); this.updateViewTrans(0); }, updateViewTrans:function(ry){ this.mViewFromA.z=Math.cos(ry)*380; this.mViewFromA.x=Math.sin(ry)*380; this.mViewFrom.smul(0.7); this.mViewFrom.x+=this.mViewFromA.x*0.3; this.mViewFrom.y+=this.mViewFromA.y*0.3; this.mViewFrom.z+=this.mViewFromA.z*0.3; this.mViewMat.lookAtLH(this.vUP,this.mViewFrom,this.vAT); }, generateCloth:function(base_y){ varcols=9; varrows=8; varstep=22; this.mNLen=step*0.9; varw=(cols-1)*step; vari,k; for(k=0;k<rows;k++) { for(i=0;i<cols;i++) { varnd=newClothNode(); nd.pos.x=-(w/2)+i*step; nd.pos.y=base_y-k*step/2; nd.pos.z=k*16; nd.uv.u=i/(cols-1); nd.uv.v=k/(rows-1); if(i>0){ varprv_nd=this.mNodes[this.mNodes.length-1]; prv_nd.links[1]=nd; nd.links[0]=prv_nd; } if(k>0){ varup_nd=this.mNodes[this.mNodes.length-cols]; up_nd.links[4]=nd; nd.links[3]=up_nd; } if(i!=0&&i!=4&&i!=(cols-1)) nd.flags|=4; this.mNodes.push(nd); } } //fixleft-topandright-top this.mNodes[0].flags|=1; this.mNodes[4].flags|=1; this.mNodes[cols-1].flags|=1; this.mLTNode=this.mNodes[0]; this.mRTNode=this.mNodes[cols-1]; }, generateRenderTriangles:function() { if(!this.mRenderTris)this.mRenderTris=[]; vari; varnd; varnlen=this.mNodes.length; for(i=0;i<nlen;i++) { nd=this.mNodes[i]; if(nd.links[1]&&nd.links[1].links[4]){ vart=newRenderTriangle(); t.texture=this.texture1; t.poss[0]=nd.pos; t.poss[1]=nd.links[1].pos; t.poss[2]=nd.links[1].links[4].pos; t.uvs[0]=nd.uv; t.uvs[1]=nd.links[1].uv; t.uvs[2]=nd.links[1].links[4].uv; this.mRenderTris.push(t); t=newRenderTriangle(); t.texture=this.texture1; t.poss[0]=nd.pos; t.poss[1]=nd.links[1].links[4].pos; t.poss[2]=nd.links[4].pos; t.uvs[0]=nd.uv; t.uvs[1]=nd.links[1].links[4].uv; t.uvs[2]=nd.links[4].uv; this.mRenderTris.push(t); } } this.addBGTriangles(this.mNodes[0].pos.y); }, addBGTriangles:function(by){ varcols=4; vart,x,y,sz=110; varox=-(cols*sz)/2; varoz=-(cols*sz)/2; for(y=0;y<cols;y++){ for(x=0;x<cols;x++){ varbv=((x+y)&1)*0.5; t=newRenderTriangle(); t.texture=this.texture2; t.poss[0]=newVec3(ox+x*sz,by,oz+y*sz); t.poss[1]=newVec3(ox+x*sz+sz,by,oz+y*sz); t.poss[2]=newVec3(ox+x*sz,by,oz+y*sz+sz); t.uvs[0]={u:0,v:bv}; t.uvs[1]={u:0.5,v:bv}; t.uvs[2]={u:0,v:bv+0.5}; if((x==1||x==2)&&(y==1||y==2)) this.modifyRoofUV(t,x==2,bv); t.lighting=false; t.zBias=0.5; this.mRenderTris.push(t); t=newRenderTriangle(); t.texture=this.texture2; t.poss[0]=newVec3(ox+x*sz,by,oz+y*sz+sz); t.poss[1]=newVec3(ox+x*sz+sz,by,oz+y*sz); t.poss[2]=newVec3(ox+x*sz+sz,by,oz+y*sz+sz); t.uvs[0]={u:0,v:bv+0.5}; t.uvs[1]={u:0.5,v:bv}; t.uvs[2]={u:0.5,v:bv+0.5}; if((x==1||x==2)&&(y==1||y==2)) this.modifyRoofUV(t,x==2,bv); t.lighting=false; t.zBias=0.5; this.mRenderTris.push(t); } } }, modifyRoofUV:function(t,rv,bv){ if(rv){ t.uvs[0].u=0.5-t.uvs[0].u; t.uvs[1].u=0.5-t.uvs[1].u; t.uvs[2].u=0.5-t.uvs[2].u; } t.uvs[0].u+=0.5; t.uvs[1].u+=0.5; t.uvs[2].u+=0.5; if(rv){ t.uvs[0].v=0.5-t.uvs[0].v+bv+bv; t.uvs[1].v=0.5-t.uvs[1].v+bv+bv; t.uvs[2].v=0.5-t.uvs[2].v+bv+bv; } }, transformPolygons:function(){ vartrans=newM44(); trans.mul(this.mViewMat,this.mProjMat); varhw=this.mViewport.ow; varhh=this.mViewport.oh; varlen=this.mRenderTris.length; vart; varspos=[0,0,0,0]; for(vari=0;i<len;i++){ t=this.mRenderTris[i]; for(vark=0;k<3;k++){ trans.transVec3(spos,t.poss[k].x,t.poss[k].y,t.poss[k].z); varW=spos[3]; spos[0]/=W; spos[1]/=W; spos[2]/=W; spos[0]*=this.mViewport.w; spos[1]*=-this.mViewport.h; spos[0]+=hw; spos[1]+=hh; t.tposs[k].x=spos[0]; t.tposs[k].y=spos[1]; t.tposs[k].z=spos[2]; } varv1=(newVec3()).copyFrom(t.poss[1]).sub(t.poss[0]).normalize(); varv2=(newVec3()).copyFrom(t.poss[2]).sub(t.poss[1]).normalize(); varN=(newVec3()).cp(v1,v2); trans.transVec3Rot(spos,N.x,N.y,N.z); if(t.lighting){ if(spos[2]>0) t.shade=0.8 else{ t.shade=0.1-N.y*0.6; if(t.shade<0)t.shade=0; } } t.sortKey=Math.floor((t.tposs[0].z+t.tposs[1].z+t.tposs[2].z+t.zBias)*1000); } } } functionClothNode() { this.flags=0; this.pos=newVec3(); this.velo=newVec3(); this.cv=newVec3(); this.F=newVec3(); this.links=[null,null,null,null]; this.uv={u:0,v:0}; } functionRenderTriangle() { this.texture=null; this.poss=newArray(3); this.tposs=[newVec3(),newVec3(),newVec3()]; this.uvs=[{u:0,v:0},{u:0,v:0},{u:0,v:0}]; this.shade=0; this.lighting=true; this.zBias=0; this.sortKey=0; }
以上就是HTML5 3D衣服摇摆动画特效的源码介绍,需要更为深入学习的下载源代码来研究。