📄 3d球棍模型.htm
字号:
<BR>sx,sy,sz(实际起点的空间坐标)[由函数"gun_js()"根据起点终点小球坐标以及起点小球的半径算得]
ex,ey,ez(实际终点的空间坐标)[由函数"gun_js()"根据起点终点小球坐标以及终点小球的半径算得]
svx,svy(起点的屏幕显示坐标)[由函数"v_xz()"根据sx,sy,sz的值计算]<BR>evx,evy(终点的屏幕显示坐标)[由函数"v_xz()"根据ex,ey,ez的值计算]
<BR>oy(小棍中点处的空间坐标的y值,用于比较深度)[根据起点终点小球的空间坐标y值计算] 下面以甲烷的数据为例: <BR>
<DIV class=HtmlCode>// 甲烷<BR>function get_data_2() {<BR>//
小球初始化<BR>// 小球数目<BR>sm = 5;<BR>dot = new Array(sm);<BR>for (i=0;
i<sm; i++) {<BR>dot[i] = new Object();<BR>dot[i].x =
0;<BR>dot[i].y = 0;<BR>dot[i].z = 0;<BR>dot[i].vx = 0;<BR>dot[i].vy
= 0;<BR>dot[i].col = 0;<BR>dot[i].r = 5;<BR>}<BR>// 0<BR>dot[0].x =
50;<BR>dot[0].y = 50;<BR>dot[0].z = 50;<BR>dot[0].col = 1;<BR>//
1<BR>dot[1].x = -50;<BR>dot[1].y = -50;<BR>dot[1].z =
50;<BR>dot[1].col = 2;<BR>// 2<BR>dot[2].x = -50;<BR>dot[2].y =
50;<BR>dot[2].z = -50;<BR>dot[2].col = 3;<BR>// 3<BR>dot[3].x =
50;<BR>dot[3].y = -50;<BR>dot[3].z = -50;<BR>dot[3].col = 4;<BR>//
4<BR>dot[4].x = 0;<BR>dot[4].y = 0;<BR>dot[4].z = 0;<BR>dot[4].col =
10;<BR>// 小球初始化完成<BR>// <BR>// 小棍初始化<BR>// 小棍的数目<BR>sm_gun =
4;<BR>gun = new Array(sm_gun);<BR>for (i=0; i<sm_gun; i++)
{<BR>gun[i] = new Object();<BR>gun[i].dot_s = 0;<BR>gun[i].dot_e =
0;<BR>gun[i].sx = 0;<BR>gun[i].sy = 0;<BR>gun[i].sz =
0;<BR>gun[i].ex = 0;<BR>gun[i].ey = 0;<BR>gun[i].ez =
0;<BR>gun[i].oy = 0;<BR>// 屏幕坐标(起点和终点)<BR>gun[i].svx =
0;<BR>gun[i].svy = 0;<BR>gun[i].evx = 0;<BR>gun[i].evy =
0;<BR>}<BR>// 0<BR>gun[0].dot_s = 0;<BR>gun[0].dot_e = 4;<BR>//
1<BR>gun[1].dot_s = 1;<BR>gun[1].dot_e = 4;<BR>// 2<BR>gun[2].dot_s
= 2;<BR>gun[2].dot_e = 4;<BR>// 3<BR>gun[3].dot_s =
3;<BR>gun[3].dot_e = 4;<BR>// 小棍初始化完成<BR>}<BR>//
<BR></DIV>自定义函数和主调程序段:(代码位于主场景第2帧)<BR>gun_js()
[为达到消隐的目的,小棍的起点和终点必须是在球的表面上,而不是球的中心。本函数就是根据起点小球和终点小球的空间坐标来计算小棍实际的起点和终点的空间坐标。另外还计算了小棍中点处的空间坐标y值,这个值用于比较深度,也是为消隐作准备]
<BR>scale(s) [整体缩放函数,本程序中未使用] <BR>rotate(xa, ya)
[旋转函数,xa是绕x轴旋转的角度值,而ya是绕z轴旋转的角度值,并不是y轴,这是变量名书写不当造成的,未做修改]
<BR>v_xz(d) [本函数将小球,小棍的空间坐标换算成屏幕显示坐标,也就是将那些坐标点投影到xz平面上,d是视点到xz平面的距离]
<BR>get_deeps()
[将各小球,各小棍的深度值取出,放到一个新的数组中,并同时记录小球或小棍的编号。由于小球,小棍的编号都是从0开始,为了区分小球和小棍,特将小棍的编号加上1000后再存储。执行此函数后得到一个存有深度值和对应编号的数组"deeps[sm+sm_gun]",后面进行消隐显示时就方便了]
<BR>get_v()
[消隐显示,从最深度最大者开始,逐个显示小球或小棍。从数组"deeps[sm+sm_gun]"中找出y值最小者,即深度最大者,并记录相应的编号,然后根据编号是>=1000还是<1000即可判断它是小棍还是小球,然后提取相应编号的小棍或小球的屏幕显示坐标值,对于小球而言,还须提取其颜色值和深度值,以便于显示不同颜色,不同大小,不同模糊程度。]
<BR>cl_all() [清除所有用于显示小球和小棍的MC,本函数在按钮中用到]<BR>
<DIV class=HtmlCode>stop();<BR>// 原点坐标<BR>ox = 200;<BR>oy =
200;<BR>// 取得点集<BR>get_data(3);<BR>// 小棍的起点,终点,深度计算<BR>function
gun_js() {<BR>var i, a, b, ar, br, dxy, dxz;<BR>var ax, ay, az, bx,
by, bz, dx, dy, dz;<BR>for (i=0; i<sm_gun; i++) {<BR>a =
gun[i].dot_s;<BR>ar = dot[a].r;<BR>ax = dot[a].x;<BR>ay =
dot[a].y;<BR>az = dot[a].z;<BR>// <BR>b = gun[i].dot_e;<BR>br =
dot[b].r;<BR>bx = dot[b].x;<BR>by = dot[b].y;<BR>bz =
dot[b].z;<BR>// <BR>dx = bx-ax;<BR>dy = by-ay;<BR>dz = bz-az;<BR>//
dxy,dxz分别是a,b投影到xy,xz面上后的距离<BR>dxy = Math.sqrt(dx*dx+dy*dy);<BR>dxz
= Math.sqrt(dx*dx+dz*dz);<BR>// 绘图时的起点坐标<BR>gun[i].sx =
(dxy-br)*dx/dxy+ax;<BR>gun[i].sy = (dxy-br)*dy/dxy+ay;<BR>gun[i].sz
= (dxz-br)*dz/dxz+az;<BR>// 绘图时的终点坐标<BR>gun[i].ex =
-(dxy-ar)*dx/dxy+bx;<BR>gun[i].ey =
-(dxy-ar)*dy/dxy+by;<BR>gun[i].ez = -(dxz-ar)*dz/dxz+bz;<BR>//
小棍中点处的y值,用以比较深度<BR>gun[i].oy = (ay+by)/2;<BR>}<BR>}<BR>// <BR>//
缩放函数,s为缩放系数<BR>function scale(s) {<BR>var i;<BR>for (i=0; i<sm;
i++) {<BR>dot[i].x *= s;<BR>dot[i].y *= s;<BR>dot[i].z *=
s;<BR>}<BR>}<BR>// 物体旋转,xa,ya均为角度值<BR>function rotate(xa, ya)
{<BR>var i, k;<BR>var rad = Math.PI/180;<BR>xa *= rad;<BR>ya *=
rad;<BR>var sin_xa = Math.sin(xa);<BR>var cos_xa =
Math.cos(xa);<BR>var sin_ya = Math.sin(ya);<BR>var cos_ya =
Math.cos(ya);<BR>var px, py, pz, tempz;<BR>for (i=0; i<sm; i++)
{<BR>px = dot[i].x;<BR>py = dot[i].y;<BR>pz = dot[i].z;<BR>tempz =
(py*cos_ya)-(px*sin_ya);<BR>dot[i].x =
(py*sin_ya)+(px*cos_ya);<BR>dot[i].y =
(pz*sin_xa)+(tempz*cos_xa);<BR>dot[i].z =
(pz*cos_xa)-(tempz*sin_xa);<BR>}<BR>}<BR>//
将物体投影到xz平面,d为视点到投影面的距离<BR>function v_xz(d) {<BR>var i, k;<BR>//
处理小球坐标<BR>for (i=0; i<sm; i++) {<BR>k =
1-dot[i].y/d;<BR>dot[i].vx = dot[i].x/k;<BR>dot[i].vy =
-dot[i].z/k;<BR>}<BR>// <BR>// 处理小棍坐标<BR>for (i=0; i<sm_gun; i++)
{<BR>// 小棍起点<BR>k = 1-gun[i].sy/d;<BR>gun[i].svx =
gun[i].sx/k;<BR>gun[i].svy = -gun[i].sz/k;<BR>// 小棍终点<BR>k =
1-gun[i].ey/d;<BR>gun[i].evx = gun[i].ex/k;<BR>gun[i].evy =
-gun[i].ez/k;<BR>}<BR>}<BR>// 提取深度值,即y值(包括小球和小棍)<BR>function
get_deeps() {<BR>var i, sm_all = sm+sm_gun;<BR>deeps = new
Array(sm);<BR>// 提取小球的y值并记录其编号<BR>for (i=0; i<sm; i++)
{<BR>deeps[i] = new Object();<BR>deeps[i].num = i;<BR>deeps[i].y =
dot[i].y;<BR>}<BR>// 提取小棍的y值并记录其编号<BR>for (i=sm; i<sm_all; i++)
{<BR>deeps[i] = new Object();<BR>//
为节约空间,将小棍的编号+1000用以与小球相区分,而不再另作标记<BR>deeps[i].num =
(i-sm)+1000;<BR>deeps[i].y = gun[i-sm].oy;<BR>}<BR>}<BR>// <BR>//
从最大深度开始,显示每个小球或小棍<BR>function get_v() {<BR>//
根据各小球坐标值计算棍的坐标值(包括起点和终点)<BR>gun_js();<BR>//
透视(将物体投影到xz平面,视点离zx面为200像素).<BR>v_xz(200);<BR>//
提取深度值,即y值,放入数组vdot中<BR>get_deeps();<BR>var i, a, j = 5;<BR>var
min_y, min_n, min_m;<BR>// 当还有1个以上未显示时<BR>while (deeps.length>0)
{<BR>// 先假设第一个就是最小y值(即最大深度)<BR>min_y = deeps[0].y;<BR>min_n =
0;<BR>min_m = deeps[0].num;<BR>// 找出未显示的球或棍中,y值最小的<BR>for (i=1;
i<deeps.length; i++) {<BR>if (deeps[i].y<min_y) {<BR>min_y =
deeps[i].y;<BR>min_n = i;<BR>min_m = deeps[i].num;<BR>}<BR>}<BR>//
显示找到的y值最小的球或棍(编号小于1000的都是球,否则就是棍)<BR>if (min_m<1000) {<BR>a =
this.attachMovie("dot", "dot"+min_m, j++);<BR>a._x =
dot[min_m].vx+ox;<BR>a._y = dot[min_m].vy+oy;<BR>a._xscale =
100-(200-dot[min_m].y)/10;<BR>a._yscale = a._xscale;<BR>//
制造雾气效果<BR>a.wuqi._alpha = (200-dot[min_m].y)/5;<BR>//
dot[i][5]保存的是颜色信息<BR>a.gotoAndStop(dot[min_m].col);<BR>} else
{<BR>min_m -= 1000;<BR>// 创建一个空MC,并画一直线作为小棍<BR>a =
this.createEmptyMovieClip("gun"+min_m, j++);<BR>a.lineStyle(3,
0xaaaaaa, 50);<BR>a.moveTo((gun[min_m].svx+ox),
(gun[min_m].svy+oy));<BR>a.lineTo((gun[min_m].evx+ox),
(gun[min_m].evy+oy));<BR>}<BR>//
从vdot中删去最小点,以便于下一轮寻找min点<BR>deeps.splice(min_n, 1);<BR>}<BR>}<BR>//
<BR>// <BR>// 清除所有小球和小棍<BR>function cl_all() {<BR>var i,a;<BR>for
(i=0; i<sm; i++) {<BR>a =
this["dot"+i];<BR>removeMovieClip(a);<BR>}<BR>for (i=0; i<sm_gun;
i++) {<BR>a = this["gun"+i];<BR>removeMovieClip(a);<BR>}<BR>}<BR>//
<BR>// 主调程序段:<BR>this.onEnterFrame = function() {<BR>//
绕x轴的转角<BR>theta_x = (_ymouse-oy)/20;<BR>// 绕z轴的转角<BR>theta_z =
(_xmouse-ox)/20;<BR>// 旋转物体<BR>rotate(theta_x, theta_z);<BR>//
显示<BR>get_v();<BR>};<BR>//
<BR></DIV>可能不少人觉得上面的代码很吓人,不要急。<BR>其实我在一年前对3d的东东也是一无所知,后来看到有人用Flash搞分子结构式,于是我也开始构思,谁让我是搞化学的呢,看了些图形学的书,可是数学基础不好,看了也不太明了,直到前几天,总算勉强把程序搞出来了,至今都还有些地方不太明了,最开始只有小球,不知道怎么解决小棍的消隐问题,后来又慢慢改进,扩充功能,最后就变成这个样子了。最开始时照着书上的方法用矩阵变换做,后来觉得矩阵计算效率低,就直接用变换公式。对于消隐,书上是将深度进行排序,而我是找出深度最大值,用完后即刻删除,好在Flash里面的"数组"不是什么真数组,元素是可以删除的。另外数据的结构也是经过了多次修改和扩充,现在觉得有些太浪费空间,也懒得管了。<BR><BR>综上,这个程序不是一步到位的,是走了很多弯路才实现的,看不懂的人不要急,先理解大致思路,然后逐步细分,各个击破。<BR>扩充功能
<BR>1。提供3种显示方式:V1--鼠标跟随,V2--绕Z轴匀速旋转,V3--固定不动<BR>2。可以进行编辑操作:点击小球可选中小球,点击右下角的空白按钮可取消选择。在输入框中输入数据,然后点击一个操作按钮:dx,dy,dz分别是将小球的x,y,z值加上输入值;X,Y,Z分别是将小球的x,y,z值直接变为输入值;Rx,Rz则是分别将输入值作为x,z轴的旋转角。
<BR><IMG src="3D球棍模型.files/swf.gif" border=0> <A
href="http://www.flash8.net/bbs/UploadFile/2004-4/200443155228614.swf"
target=_blank><FONT color=#373e55>点击浏览该文件</FONT></A>
<BR>源文件:<BR><IMG src="3D球棍模型.files/fla.gif" border=0> <A
href="http://www.flash8.net/bbs/viewFile.asp?Boardid=10&ID=107509"
target=_blank><FONT
color=#373e55>点击浏览该文件</FONT></A><BR><B>优化之后<BR></B>对消隐部分作了根本性的改变,使执行效率有大大提高。另外,小棍也添加了雾化效果。
源文件(2004版)中有很详细的注释。 <BR><IMG src="3D球棍模型.files/swf.gif" border=0> <A
href="http://www.flash8.net/bbs/UploadFile/2004-9/200492112675.swf"
target=_blank><FONT color=#373e55>点击浏览该文件</FONT></A><BR><FONT
color=#373e55><IMG src="3D球棍模型.files/fla.gif" border=0></FONT> <A
href="http://www.flash8.net/bbs/viewFile.asp?Boardid=10&ID=156490"
target=_blank><FONT color=#373e55>点击浏览该文件</FONT></A>
</TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=0 cellPadding=0 width=778 align=center border=0>
<TBODY>
<TR>
<TD vAlign=top bgColor=#ffffff>
<DIV align=center></DIV>
<TABLE cellSpacing=0 cellPadding=8 width=550 align=center border=0>
<TBODY>
<TR>
<TD>
<DIV align=left><SPAN class=style1>责任编辑:uufeng</SPAN>
</DIV></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=0 cellPadding=0 width=778 align=center border=0>
<TBODY>
<TR>
<TD vAlign=top bgColor=#ffffff>
<TABLE cellSpacing=0 cellPadding=0 width="100%" align=center border=0>
<TBODY>
<TR>
<TD bgColor=#bbbbbb height=2></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD bgColor=#f6f6f6>
<TABLE cellSpacing=0 cellPadding=0 width=580 align=center
border=0><TBODY>
<TR>
<TD class=style1 width=280 height=30 ?>上一篇: <A
href="http://www2.flash8.net/teach/2012.htm">一个遮罩效果</A></TD>
<TD>下一篇: <A
href="http://www2.flash8.net/teach/2014.htm">读取XML中的内容(终极篇)</A></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=0 cellPadding=0 width="100%" align=center border=0>
<TBODY>
<TR>
<TD bgColor=#bbbbbb height=2></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD vAlign=top width=380>
<TABLE cellSpacing=0 cellPadding=0 width=380 align=center
border=0><TBODY>
<TR>
<TD>
<TABLE cellSpacing=0 cellPadding=0 width=203 border=0>
<TBODY>
<TR>
<TD width=122><IMG height=32 alt=""
src="3D球棍模型.files/gbook_school.gif" width=122 border=0
name=gbook2_r2_c1></TD>
<TD> </TD></TR></TBODY></TABLE></TD></TR>
<TR>
<TD background=3D球棍模型.files/gbook2_r3_c1.gif height=9></TD></TR>
<TR>
<TD vAlign=top>
<P align=center>没有相关教材 </P></TD></TR></TBODY></TABLE></TD>
<TD width=10 background=3D球棍模型.files/linebg2.gif> </TD>
<TD vAlign=top><A name=gbook></A><IFRAME
src="3D球棍模型.files/gbook_teach2.htm" frameBorder=0 width=380
scrolling=no height=320></IFRAME></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=0 cellPadding=0 width="100%" align=center border=0>
<TBODY>
<TR>
<TD background=3D球棍模型.files/linebg3.gif
height=8></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE>
<SCRIPT language=JavaScript src="3D球棍模型.files/end.js"></SCRIPT>
</BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -