玩转Flash AS 3D之贴图篇 (1)
作者:tiger_0309 类型:原创 来源:闪吧
在之前我发过一篇名为玩转flash as 3d的贴子,那时候之所以用“玩转”的字眼,是因为我当时觉得我对flash 3d掌握的很精通了,可是在后来的学习中却发现自己只不过是懂点皮毛罢了,或者可以说连皮毛也还不够,在玩转flash as 3d中我主要介绍了从3d坐标到2d坐标的转换,并且结合flash的画图方法做的一些旋转的例子,关于这方面的例子网上也不少,只不过没有更系统的把它组织和整理出来,而我做的可能就是这方面的工作罢了。
flash是个二维软件,所以它所做的都是假3d,这一点大家必须要认识到,但是从后来的发展,越来越多的人尝试着用它来做一些3d的东西来,假的也越来越来真起来,时下最有名的俩个flash 3d引擎,sandy和papervision3d就是很好的例子,尤其是后者更为突出,并且已经有了as3。
如果说到3d,而不涉及到贴图和光源的话就不能说是3d,在次我将对flash 3d贴图做一个比较“基础”和“系统”的讲解,之所以上引号是到时候有人觉得我讲解的不够系统或者基础,我好有台阶可下,以下我讲的理论并不是我的原创,大部分来自网上。
好了言归正转,在阅读此文章之前我强烈推荐先看看我的第一篇文章,因为我对一些坐标转化之类的不在介绍了。 http://space.flash8.net/bbs/viewthread.php?tid=323970&highlight=
说到如何贴图,其实就是如何动态地skew一个影片剪辑,skew的汉语意思是歪斜.扭曲和变形,我无法用一个词语来代替它,所以就用了一个英文,先看下面的一个简单例子,做一个嵌套的影片剪辑,然后改变父影片剪辑的_yscale,在旋转子影片剪辑就可以。效果:(skew1.swf)
源文件:
skew1.rar
图片附件: 001.gif
图片附件: 002.gif
源文件:
skew3.rar
flash是个二维软件,所以它所做的都是假3d,这一点大家必须要认识到,但是从后来的发展,越来越多的人尝试着用它来做一些3d的东西来,假的也越来越来真起来,时下最有名的俩个flash 3d引擎,sandy和papervision3d就是很好的例子,尤其是后者更为突出,并且已经有了as3。
如果说到3d,而不涉及到贴图和光源的话就不能说是3d,在次我将对flash 3d贴图做一个比较“基础”和“系统”的讲解,之所以上引号是到时候有人觉得我讲解的不够系统或者基础,我好有台阶可下,以下我讲的理论并不是我的原创,大部分来自网上。
好了言归正转,在阅读此文章之前我强烈推荐先看看我的第一篇文章,因为我对一些坐标转化之类的不在介绍了。 http://space.flash8.net/bbs/viewthread.php?tid=323970&highlight=
说到如何贴图,其实就是如何动态地skew一个影片剪辑,skew的汉语意思是歪斜.扭曲和变形,我无法用一个词语来代替它,所以就用了一个英文,先看下面的一个简单例子,做一个嵌套的影片剪辑,然后改变父影片剪辑的_yscale,在旋转子影片剪辑就可以。效果:(skew1.swf)
源文件:

再看下一个例子,做一个嵌套的影片剪辑,父级叫parent,子级叫son,把子级旋转45度,再做几个按钮,在按钮中加入代码来控制父影片剪辑的_yscale和子影片剪辑的_yscale和_xscale,其中的图片大小我们先用100*100,就是正方形。效果:(skew2.swf)
下面的图就是有关skew的数学解释,不过说实话我虽然会应用它,但是对它的数学解释不是太懂,不过我觉得没有必要把它弄的多透彻,只要知道它是怎么来的就。可以了有兴趣的可以自己研究一下,研究出来别忘了告诉我一声。


那么我就直接介绍这个函数了,如图:
function skewObj (obj, mcW, mcH, pt0, ptH, ptW) {
function distance (pt1, pt2) {
var dy = pt2.y-pt1.y;
var dx = pt2.x-pt1.x;
var side = Math.sqrt(dy*dy+dx*dx);
return side;
}
obj._x = pt0.x;//obj是父级影片剪辑
obj._y = pt0.y;
obj._yscale = 100;
var angleP2 = Math.atan2(ptW.y-pt0.y, ptW.x-pt0.x);
var angleP1 = Math.atan2(ptH.y-pt0.y, ptH.x-pt0.x);
var dAngle = (angleP1-angleP2)/2;
var arm = Math.sqrt(2)/2/Math.cos(dAngle);
// original a 100x100 model , now use 1x1 model
obj._rotation = (180/Math.PI)*(angleP1-dAngle);
obj.mc._rotation = -45;//mc是子影片剪辑
obj._yscale = 100*Math.tan(dAngle);
obj.mc._xscale = distance(ptW, pt0)*100/arm/mcW;
obj.mc._yscale = distance(ptH, pt0)*100/arm/mcH;
}
其中pt0, ptH, ptW就是上图的三点,为什么只要三点,因为学过数学的都知道,三点可以确定一个平面,先做一个小小的应用,如下面的例子(skew3.swf):
function distance (pt1, pt2) {
var dy = pt2.y-pt1.y;
var dx = pt2.x-pt1.x;
var side = Math.sqrt(dy*dy+dx*dx);
return side;
}
obj._x = pt0.x;//obj是父级影片剪辑
obj._y = pt0.y;
obj._yscale = 100;
var angleP2 = Math.atan2(ptW.y-pt0.y, ptW.x-pt0.x);
var angleP1 = Math.atan2(ptH.y-pt0.y, ptH.x-pt0.x);
var dAngle = (angleP1-angleP2)/2;
var arm = Math.sqrt(2)/2/Math.cos(dAngle);
// original a 100x100 model , now use 1x1 model
obj._rotation = (180/Math.PI)*(angleP1-dAngle);
obj.mc._rotation = -45;//mc是子影片剪辑
obj._yscale = 100*Math.tan(dAngle);
obj.mc._xscale = distance(ptW, pt0)*100/arm/mcW;
obj.mc._yscale = distance(ptH, pt0)*100/arm/mcH;
}


源文件:

有了以上的基础我们来做第一个3d贴图,代码如下:
Point = function (x, y, z) {
this.x = x;
this.y = y;
this.z = z;
};
Transform3DPointsTo2DPoints = function (pts, angles) {
var tps = new Array();
var sx = Math.sin(angles.x);
var cx = Math.cos(angles.x);
var sy = Math.sin(angles.y);
var cy = Math.cos(angles.y);
var sz = Math.sin(angles.z);
var cz = Math.cos(angles.z);
var p, xy, xz, yx, yz, zx, zy;
var i = pts.length;
while (i--) {
p = pts;
xy = cx*p.y-sx*p.z;
xz = sx*p.y+cx*p.z;
yz = cy*xz-sy*p.x;
yx = sy*xz+cy*p.x;
zx = cz*yx-sz*xy;
zy = sz*yx+cz*xy;
x = 275+zx;
y = 200-zy;
z = yz;
tps = new Point(x, y, z);
}
return tps;
};//坐标转化我就不说了,我在上一篇贴子里已经讲过了
var points3D = [
new Point(-70, -52.5, 70),
new Point(-70, 52.5, 70),
new Point(70, 52.5, 70),
new Point(70, -52.5, 70),
new Point(-70, -52.5, -70),
new Point(-70, 52.5, -70),
new Point(70, 52.5, -70),
new Point(70, -52.5, -70)
];//其实根据三点确定一个平面,不需要这么多点,为了配合图片的大小,我自己算出的3d坐标,你也
可以自己算
var points2D = new Array();
var rotation = new Point(0, 0, 0);
function skewObj(obj, mcW, mcH, pt0, ptH, ptW) {
function distance(pt1, pt2) {
var dy = pt2.y-pt1.y;
var dx = pt2.x-pt1.x;
var side = Math.sqrt(dy*dy+dx*dx);
return side;
}
var z = (ptH.z+ptW.z)/2;
obj.swapDepths(Math.round(10000+z*100));
obj._x = pt0.x;
obj._y = pt0.y;
obj._yscale = 100;
var angleP2 = Math.atan2(ptW.y-pt0.y, ptW.x-pt0.x);
var angleP1 = Math.atan2(ptH.y-pt0.y, ptH.x-pt0.x);
var dAngle = (angleP1-angleP2)/2;
var arm = Math.sqrt(2)/2/Math.cos(dAngle);
// original a 100x100 model , now use 1x1 model
obj._rotation = (180/Math.PI)*(angleP1-dAngle);
obj.mc._rotation = -45;
obj._yscale = 100*Math.tan(dAngle);
obj.mc._xscale = distance(ptW, pt0)*100/arm/mcW;
obj.mc._yscale = distance(ptH, pt0)*100/arm/mcH;
}
for (var i = 1; i<=4; i++) {
_root.attachMovie("obj"+i, "obj"+i, i);
H1 = obj1.mc._height;
W1 = obj1.mc._width;
H2 = obj2.mc._height;
W2 = obj2.mc._width;
H3 = obj3.mc._height;
W3 = obj3.mc._width;
H4 = obj4.mc._height;
W4 = obj4.mc._width;
}
onEnterFrame = function () {
rotation.x -= _ymouse/5000;
rotation.y += _xmouse/5000;
points2D = Transform3DPointsTo2DPoints(points3D, rotation);
skewObj(obj1, W1, H1, points2D[1], points2D[0], points2D[2]);
skewObj(obj2, W2, H2, points2D[2], points2D[3], points2D[6]);
skewObj(obj3, W3, H3, points2D[6], points2D[7], points2D[5]);
skewObj(obj4, W4, H4, points2D[5], points2D[4], points2D[1]);
};
(3d贴图1.swf):
this.x = x;
this.y = y;
this.z = z;
};
Transform3DPointsTo2DPoints = function (pts, angles) {
var tps = new Array();
var sx = Math.sin(angles.x);
var cx = Math.cos(angles.x);
var sy = Math.sin(angles.y);
var cy = Math.cos(angles.y);
var sz = Math.sin(angles.z);
var cz = Math.cos(angles.z);
var p, xy, xz, yx, yz, zx, zy;
var i = pts.length;
while (i--) {
p = pts;
xy = cx*p.y-sx*p.z;
xz = sx*p.y+cx*p.z;
yz = cy*xz-sy*p.x;
yx = sy*xz+cy*p.x;
zx = cz*yx-sz*xy;
zy = sz*yx+cz*xy;
x = 275+zx;
y = 200-zy;
z = yz;
tps = new Point(x, y, z);
}
return tps;
};//坐标转化我就不说了,我在上一篇贴子里已经讲过了
var points3D = [
new Point(-70, -52.5, 70),
new Point(-70, 52.5, 70),
new Point(70, 52.5, 70),
new Point(70, -52.5, 70),
new Point(-70, -52.5, -70),
new Point(-70, 52.5, -70),
new Point(70, 52.5, -70),
new Point(70, -52.5, -70)
];//其实根据三点确定一个平面,不需要这么多点,为了配合图片的大小,我自己算出的3d坐标,你也
可以自己算
var points2D = new Array();
var rotation = new Point(0, 0, 0);
function skewObj(obj, mcW, mcH, pt0, ptH, ptW) {
function distance(pt1, pt2) {
var dy = pt2.y-pt1.y;
var dx = pt2.x-pt1.x;
var side = Math.sqrt(dy*dy+dx*dx);
return side;
}
var z = (ptH.z+ptW.z)/2;
obj.swapDepths(Math.round(10000+z*100));
obj._x = pt0.x;
obj._y = pt0.y;
obj._yscale = 100;
var angleP2 = Math.atan2(ptW.y-pt0.y, ptW.x-pt0.x);
var angleP1 = Math.atan2(ptH.y-pt0.y, ptH.x-pt0.x);
var dAngle = (angleP1-angleP2)/2;
var arm = Math.sqrt(2)/2/Math.cos(dAngle);
// original a 100x100 model , now use 1x1 model
obj._rotation = (180/Math.PI)*(angleP1-dAngle);
obj.mc._rotation = -45;
obj._yscale = 100*Math.tan(dAngle);
obj.mc._xscale = distance(ptW, pt0)*100/arm/mcW;
obj.mc._yscale = distance(ptH, pt0)*100/arm/mcH;
}
for (var i = 1; i<=4; i++) {
_root.attachMovie("obj"+i, "obj"+i, i);
H1 = obj1.mc._height;
W1 = obj1.mc._width;
H2 = obj2.mc._height;
W2 = obj2.mc._width;
H3 = obj3.mc._height;
W3 = obj3.mc._width;
H4 = obj4.mc._height;
W4 = obj4.mc._width;
}
onEnterFrame = function () {
rotation.x -= _ymouse/5000;
rotation.y += _xmouse/5000;
points2D = Transform3DPointsTo2DPoints(points3D, rotation);
skewObj(obj1, W1, H1, points2D[1], points2D[0], points2D[2]);
skewObj(obj2, W2, H2, points2D[2], points2D[3], points2D[6]);
skewObj(obj3, W3, H3, points2D[6], points2D[7], points2D[5]);
skewObj(obj4, W4, H4, points2D[5], points2D[4], points2D[1]);
};
这是单面贴图,我们可以再在上面加上一个以前用过的函数就可以实现双面贴图,就是在上面skewObj(obj, mcW, mcH, pt0, ptH, ptW)函数中加入以下代码就行了。
if (isVisibleBetween(pt0, ptH, ptW)){
if (obj.mc._currentframe != 2) obj.mc.gotoAndStop(2); // frame 1 for front
}else{
if (obj.mc._currentframe != 1) obj.mc.gotoAndStop(1); // frame 2 for back
}
isVisibleBetween(pt0, ptH, ptW)这个函数我以前讲过,是根据平面任意三点的坐标可以计算出该平面是否可见,这个函数如下:
if (obj.mc._currentframe != 2) obj.mc.gotoAndStop(2); // frame 1 for front
}else{
if (obj.mc._currentframe != 1) obj.mc.gotoAndStop(1); // frame 2 for back
}
isVisibleBetween = function(a,b,c){
if (((b.y-a.y)/(b.x-a.x)-(c.y-a.y)/(c.x-a.x)<0)^(a.x<=b.x == a.x>c.x)){
return true;
}else{
return false;
}
};
最后你还要在每个影片剪辑加上一帧,换上你想要的背面图片就可以了,如下:(3d贴图2.swf)
if (((b.y-a.y)/(b.x-a.x)-(c.y-a.y)/(c.x-a.x)<0)^(a.x<=b.x == a.x>c.x)){
return true;
}else{
return false;
}
};
所有的立体图形贴图都是由一小块的正方形或者三角形组成,比如圆柱体,我们可以把它看成许多块矩形组成的,我下面的例子就是一个简单的圆柱体,不过我只是用了十个矩形组成的,要让它更逼真可以把它分割成更多的矩形,这里我还要提醒一点,分的越多,你的cpu负担就越重,有人说这是flash做3d的缺点,认为其它专门的3d软件就不会有这中现象,其实我认为不然,3d软件在渲染的时候占用cpu更大,只不过导出图象序列后就不占用cpu,可是那是静态图象,而flash只所以占用cpu大,是因为它把这渲染和输出合二为一了。
代码:
代码:
Point = function (x, y, z) {
this.x = x;
this.y = y;
this.z = z;
};
Transform3DPointsTo2DPoints = function (pts, angles) {
var tps = new Array();
var sx = Math.sin(angles.x);
var cx = Math.cos(angles.x);
var sy = Math.sin(angles.y);
var cy = Math.cos(angles.y);
var sz = Math.sin(angles.z);
var cz = Math.cos(angles.z);
var p, xy, xz, yx, yz, zx, zy;
var i = pts.length;
while (i--) {
p = pts;
xy = cx*p.y-sx*p.z;
xz = sx*p.y+cx*p.z;
yz = cy*xz-sy*p.x;
yx = sy*xz+cy*p.x;
zx = cz*yx-sz*xy;
zy = sz*yx+cz*xy;
x=275+zx;
y=200-zy;
z=yz;
tps = new Point(x, y, z);
}
return tps;
};
var points3D = [
new Point(100*Math.cos(2*Math.PI/10*0), 100, 100*Math.sin(2*Math.PI/10*0)),
new Point(100*Math.cos(2*Math.PI/10*1), 100, 100*Math.sin(2*Math.PI/10*1)),
new Point(100*Math.cos(2*Math.PI/10*2), 100, 100*Math.sin(2*Math.PI/10*2)),
new Point(100*Math.cos(2*Math.PI/10*3), 100, 100*Math.sin(2*Math.PI/10*3)),
new Point(100*Math.cos(2*Math.PI/10*4), 100, 100*Math.sin(2*Math.PI/10*4)),
new Point(100*Math.cos(2*Math.PI/10*5), 100, 100*Math.sin(2*Math.PI/10*5)),
new Point(100*Math.cos(2*Math.PI/10*6), 100, 100*Math.sin(2*Math.PI/10*6)),
new Point(100*Math.cos(2*Math.PI/10*7), 100, 100*Math.sin(2*Math.PI/10*7)),
new Point(100*Math.cos(2*Math.PI/10*8), 100, 100*Math.sin(2*Math.PI/10*8)),
new Point(100*Math.cos(2*Math.PI/10*9), 100, 100*Math.sin(2*Math.PI/10*9)),
new Point(100*Math.cos(2*Math.PI/10*0), -100, 100*Math.sin(2*Math.PI/10*0)),
new Point(100*Math.cos(2*Math.PI/10*1), -100, 100*Math.sin(2*Math.PI/10*1)),
new Point(100*Math.cos(2*Math.PI/10*2), -100, 100*Math.sin(2*Math.PI/10*2)),
new Point(100*Math.cos(2*Math.PI/10*3), -100, 100*Math.sin(2*Math.PI/10*3)),
new Point(100*Math.cos(2*Math.PI/10*4), -100, 100*Math.sin(2*Math.PI/10*4)),
new Point(100*Math.cos(2*Math.PI/10*5), -100, 100*Math.sin(2*Math.PI/10*5)),
new Point(100*Math.cos(2*Math.PI/10*6), -100, 100*Math.sin(2*Math.PI/10*6)),
new Point(100*Math.cos(2*Math.PI/10*7), -100, 100*Math.sin(2*Math.PI/10*7)),
new Point(100*Math.cos(2*Math.PI/10*8), -100, 100*Math.sin(2*Math.PI/10*8)),
new Point(100*Math.cos(2*Math.PI/10*9), -100, 100*Math.sin(2*Math.PI/10*9))
];
var points2D = new Array();
var rotation = new Point(0, 0, 0);
function skewObj(obj, mcW, mcH, pt0, ptH, ptW) {
function distance(pt1, pt2) {
var dy = pt2.y-pt1.y;
var dx = pt2.x-pt1.x;
var side = Math.sqrt(dy*dy+dx*dx);
return side;
}
var z=(ptH.z+ptW.z+pt0.z)/3;
obj.swapDepths(Math.round(10000+z*100));
obj._x = pt0.x;
obj._y = pt0.y;
obj._yscale = 100;
var angleP2 = Math.atan2(ptW.y-pt0.y, ptW.x-pt0.x);
var angleP1 = Math.atan2(ptH.y-pt0.y, ptH.x-pt0.x);
var dAngle = (angleP1-angleP2)/2;
var arm = Math.sqrt(2)/2/Math.cos(dAngle);
// original a 100x100 model , now use 1x1 model
obj._rotation = (180/Math.PI)*(angleP1-dAngle);
obj.mc._rotation = -45;
obj._yscale = 100*Math.tan(dAngle);
obj.mc._xscale = distance(ptW, pt0)*100/arm/mcW;
obj.mc._yscale = distance(ptH, pt0)*100/arm/mcH;
}
for(var i=0;i<10;i++){
_root.attachMovie("obj"+(i+1),"obj"+(i+1),i+1);
H1 = obj1.mc._height;
W1 = obj1.mc._width;
H2 = obj2.mc._height;
W2 = obj2.mc._width;
H3 = obj3.mc._height;
W3 = obj3.mc._width;
H4 = obj4.mc._height;
W4 = obj4.mc._width;
H5 = obj5.mc._height;
W5 = obj5.mc._width;
H6 = obj6.mc._height;
W6 = obj6.mc._width;
H7 = obj7.mc._height;
W7 = obj7.mc._width;
H8 = obj8.mc._height;
W8 = obj8.mc._width;
H9 = obj9.mc._height;
W9 = obj9.mc._width;
H10 = obj10.mc._height;
W10 = obj10.mc._width;
}
onEnterFrame = function () {
rotation.x -= _ymouse/5000;
rotation.y += _xmouse/5000;
points2D = Transform3DPointsTo2DPoints(points3D, rotation);
skewObj(obj1, W1, H1, points2D[0], points2D[10], points2D[1]);
skewObj(obj2, W2, H2, points2D[1], points2D[11], points2D[2]);
skewObj(obj3, W3, H3, points2D[2], points2D[12], points2D[3]);
skewObj(obj4, W4, H4, points2D[3], points2D[13], points2D[4]);
skewObj(obj5, W5, H5, points2D[4], points2D[14], points2D[5]);
skewObj(obj6, W6, H6, points2D[5], points2D[15], points2D[6]);
skewObj(obj7, W7, H7, points2D[6], points2D[16], points2D[7]);
skewObj(obj8, W8, H8, points2D[7], points2D[17], points2D[8]);
skewObj(obj9, W9, H9, points2D[8], points2D[18], points2D[9]);
skewObj(obj10, W10, H10, points2D[9], points2D[19], points2D[0]);
};
(3d贴图3.swf):
this.x = x;
this.y = y;
this.z = z;
};
Transform3DPointsTo2DPoints = function (pts, angles) {
var tps = new Array();
var sx = Math.sin(angles.x);
var cx = Math.cos(angles.x);
var sy = Math.sin(angles.y);
var cy = Math.cos(angles.y);
var sz = Math.sin(angles.z);
var cz = Math.cos(angles.z);
var p, xy, xz, yx, yz, zx, zy;
var i = pts.length;
while (i--) {
p = pts;
xy = cx*p.y-sx*p.z;
xz = sx*p.y+cx*p.z;
yz = cy*xz-sy*p.x;
yx = sy*xz+cy*p.x;
zx = cz*yx-sz*xy;
zy = sz*yx+cz*xy;
x=275+zx;
y=200-zy;
z=yz;
tps = new Point(x, y, z);
}
return tps;
};
var points3D = [
new Point(100*Math.cos(2*Math.PI/10*0), 100, 100*Math.sin(2*Math.PI/10*0)),
new Point(100*Math.cos(2*Math.PI/10*1), 100, 100*Math.sin(2*Math.PI/10*1)),
new Point(100*Math.cos(2*Math.PI/10*2), 100, 100*Math.sin(2*Math.PI/10*2)),
new Point(100*Math.cos(2*Math.PI/10*3), 100, 100*Math.sin(2*Math.PI/10*3)),
new Point(100*Math.cos(2*Math.PI/10*4), 100, 100*Math.sin(2*Math.PI/10*4)),
new Point(100*Math.cos(2*Math.PI/10*5), 100, 100*Math.sin(2*Math.PI/10*5)),
new Point(100*Math.cos(2*Math.PI/10*6), 100, 100*Math.sin(2*Math.PI/10*6)),
new Point(100*Math.cos(2*Math.PI/10*7), 100, 100*Math.sin(2*Math.PI/10*7)),
new Point(100*Math.cos(2*Math.PI/10*8), 100, 100*Math.sin(2*Math.PI/10*8)),
new Point(100*Math.cos(2*Math.PI/10*9), 100, 100*Math.sin(2*Math.PI/10*9)),
new Point(100*Math.cos(2*Math.PI/10*0), -100, 100*Math.sin(2*Math.PI/10*0)),
new Point(100*Math.cos(2*Math.PI/10*1), -100, 100*Math.sin(2*Math.PI/10*1)),
new Point(100*Math.cos(2*Math.PI/10*2), -100, 100*Math.sin(2*Math.PI/10*2)),
new Point(100*Math.cos(2*Math.PI/10*3), -100, 100*Math.sin(2*Math.PI/10*3)),
new Point(100*Math.cos(2*Math.PI/10*4), -100, 100*Math.sin(2*Math.PI/10*4)),
new Point(100*Math.cos(2*Math.PI/10*5), -100, 100*Math.sin(2*Math.PI/10*5)),
new Point(100*Math.cos(2*Math.PI/10*6), -100, 100*Math.sin(2*Math.PI/10*6)),
new Point(100*Math.cos(2*Math.PI/10*7), -100, 100*Math.sin(2*Math.PI/10*7)),
new Point(100*Math.cos(2*Math.PI/10*8), -100, 100*Math.sin(2*Math.PI/10*8)),
new Point(100*Math.cos(2*Math.PI/10*9), -100, 100*Math.sin(2*Math.PI/10*9))
];
var points2D = new Array();
var rotation = new Point(0, 0, 0);
function skewObj(obj, mcW, mcH, pt0, ptH, ptW) {
function distance(pt1, pt2) {
var dy = pt2.y-pt1.y;
var dx = pt2.x-pt1.x;
var side = Math.sqrt(dy*dy+dx*dx);
return side;
}
var z=(ptH.z+ptW.z+pt0.z)/3;
obj.swapDepths(Math.round(10000+z*100));
obj._x = pt0.x;
obj._y = pt0.y;
obj._yscale = 100;
var angleP2 = Math.atan2(ptW.y-pt0.y, ptW.x-pt0.x);
var angleP1 = Math.atan2(ptH.y-pt0.y, ptH.x-pt0.x);
var dAngle = (angleP1-angleP2)/2;
var arm = Math.sqrt(2)/2/Math.cos(dAngle);
// original a 100x100 model , now use 1x1 model
obj._rotation = (180/Math.PI)*(angleP1-dAngle);
obj.mc._rotation = -45;
obj._yscale = 100*Math.tan(dAngle);
obj.mc._xscale = distance(ptW, pt0)*100/arm/mcW;
obj.mc._yscale = distance(ptH, pt0)*100/arm/mcH;
}
for(var i=0;i<10;i++){
_root.attachMovie("obj"+(i+1),"obj"+(i+1),i+1);
H1 = obj1.mc._height;
W1 = obj1.mc._width;
H2 = obj2.mc._height;
W2 = obj2.mc._width;
H3 = obj3.mc._height;
W3 = obj3.mc._width;
H4 = obj4.mc._height;
W4 = obj4.mc._width;
H5 = obj5.mc._height;
W5 = obj5.mc._width;
H6 = obj6.mc._height;
W6 = obj6.mc._width;
H7 = obj7.mc._height;
W7 = obj7.mc._width;
H8 = obj8.mc._height;
W8 = obj8.mc._width;
H9 = obj9.mc._height;
W9 = obj9.mc._width;
H10 = obj10.mc._height;
W10 = obj10.mc._width;
}
onEnterFrame = function () {
rotation.x -= _ymouse/5000;
rotation.y += _xmouse/5000;
points2D = Transform3DPointsTo2DPoints(points3D, rotation);
skewObj(obj1, W1, H1, points2D[0], points2D[10], points2D[1]);
skewObj(obj2, W2, H2, points2D[1], points2D[11], points2D[2]);
skewObj(obj3, W3, H3, points2D[2], points2D[12], points2D[3]);
skewObj(obj4, W4, H4, points2D[3], points2D[13], points2D[4]);
skewObj(obj5, W5, H5, points2D[4], points2D[14], points2D[5]);
skewObj(obj6, W6, H6, points2D[5], points2D[15], points2D[6]);
skewObj(obj7, W7, H7, points2D[6], points2D[16], points2D[7]);
skewObj(obj8, W8, H8, points2D[7], points2D[17], points2D[8]);
skewObj(obj9, W9, H9, points2D[8], points2D[18], points2D[9]);
skewObj(obj10, W10, H10, points2D[9], points2D[19], points2D[0]);
};
光有矩形贴图还不够,有时候还需要三角形,三角形的原理也来自矩形,如下图,我们把矩形也看成正方形,通过给出的三角形pH的坐标可以算出ptH的坐标,
那么上面的函数就变成这样了:
skewObj(clip, 100, 100, rp0, getPH(rp0,rpH,rpW), rpW);
其中100我是按照正方形来计算的,如果你不是用的正方形,那么应该是这样了
skewObj(clip, mcW, mcH, rp0, getPH(rp0,rpH,rpW), rpW);
mcW和mcH分别是矩形的长和宽
这是四面体的三维坐标:
pointsArray = [
new Point(-50, 29, 29),
new Point(0, 29, -58),
new Point(50, 29, 29),
new Point(0, -58, 0)];
具体的原代码我就不给了,大家只需把坐标和上面的函数换一下就好了,如果实在做不出,把我的swf反编译也行,所有的文件都没有加密。(3d贴图4.swf):
图片附件: 003. gif
function getPH(pt0,pH,ptW){
var pt=new Object();
pt.x=pH.x-(ptW.x-pt0.x)/2;
pt.y=pH.y-(ptW.y-pt0.y)/2
pt.z=pH.z-(ptW.z-pt0.z)/2;
return pt;
}
//这个函数不用解释也能看懂吧
var pt=new Object();
pt.x=pH.x-(ptW.x-pt0.x)/2;
pt.y=pH.y-(ptW.y-pt0.y)/2
pt.z=pH.z-(ptW.z-pt0.z)/2;
return pt;
}
那么上面的函数就变成这样了:
skewObj(clip, 100, 100, rp0, getPH(rp0,rpH,rpW), rpW);
其中100我是按照正方形来计算的,如果你不是用的正方形,那么应该是这样了
skewObj(clip, mcW, mcH, rp0, getPH(rp0,rpH,rpW), rpW);
mcW和mcH分别是矩形的长和宽
这是四面体的三维坐标:
pointsArray = [
new Point(-50, 29, 29),
new Point(0, 29, -58),
new Point(50, 29, 29),
new Point(0, -58, 0)];
具体的原代码我就不给了,大家只需把坐标和上面的函数换一下就好了,如果实在做不出,把我的swf反编译也行,所有的文件都没有加密。(3d贴图4.swf):


然后我们再看看上面的哪个圆柱体,给它加个盖和底,说到这里我有要提一下闪客帝国有名的哪个3d易拉罐,当时看的时候怎么也看不懂,并且原文件加密了,现在再想想其实也不难,它只不过把它分割成一个个的三角形而已。(3d贴图5.swf):
写到这里理论上我们可以给任意的立体图形贴图了,只要你有耐心,你的配置足够高(主要是cpu).
回顾上面的例子,不知道你注意到没有,所有的贴图还有个致命的缺陷,就是做出来的三维图形不是真正意义上的透视图形,为什么呢?那是因为在flash8之前还不能操作位图,所有的坐标都没有进行透视处理,你可以试一下坐标透视处理后会出现下面状况,把上面坐标转化函数改成这样:
写到这里理论上我们可以给任意的立体图形贴图了,只要你有耐心,你的配置足够高(主要是cpu).
回顾上面的例子,不知道你注意到没有,所有的贴图还有个致命的缺陷,就是做出来的三维图形不是真正意义上的透视图形,为什么呢?那是因为在flash8之前还不能操作位图,所有的坐标都没有进行透视处理,你可以试一下坐标透视处理后会出现下面状况,把上面坐标转化函数改成这样:
scaleFactor = focalLength/(focalLength+yz);
x = zx*scaleFactor;
y = zy*scaleFactor;
z = yz;
不过庆幸的是在flash8中我们可以做到真正的透视3d了,最后的一个例子我就是用flash8做的,你可以和上面的比较一下,看有什么不同,在这个原文件我应用了ditortimage类,老外写的类,很不错。(3d贴图6.swf):
x = zx*scaleFactor;
y = zy*scaleFactor;
z = yz;