汇编小程序解析--3D立方体旋转

news/2024/12/22 20:20:24/

汇编小程序解析–3D立方体旋转,源代码如下,是vulture大神于1995年写的,我到现在才基本看懂。

;本程序由国外的Vulture大哥编写,并公布了源码,这个是他95年的一个作品,可以说是在当时是非常成功的!;这个程序是巧妙的利用了坐标的不断变化,从而实现了由星星构成的箱子3D转动!;为了尊重版权,本人未对源码注释进行翻译,这样做也可以让国内的汇编爱好者自己琢磨国外的汇编编程的思维!;编译方法: 1 tasm 3d.asm;           2 tlink 3d.obj;           3 exe2bin 3d.exe 3d.com;本程序是站长精心收集的一个很经典的3D小动画. 站长的x86汇编小站:http://www.x86asm.com ;                                                    永久域名:http://x86asm.yeah.net;==============================================================================;
;                                                                              ;
;   Assembler Program By Vulture.                                              ;
;   3D-system example. Use the following formulas to rotate a point:           ;
;                                                                              ;
;        Rotate around x-axis                                                  ;
;        YT = Y * COS(xang) - Z * SIN(xang) / 256                              ;
;        ZT = Y * SIN(xang) + Z * COS(xang) / 256                              ;
;        Y = YT                                                                ;
;        Z = ZT                                                                ;
;                                                                              ;
;        Rotate around y-axis                                                  ;
;        XT = X * COS(yang) - Z * SIN(yang) / 256                              ;
;        ZT = X * SIN(yang) + Z * COS(yang) / 256                              ;
;        X = XT                                                                ;
;        Z = ZT                                                                ;
;                                                                              ;
;        Rotate around z-axis                                                  ;
;        XT = X * COS(zang) - Y * SIN(zang) / 256                              ;
;        YT = X * SIN(zang) + Y * COS(zang) / 256                              ;
;        X = XT                                                                ;
;        Y = YT                                                                ;
;                                                                              ;
;   Divide by 256 coz we have multiplyd our sin values with 256 too.           ;
;   This example isn't too fast right now but it'll work just fine.            ;
;                                                                              ;
;       Current Date: 6-9-95         Vulture                                   ;
;                                                                              ;
;==============================================================================;IDEAL                           ; Ideal mode
P386                            ; Allow 80386 instructions
JUMPS                           ; Tasm handles out of range jumps (rulez!:))SEGMENT CODE                    ; Code segment starts
ASSUME cs:code,ds:code          ; Let cs and ds point to code segmentORG 100h                        ; Make a .COM fileSTART:                          ; Main programmov     ax,0013h            ; Init vgaint     10hmov     ax,csmov     ds,ax               ; ds points to codesegmentmov     ax,0a000hmov     es,ax               ; es points to vgalea     si,[Palette]        ; Set palettemov     dx,3c8hxor     al,alout     dx,almov     dx,3c9hmov     cx,189*3repz    outsb; === Set some variables ===mov     [DeltaX],1          ; Initial speed of rotationmov     [DeltaY],1          ; Change this and watch whatmov     [DeltaZ],1          ; happens. It's fun!mov     [Xoff],256mov     [Yoff],256          ; Used for calculating vga-posmov     [Zoff],300          ; Distance from viewerMainLoop:call    MainProgram         ; Yep... do it all... ;-)in      al,60h              ; Scan keyboardcmp     al,1                ; Test on ESCAPEjne     MainLoop            ; Continue if not keypressed; === Quit to DOS ===mov     ax,0003h            ; Back to textmodeint     10hlea     dx,[Credits]mov     ah,9int     21hmov     ax,4c00h            ; Return control to DOSint     21h                 ; Call DOS interrupt; === Sub-routines ===PROC WaitVrt                    ; Waits for vertical retrace to reduce "snow"mov     dx,3dah
Vrt:in      al,dxtest    al,8jnz     Vrt                 ; Wait until Verticle Retrace starts
NoVrt:in      al,dxtest    al,8jz      NoVrt               ; Wait until Verticle Retrace endsret                         ; Return to main program
ENDP WaitVrtPROC UpdateAngles
; Calculates new x,y,z angles
; to rotate aroundmov     ax,[XAngle]         ; Load current anglesmov     bx,[YAngle]mov     cx,[ZAngle]add     ax,[DeltaX]         ; Add velocityand     ax,11111111b        ; Range from 0..255mov     [XAngle],ax         ; Update Xadd     bx,[DeltaY]         ; Add velocityand     bx,11111111b        ; Range from 0..255mov     [YAngle],bx         ; Update Yadd     cx,[DeltaZ]         ; Add velocityand     cx,11111111b        ; Range from 0..255mov     [ZAngle],cx         ; Update Zret
ENDP UpdateAnglesPROC GetSinCos
; Needed : bx=angle (0..255)
; Returns: ax=Sin   bx=Cospush    bx                  ; Save angle (use as pointer)shl     bx,1                ; Grab a word so bx=bx*2mov     ax,[SinCos + bx]    ; Get sinepop     bx                  ; Restore pointer into bxpush    ax                  ; Save sine on stackadd     bx,64               ; Add 64 to get cosineand     bx,11111111b        ; Range from 0..255shl     bx,1                ; *2 coz it's a wordmov     ax,[SinCos + bx]    ; Get cosinemov     bx,ax               ; Save it   bx=Cospop     ax                  ; Restore   ax=Sinret
ENDP GetSinCosPROC SetRotation
; Set sine & cosine of x,y,zmov     bx,[XAngle]         ; Grab anglecall    GetSinCos           ; Get the sine&cosinemov     [Xsin],ax           ; Save sinmov     [Xcos],bx           ; Save cosmov     bx,[Yangle]call    GetSinCosmov     [Ysin],axmov     [Ycos],bxmov     bx,[Zangle]call    GetSinCosmov     [Zsin],axmov     [Zcos],bxret
ENDP SetRotationPROC RotatePoint            ; Rotates the point around x,y,z
; Gets original x,y,z values
; This can be done elsewheremovsx   ax,[Cube+si]    ; si = X        (movsx coz of byte)mov     [X],axmovsx   ax,[Cube+si+1]  ; si+1 = Ymov     [Y],axmovsx   ax,[Cube+si+2]  ; si+2 = Zmov     [Z],ax; Rotate around x-axis
; YT = Y * COS(xang) - Z * SIN(xang) / 256
; ZT = Y * SIN(xang) + Z * COS(xang) / 256
; Y = YT
; Z = ZTmov     ax,[Y]mov     bx,[XCos]imul    bx               ; ax = Y * Cos(xang)mov     bp,axmov     ax,[Z]mov     bx,[XSin]imul    bx               ; ax = Z * Sin(xang)sub     bp,ax            ; bp = Y * Cos(xang) - Z * Sin(xang)sar     bp,8             ; bp = Y * Cos(xang) - Z * Sin(xang) / 256mov     [Yt],bpmov     ax,[Y]mov     bx,[XSin]imul    bx               ; ax = Y * Sin(xang)mov     bp,axmov     ax,[Z]mov     bx,[XCos]imul    bx               ; ax = Z * Cos(xang)add     bp,ax            ; bp = Y * SIN(xang) + Z * COS(xang)sar     bp,8             ; bp = Y * SIN(xang) + Z * COS(xang) / 256mov     [Zt],bpmov     ax,[Yt]          ; Switch valuesmov     [Y],axmov     ax,[Zt]mov     [Z],ax; Rotate around y-axis
; XT = X * COS(yang) - Z * SIN(yang) / 256
; ZT = X * SIN(yang) + Z * COS(yang) / 256
; X = XT
; Z = ZTmov     ax,[X]mov     bx,[YCos]imul    bx               ; ax = X * Cos(yang)mov     bp,axmov     ax,[Z]mov     bx,[YSin]imul    bx               ; ax = Z * Sin(yang)sub     bp,ax            ; bp = X * Cos(yang) - Z * Sin(yang)sar     bp,8             ; bp = X * Cos(yang) - Z * Sin(yang) / 256mov     [Xt],bpmov     ax,[X]mov     bx,[YSin]imul    bx               ; ax = X * Sin(yang)mov     bp,axmov     ax,[Z]mov     bx,[YCos]imul    bx               ; ax = Z * Cos(yang)add     bp,ax            ; bp = X * SIN(yang) + Z * COS(yang)sar     bp,8             ; bp = X * SIN(yang) + Z * COS(yang) / 256mov     [Zt],bpmov     ax,[Xt]          ; Switch valuesmov     [X],axmov     ax,[Zt]mov     [Z],ax; Rotate around z-axis
; XT = X * COS(zang) - Y * SIN(zang) / 256
; YT = X * SIN(zang) + Y * COS(zang) / 256
; X = XT
; Y = YTmov     ax,[X]mov     bx,[ZCos]imul    bx               ; ax = X * Cos(zang)mov     bp,axmov     ax,[Y]mov     bx,[ZSin]imul    bx               ; ax = Y * Sin(zang)sub     bp,ax            ; bp = X * Cos(zang) - Y * Sin(zang)sar     bp,8             ; bp = X * Cos(zang) - Y * Sin(zang) / 256mov     [Xt],bpmov     ax,[X]mov     bx,[ZSin]imul    bx               ; ax = X * Sin(zang)mov     bp,axmov     ax,[Y]mov     bx,[ZCos]imul    bx               ; ax = Y * Cos(zang)add     bp,ax            ; bp = X * SIN(zang) + Y * COS(zang)sar     bp,8             ; bp = X * SIN(zang) + Y * COS(zang) / 256mov     [Yt],bpmov     ax,[Xt]          ; Switch valuesmov     [X],axmov     ax,[Yt]mov     [Y],axret
ENDP RotatePointPROC ShowPoint
; Calculates screenposition and
; plots the point on the screenmov     ax,[Xoff]           ; Xoff*X / Z+Zoff = screen xmov     bx,[X]imul    bxmov     bx,[Z]add     bx,[Zoff]           ; Distanceidiv    bxadd     ax,[Mx]             ; Center on screenmov     bp,axmov     ax,[Yoff]           ; Yoff*Y / Z+Zoff = screen ymov     bx,[Y]imul    bxmov     bx,[Z]add     bx,[Zoff]           ; Distanceidiv    bxadd     ax,[My]             ; Center on screenmov     bx,320imul    bxadd     ax,bp               ; ax = (y*320)+xmov     di,axmov     ax,[Z]              ; Get color from Zadd     ax,100d             ; (This piece of code could be improved)mov     [byte ptr es:di],al ; Place a dot with color almov     [Erase+si],di       ; Save position for eraseret
ENDP ShowPointPROC MainProgramcall    UpdateAngles        ; Calculate new anglescall    SetRotation         ; Find sine & cosine of those anglesxor     si,si               ; First 3d-pointmov     cx,MaxPoints
ShowLoop:  call    RotatePoint         ; Rotates the point using above formulascall    ShowPoint           ; Shows the pointadd     si,3                ; Next 3d-pointloop    ShowLoopcall    WaitVrt             ; Wait for retracexor     si,si               ; Starting with point 0xor     al,al               ; Color = 0 = blackmov     cx,MaxPoints
Deletion:mov     di,[Erase+si]       ; di = vgapos old pointmov     [byte ptr es:di],al ; Delete itadd     si,3                ; Next pointloop    Deletionret
ENDP MainProgram; === DATA ===Credits   DB   13,10,"Code by Vulture / Outlaw Triad",13,10,"$"Label SinCos Word       ; 256 values
dw 0,6,13,19,25,31,38,44,50,56
dw 62,68,74,80,86,92,98,104,109,115
dw 121,126,132,137,142,147,152,157,162,167
dw 172,177,181,185,190,194,198,202,206,209
dw 213,216,220,223,226,229,231,234,237,239
dw 241,243,245,247,248,250,251,252,253,254
dw 255,255,256,256,256,256,256,255,255,254
dw 253,252,251,250,248,247,245,243,241,239
dw 237,234,231,229,226,223,220,216,213,209
dw 206,202,198,194,190,185,181,177,172,167
dw 162,157,152,147,142,137,132,126,121,115
dw 109,104,98,92,86,80,74,68,62,56
dw 50,44,38,31,25,19,13,6,0,-6
dw -13,-19,-25,-31,-38,-44,-50,-56,-62,-68
dw -74,-80,-86,-92,-98,-104,-109,-115,-121,-126
dw -132,-137,-142,-147,-152,-157,-162,-167,-172,-177
dw -181,-185,-190,-194,-198,-202,-206,-209,-213,-216
dw -220,-223,-226,-229,-231,-234,-237,-239,-241,-243
dw -245,-247,-248,-250,-251,-252,-253,-254,-255,-255
dw -256,-256,-256,-256,-256,-255,-255,-254,-253,-252
dw -251,-250,-248,-247,-245,-243,-241,-239,-237,-234
dw -231,-229,-226,-223,-220,-216,-213,-209,-206,-202
dw -198,-194,-190,-185,-181,-177,-172,-167,-162,-157
dw -152,-147,-142,-137,-132,-126,-121,-115,-109,-104
dw -98,-92,-86,-80,-74,-68,-62,-56,-50,-44
dw -38,-31,-25,-19,-13,-6Label Cube Byte           ; The 3d pointsc = -35            ; 5x*5y*5z (=125) pointsrept 5b = -35rept 5a = -35rept 5db a,b,ca = a + 20endmb = b + 20endmc = c + 20endmLabel Palette Byte              ; The palette to usedb 0,0,0                 ; 63*3 gray-tintd = 63rept 63db d,d,ddb d,d,ddb d,d,dd = d - 1endmX      DW ?             ; X variable for formula
Y      DW ?
Z      DW ?Xt     DW ?             ; Temporary variable for x
Yt     DW ?
Zt     DW ?XAngle DW 0             ; Angle to rotate around x
YAngle DW 0
ZAngle DW 0DeltaX DW ?             ; Amound Xangle is increased each time
DeltaY DW ?
DeltaZ DW ?Xoff   DW ?
Yoff   DW ?
Zoff   DW ?             ; Distance from viewerXSin   DW ?             ; Sine and cosine of angle to rotate around
XCos   DW ?
YSin   DW ?
YCos   DW ?
ZSin   DW ?
ZCos   DW ?Mx     DW 160            ; Middle of the screen
My     DW 100MaxPoints EQU 125        ; Number of 3d PointsErase  DW MaxPoints DUP (?)     ; Array for deletion screenpointsENDS CODE                       ; End of codesegment
END START                       ; The definite end.... :); You may use this code in your own productions but
; give credit where credit is due. Only lamers steal
; code so try to create your own 3d-engine and use
; this code as an example.
; Thanx must go to Arno Brouwer and Ash for releasing
; example sources.
;
;    Ciao dudoz,
;
;         Vulture / Outlaw Triad

首先,学习一下图形变换的基础知识。

1. 向量绕坐标轴或者原点旋转

旋转的时候,向量的长度不变,方向发生变化。
由二维向量绕原点旋转得知 :
x1 = r * cos a
y1 = r * sin a
得出:
x2 = r * cos ( a + b) = r * cos a * cos b - r * sin a * sin b = x1 * cos b - y1 * sinb
y2 = r * sin ( a + b) = r * sin a * cos b + r * cos a * sin b = x1 * sinb + y1 * cosb
由此得出以下旋转公式(注意矩阵乘法不满足结合律,故两个向量的顺序不能颠倒):

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
注意,网上很多资料都是引用的下图的公式,到底哪个是对的,我需要再考虑一下。
在这里插入图片描述

2. 向量移动

平移得时候,图像或者向量的长度和方向不变,但是位置发生变化。

由:
x2 = x1 + a
y2 = y1 + b
z2 = z1 + c
得如下平移公式:
在这里插入图片描述
注意:平移公式维度从3维上升到4维,因为只有这样,才可以用矩阵乘法表示向量的平移操作,否则,只能用加法来表示向量平移操作。同时,因为平移操作上升了矩阵计算的维度,所以其他的操作,比如旋转、缩放也是用4维矩阵乘法来实现的,这样所有的操作和计算就实现了数学形式上的统一。这也就是齐次坐标的来源。

3. 向量缩小放大

向量或者图像缩放,可以按照几个坐标方向的系数分别缩放,缩放时。
由:
x2 = x1 * a
y2 = y1 * b
z2 = z1 * c
可得如下公式:
在这里插入图片描述
实际上,图像的几何变换通常不是单一的,也就是说经常性的缩放、旋转、平移一起变换。例如先放大2倍,然后旋转45度,然后再缩小0.5倍。那么就可以表示成矩阵乘法串接的形式:
在这里插入图片描述

4. 绕任意点的二维旋转

首先将旋转点移动到原点处,执行如上面所描述的绕原点的旋转,再将旋转点移回到原来的位置。
在这里插入图片描述

4. 绕任意轴的三维旋转
这种旋转又分为2种情况:
旋转轴平行于坐标轴。

将旋转轴平移至与坐标轴重合,旋转,步骤1的逆过程。

旋转住不平行于坐标轴。

将旋转轴平移至原点(如果经过原点则此步骤可省略)
将旋转轴旋转角度c,与z轴重合,向量映射至 XOY 平面
将旋转轴旋转b,旋转至于X轴重合,向量映射至x轴上
绕 X轴旋转 a度
执行步骤3的逆过程
执行步骤2的逆过程
执行步骤1的逆过程
其中,a,b,c分别为向量和x,y,z轴的夹角。

结合此文章可以更明确的理解上述公式:
图像旋转变换


http://www.ppmy.cn/news/51863.html

相关文章

计算机专业毕业生求职选择及思考(干货满满)

这个专栏主要是关于应届生求职工作相关的文章,提供一些建议和思考后续持续更新! 后面章节持续更新 计算机专业毕业生求职的整体总结和概括。 求职时间 首先注意几个求职时间节点: 提前批: 秋招提前批,互联网大厂招…

vue封装公共组件库并发布到npm库详细教程

vue组件封装的原理:利用vue框架提供的api: Vue.use( plugin ),我们需要把封装好组件的项目打包成vue库,并提供install方法,然后发布到npm中。Vue.use( plugin )的时候会自动执行插件中的install方法。 一、组件库代码目录 目录…

适合程序员阅读的有用书籍:

几本适合程序员阅读的有用书籍: 1.《计算机程序设计艺术》(The Art of Computer Programming)是由Donald E. Knuth撰写的一系列著作,是计算机科学领域的经典之作。该系列著作共分为三卷,分别介绍了算法和计算机程序设计的基础知识和技巧。 …

FileZilla密钥登录

使用密码登录非常的方便,但是有的客户的云服务器上是限定只能通过密钥登录。我一般使用命令行的scp命令就可以正常上传,但是对于我一些同事来说,就很不方便。 生成密钥 这个不难,可以参考我之前的文章。 《Mac使用ssh连接远程服…

微电网两阶段鲁棒优化经济调度方法(Python代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

DolphinScheduler 2.0.5详解

文章目录 第一章 DolphinScheduler介绍1.1 关于DolphinScheduler1.2 DolphinScheduler特性1.3 配置建议1.3.1 Linux 操作系统版本要求1.3.2 服务器建议配置1.3.3 生产环境1.3.4 网络要求1.3.5 客户端 Web 浏览器要求 第二章 DolphinScheduler安装部署2.1 安装部署介绍2.2 单机版…

35岁程序员被裁赔偿27万,公司又涨薪让我回去,前提是退还补偿金,能回吗?

在大多数人眼里,35岁似乎都是一道槛,互联网界一直都有着“程序员是吃青春饭”的说法,。 如果在35岁的时候被裁能获得27万的赔偿,公司又涨薪请你回去上班,你会怎么选? 最近,就有一位朋友在网上…

rk3568 适配摄像头 (CIF协议)

rk3568 适配摄像头 (CIF协议) 在RK3568处理器中,支持CIF协议的摄像头可以通过CSI接口连接到处理器,实现视频数据的采集和处理。同时,RK3568还支持多种图像处理算法和编解码器,可以对采集到的视频数据进行实时处理和压缩&#xff…