html 衣服特效,新7款HTML5/CSS3特效之3D衣服摆动

function ClothApp()

{

this.canvas = document.getElementById("cv");

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

var tex = new Image();

this.texture1 = tex;

tex.onload = function(){

_this.start();

};

tex.src = "//ku.shouce.ren/files/images/201603/56e5100521fc6.gif";

tex = new Image();

this.texture2 = tex;

tex.onload = function(){

_this.start();

};

tex.src = "//ku.shouce.ren/files/images/201603/56e5102959956.png";

this.mLoadCount = 2;

this.mTickCount = 0;

this.G = 0.53;

this.G1 = 0.45;

this.mProjMat = null;

this.mViewMat = null;

this.mViewFrom = new Vec3();

this.mViewFrom.y = -150;

this.mViewFrom.z = 1000;

this.mViewFromA = (new Vec3()).copyFrom(this.mViewFrom);

this.mViewAngle = 0;

this.mNLen = 0;

this.mNodes = [];

this.mRenderTris = null;

this.mLTNode = null;

this.mRTNode = null;

this.mLTNodeV = new Vec3();

this.mRTNodeV = new Vec3();

this.mWForce = new Vec3();

this.frate = 15;

var _this = this;

}

ClothApp.zsortCmp = function(t1, t2) {

return t2.sortKey - t1.sortKey;

}

ClothApp.prototype = {

start: function() {

if (--this.mLoadCount != 0) return;

this.vUP = new Vec3(0, 1, 0);

this.vAT = new Vec3(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);

var nlen = this.mNodes.length;

var i, 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() {

var nlen = this.mNodes.length;

var i, 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);

var len = this.mRenderTris.length;

var t, sh;

for (var i = 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() {

var i, k, nd;

var v = new Vec3();

var nlen = this.mNodes.length;

var naturalLen = this.mNLen;

for (k = 0;k < nlen;k++)

{

nd = this.mNodes[k];

var F = nd.F;

for (i = 0;i < 4;i++)

{

var nbr = nd.links[i];

if (!nbr) continue;

var len = v.copyFrom(nbr.pos).sub(nd.pos).norm();

var dlen = 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 = new M44();

this.mProjMat.perspectiveLH(24, 15, 10, 9000);

this.mViewMat = new M44();

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) {

var cols = 9;

var rows = 8;

var step = 22;

this.mNLen = step*0.9;

var w = (cols-1) * step;

var i, k;

for (k = 0;k < rows;k++)

{

for (i = 0;i < cols;i++)

{

var nd = new ClothNode();

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) {

var prv_nd = this.mNodes[this.mNodes.length-1];

prv_nd.links[1] = nd;

nd.links[0] = prv_nd;

}

if (k > 0) {

var up_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);

}

}

// fix left-top and right-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 = [];

var i;

var nd;

var nlen = this.mNodes.length;

for(i = 0;i < nlen;i++)

{

nd = this.mNodes[i];

if (nd.links[1] && nd.links[1].links[4]) {

var t = new RenderTriangle();

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 = new RenderTriangle();

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) {

var cols = 4;

var t, x, y, sz = 110;

var ox = -(cols*sz)/2;

var oz = -(cols*sz)/2;

for (y = 0;y < cols;y++) {

for (x = 0;x < cols;x++) {

var bv = ((x+y)&1) * 0.5;

t = new RenderTriangle();

t.texture = this.texture2;

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

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

t.poss[2] = new Vec3(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 = new RenderTriangle();

t.texture = this.texture2;

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

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

t.poss[2] = new Vec3(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() {

var trans = new M44();

trans.mul(this.mViewMat, this.mProjMat);

var hw = this.mViewport.ow;

var hh = this.mViewport.oh;

var len = this.mRenderTris.length;

var t;

var spos = [0, 0, 0, 0];

for (var i = 0;i < len;i++) {

t = this.mRenderTris[i];

for (var k = 0;k < 3;k++) {

trans.transVec3(spos, t.poss[k].x, t.poss[k].y, t.poss[k].z);

var W = 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];

}

var v1 = (new Vec3()).copyFrom(t.poss[1]).sub(t.poss[0]).normalize();

var v2 = (new Vec3()).copyFrom(t.poss[2]).sub(t.poss[1]).normalize();

var N = (new Vec3()).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 );

}

}

}

function ClothNode()

{

this.flags = 0;

this.pos = new Vec3();

this.velo = new Vec3();

this.cv = new Vec3();

this.F = new Vec3();

this.links = [null, null, null, null];

this.uv = {

u:0, v:0};

}

function RenderTriangle()

{

this.texture = null;

this.poss = new Array(3);

this.tposs = [new Vec3(), new Vec3(), new Vec3()];

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;

}

void( new ClothApp() );

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值