[原创]最新编写的三维类Vxp3
为了实现更强大的三维效果,重新改写了更为完善的三维类,命名为Vxp3。[b][color=red]相对于前一个版本,主要做了如下更新:[/color] [/b]
[quote]1、将方法的数量增加到39个,能够实现更多的功能;
2、为了保持向下兼容,很多不再推荐的方法仍然保留;
3、按照计算机图形学的通常情况更改了坐标系,修改旋转的方向为逆时针;
4、新增向量分解和坐标系变换两种方法编写的任意轴旋转问题,不过从效率上讲,推荐前者;
5、扩展向量的缩放方法,可沿坐标轴缩放,全坐标轴缩放和任意向量缩放;
6、更新了向屏幕投影的算法,以观察距离为缩放度量,使立体感更强;
7、新增正交投影方法;
8、新增镜像变换方法;
9、新增错切方法。
[/quote]
[b][color=red]整个类的源文件分为以下十个部分:[/color] [/b]
[quote]1、基本属性;
2、构造函数
3、基本方法;
4、数值计算;
5、旋转方法;
6、缩放方法;
7、屏幕投影;
8、正交投影;
9、镜像变换;
10、错切变换。[/quote] [b][color=Red]全部源代码如下:[/color][/b]
[code]class Vxp3 {
//---------------------------
//三维向量的40个基本方法
//最后更新:2007-06-14
//版本:1.00_alpha
//作者:las
//E-mail:ilovelassie@163.com
//版权:遵守GNU协议,任何人都可以自由复制修改传播,但不得用于商业用途。
//----------------------------
//定义三个坐标作为共有属性。
public var ix:Number;
public var iy:Number;
public var iz:Number;
//构造函数。
public function Vxp3(param_x:Number, param_y:Number, param_z:Number) {
this.ix = param_x;
this.iy = param_y;
this.iz = param_z;
}
//基本方法:
//1.输出向量到输出窗口。
public function toString(s:String):Void {
trace(s+": x:"+this.ix+" y:"+this.iy+" z:"+this.iz);
}
//2.向量的重设。
public function reset(param_x:Number, param_y:Number, param_z:Number):Void {
this.ix = param_x;
this.iy = param_y;
this.iz = param_z;
}
//3.向量的复制。
public function clone():Vxp3 {
return (new Vxp3(this.ix, this.iy, this.iz));
}
//计算方法:
//1.向量比较。
public function equal(v:Vxp3):Boolean {
return (this.ix == v.ix && this.iy == v.iy && this.iz == v.iz);
}
//2.向量加法。
public function plus(v:Vxp3):Vxp3 {
return (new Vxp3(this.ix+v.ix, this.iy+v.iy, this.iz+v.iz));
}
//3.向量减法。
public function minus(v:Vxp3):Vxp3 {
return (new Vxp3(this.ix-v.ix, this.iy-v.iy, this.iz-v.iz));
}
//4.向量求模。
public function get mod():Number {
return (Math.sqrt(this.ix*this.ix+this.iy*this.iy+this.iz*this.iz));
}
//5.向量设模。
public function set mod(l:Number):Void {
var r = this.mod;
if (r == 0) {
this.reset(0, 0, 0);
} else {
var v = this.scale(l/r);
this.reset(v.ix, v.iy, v.iz);
}
}
//6.向量点积。
public function dot(v:Vxp3):Number {
return (this.ix*v.ix+this.iy*v.iy+this.iz*v.iz);
}
//7.向量叉乘。
public function cross(v:Vxp3):Vxp3 {
var cx = this.iy*v.iz-this.iz*v.iy;
var cy = this.iz*v.ix-this.ix*v.iz;
var cz = this.ix*v.iy-this.iy*v.ix;
return (new Vxp3(cx, cy, cz));
}
//8.向量夹角。
public function angle(v:Vxp3):Number {
var dp = this.dot(v);
var cosAngle = dp/(this.mod*v.mod);
return (Math.acos(cosAngle));
}
//9.向量的X轴方向角。
public function angleX():Number {
return (Math.acos(this.ix/this.mod));
}
//10.向量的Y轴方向角。
public function angleY():Number {
return (Math.acos(this.iy/this.mod));
}
//11.向量的Z轴方向角。
public function angleZ():Number {
return (Math.acos(this.iz/this.mod));
}
//旋转方法
//12.围绕X轴旋转,参数为逆时针角速度。
public function rotateX1(a:Number):Vxp3 {
return (this.rotateX2(Math.cos(a), Math.sin(a)));
}
//13.围绕Y轴旋转,参数为逆时针角速度。
public function rotateY1(a:Number):Vxp3 {
return (this.rotateY2(Math.cos(a), Math.sin(a)));
}
//14.围绕Z轴旋转,参数为逆时针角速度。
public function rotateZ1(a:Number):Vxp3 {
return (this.rotateZ2(Math.cos(a), Math.sin(a)));
}
//15.围绕X轴旋转,参数为逆时针角速度的余弦值和正弦值。
public function rotateX2(c:Number, s:Number):Vxp3 {
var ny = this.iy*c-this.iz*s;
var nz = this.iz*c+this.iy*s;
return (new Vxp3(this.ix, ny, nz));
}
//16.围绕Y轴旋转,参数为逆时针角速度的余弦值和正弦值。
public function rotateY2(c:Number, s:Number):Vxp3 {
var nz = this.iz*c-this.ix*s;
var nx = this.ix*c+this.iz*s;
return (new Vxp3(nx, this.iy, nz));
}
//17.围绕Z轴旋转,参数为逆时针角速度的余弦值和正弦值。
public function rotateZ2(c:Number, s:Number):Vxp3 {
var nx = this.ix*c-this.iy*s;
var ny = this.iy*c+this.ix*s;
return (new Vxp3(nx, ny, this.iz));
}
//18.使用向量分解法的扩展旋转方法,参数为基准向量和要旋转角度值。
public function rotateN1(param_n:Vxp3, a:Number):Vxp3 {
return (this.rotateN2(param_n, Math.cos(a), Math.sin(a)));
}
//19.使用向量分解法的扩展旋转方法,参数为基准向量和要旋转角度的余弦和正弦值。
public function rotateN2(param_n:Vxp3, c:Number, s:Number):Vxp3 {
var n = param_n.clone();
n.mod = 1;
var v = n.scale(this.dot(n));
return (((this.minus(v)).scale(c)).plus((n.cross(this)).scale(s)).plus(v));
}
//20.使用局部坐标系法的扩展旋转方法。
public function rotateN3(v:Vxp3, a:Number):Vxp3 {
var vi:Vxp3 = new Vxp3();
var vj:Vxp3 = new Vxp3();
var vk:Vxp3 = new Vxp3();
var vc:Vxp3 = new Vxp3();
var vs:Vxp3 = new Vxp3();
vi = v.clone();
if (vi.iy == 0 && vi.iz == 0) {
vj.reset(0, 1, 0);
} else {
vj.reset(1, 0, 0);
}
vk = vj.cross(vi);
vj = vk.cross(vi);
vi.mod = 1;
vj.mod = 1;
vk.mod = 1;
var vc = new Vxp3(this.dot(vi), this.dot(vj), this.dot(vk));
vc = vc.rotateX1(a);
var vs = vc.clone();
vs.ix = vc.ix*vi.ix+vc.iy*vj.ix+vc.iz*vk.ix;
vs.iy = vc.ix*vi.iy+vc.iy*vj.iy+vc.iz*vk.iy;
vs.iz = vc.ix*vi.iz+vc.iy*vj.iz+vc.iz*vk.iz;
return vs;
}
//缩放方法
//21.同比例缩放。
public function scale(s:Number):Vxp3 {
return (new Vxp3(this.ix*s, this.iy*s, this.iz*s));
}
//22.X轴缩放。
public function scaleX(s:Number):Vxp3 {
return (new Vxp3(this.ix*s, this.iy, this.iz));
}
//23.Y轴缩放。
public function scaleY(s:Number):Vxp3 {
return (new Vxp3(this.ix, this.iy*s, this.iz));
}
//24.Z轴缩放。
public function scaleZ(s:Number):Vxp3 {
return (new Vxp3(this.ix, this.iy, this.iz*s));
}
//25.任意轴缩放,参数为基准向量和缩放系数。
public function scaleN(param_n:Vxp3, s:Number):Vxp3 {
var n = param_n.clone();
n.mod = 1;
var v = n.scale(this.dot(n)*(s-1));
return (this.plus(v));
}
//屏幕投影
//26.使用远点投影法返回X轴坐标。
public function translateX(l:Number):Number {
return (l*this.ix/(l-this.iz));
}
//27.使用远点投影法返回Y轴坐标。
public function translateY(l:Number):Number {
return (l*this.iy/(l-this.iz));
}
//28.新投影法,返回屏幕X坐标。
public function tranToX(v:Vxp3):Number {
var l:Number = v.mod;
return (l*this.ix/(l-this.iz));
}
//29.新投影法,返回屏幕Y坐标
public function tranToY(v:Vxp3):Number {
var l:Number = v.mod;
return (l*this.iy/(l-this.iz));
}
//正交投影
//30.任意过原点直线上的投影。
public function projectL(param_n:Vxp3):Vxp3 {
var n = param_n.clone();
n.mod = 1;
return (n.scale(this.dot(n)));
}
//31.任意过原点平面上的投影,参数为平面的法向量。
public function projectS(param_n:Vxp3):Vxp3 {
var n = param_n.clone();
n.mod = 1;
return (this.minus(n.scale(this.dot(n))));
}
//镜像变换
//32.向量关于X轴的镜像。
public function mirrorX():Vxp3 {
return (this.scaleX(-1));
}
//33.向量关于Y轴的镜像。
public function mirrorY():Vxp3 {
return (this.scaleY(-1));
}
//34.向量关于Z轴的镜像。
public function mirrorZ():Vxp3 {
return (this.scaleZ(-1));
}
//35.向量关于原点的镜像。
public function mirrorO():Vxp3 {
return (this.scale(-1));
}
//36.向量关于任意过原点直线的镜像。
public function mirrorN(param_n:Vxp3):Vxp3 {
var n = param_n.clone();
n.mod = 1;
return (this.minus(n.scale(2*this.dot(n))));
}
//错切变换
//37.X轴Y轴方向的切变,参数为X轴方向的切变系数xs和Y轴方向的切变系数ys。
public function shareXY(xs:Number, ys:Number):Vxp3 {
return (new Vxp3(this.ix+this.iz*xs, this.iy+this.iz*ys, this.iz));
}
//38.Y轴Z轴方向的切变,参数为Y轴方向的切变系数ys和Z轴方向的切变系数zs。
public function shareYZ(ys:Number, zs:Number):Vxp3 {
return (new Vxp3(this.ix, this.iy+this.ix*ys, this.iz+this.ix*zs));
}
//39.Z轴X轴方向的切变,参数为Z轴方向的切变系数xs和X轴方向的切变系数xs。
public function shareZX(zs:Number, xs:Number):Vxp3 {
return (new Vxp3(this.ix+this.iy*xs, this.iy, this.iz+this.ix*zs));
}
}[/code] 不错
流星做这个1年多了啊,现在应该是这方面专家了
有前途
附:编程随想一篇
为了编写更新更高级的三维效果,特意重新编写了原来的三维类。在此期间参考阅读了《3D数学基础:图形与游戏开发》,这本书着重讲解了数学知识。其实编程到了一定程度,所困扰的或者说所称为水平提高的瓶颈其实就是数学。所以应该多看一些数学书,学习一些数学知识。说到这里我不得不扯些,数学真的可以称得上是关于方法的学科,其中所蕴含的思想是终身受益的。可是现在我们的教育是那种填鸭式的教育,不管你愿不愿意,不管你有没有兴趣,我的任务就是把这些强制性添装到你的脑子里去,考试的时候你能写在卷子上就OK了。这样我老师可以获得所谓的“教育质量”,学生也可以获得所谓的“学习成绩”,往往忽略了知识的本质。学生掌握了大量的知识,却不知道如何应用。
当我在这本书上看到了我所需要的问题的解决方法。这里面的数学知识正是我所学过的《线性代数》和《矩阵论》,比如向量的分解,向量的正交化——施密特正交化,向量的标准正交基,坐标系的相互转换,还有矩阵的一些性质——单位正交阵的逆等于它的转置等。这时候我才知道我们学的知识是干什么用的,我只能说,这是教育的悲哀……
以上随想纯属无聊,呵呵 [quote]原帖由 [i]hrbeu[/i] 于 2007-6-27 11:09 发表 [url=http://www.heubbs.com/redirect.php?goto=findpost&pid=207690&ptid=17361][img]http://www.heubbs.com/images/common/back.gif[/img][/url]
不错
流星做这个1年多了啊,现在应该是这方面专家了
有前途 [/quote]
专家谈不上,也就是闲着无聊的时候编写点小代码玩玩而已。
已经没有刚开始的那种钻研的激情了,呵呵:p
页:
[1]