1 ;THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
2 ;SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
3 ;END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
4 ;ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
5 ;IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
6 ;SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
7 ;FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
8 ;CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
9 ;AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
10 ;COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
12 ; $Source: /cvs/cvsroot/d2x/maths/vecmata.asm,v $
15 ; $Date: 2001-10-31 07:41:54 $
17 ; Source for vector/matrix library
19 ; $Log: not supported by cvs2svn $
20 ; Revision 1.2 2001/10/19 09:34:02 bradleyb
21 ; Changed __ENV_LINUX__ to __linux__
23 ; Revision 1.1.1.1 2001/01/19 03:29:58 bradleyb
26 ; Revision 1.1.1.1 1999/06/14 22:13:33 donut
27 ; Import of d1x 1.37 source.
29 ; Revision 1.54 1995/01/31 00:14:50 matt
30 ; Took out int3 from dotprod overflow, since it saturates now
32 ; Revision 1.53 1994/12/14 18:29:33 matt
33 ; Made dotprod overflow check stay in, and return saturated value
35 ; Revision 1.52 1994/12/14 12:34:13 matt
36 ; Disabled now-unused vector_2_matrix_norm()
38 ; Revision 1.51 1994/12/13 16:55:13 matt
39 ; Ripped out optimization from last version, which was bogus
41 ; Revision 1.50 1994/12/13 14:55:18 matt
42 ; Use quick normalize in a couple of places where it was safe to do so
44 ; Revision 1.49 1994/12/13 14:44:12 matt
45 ; Added vm_vector_2_matrix_norm()
47 ; Revision 1.48 1994/12/13 13:26:49 matt
48 ; Fixed overflow check
50 ; Revision 1.47 1994/12/03 15:39:54 matt
51 ; Gracefully handle some vector_2_matrix problems
53 ; Revision 1.46 1994/11/19 17:15:05 matt
54 ; Assemble out some code not used in DESCENT
56 ; Revision 1.45 1994/11/17 11:41:05 matt
57 ; Put handling in extract_angles_from_matrix to deal with bad matrices
59 ; Revision 1.44 1994/11/16 11:48:10 matt
60 ; Added error checking to vm_extract_angles_matrix()
62 ; Revision 1.43 1994/09/19 22:00:10 matt
63 ; Fixed register trash
65 ; Revision 1.42 1994/09/11 19:23:05 matt
66 ; Added vm_vec_normalized_dir_quick()
68 ; Revision 1.41 1994/08/14 13:28:38 matt
69 ; Put in check for zero-length vector in extract angles
71 ; Revision 1.40 1994/07/19 18:52:53 matt
72 ; Added vm_vec_normalize_quick() and vm_vec_copy_normalize_quick()
74 ; Revision 1.39 1994/06/16 18:24:22 matt
75 ; Added vm_vec_mag_quick()
77 ; Revision 1.38 1994/06/10 23:18:38 matt
78 ; Added new code for vm_vec_ang_2_matrix() which may be better, but may
81 ; Revision 1.37 1994/05/22 18:17:29 mike
82 ; Optimize vm_vec_dist_quick, using jns in place of abs_eax.
84 ; Revision 1.36 1994/05/19 12:07:04 matt
85 ; Fixed globals and macros and added a constant
87 ; Revision 1.35 1994/05/19 09:19:00 matt
88 ; Made vm_vec_normalized_dir() return mag of vector
90 ; Revision 1.34 1994/05/18 22:28:01 matt
91 ; Added function vm_vec_normalized_dir()
92 ; Added C macros IS_ZERO_VEC(), vm_vec_zero(), and vm_set_identity()
93 ; Added C global static vars vmd_zero_vector & vmd_identity_matrix
95 ; Revision 1.33 1994/05/18 21:44:16 matt
97 ; vm_extract_angles_vector()
98 ; vm_extract_angles_vector_normalized()
99 ; vm_vec_copy_normalize()
101 ; Revision 1.32 1994/05/13 12:41:51 matt
102 ; Added new function, vm_vec_dist_quick(), which does an approximation.
104 ; Revision 1.31 1994/05/04 17:41:31 mike
105 ; Comment out debug_brk on null vector.
107 ; Revision 1.30 1994/04/15 21:41:31 matt
108 ; Check for foward vector straigt up in extract angles routine
110 ; Revision 1.29 1994/03/30 15:45:05 matt
111 ; Added two functions, vm_vec_scale_add() & vm_vec_scale_add2()
113 ; Revision 1.28 1994/02/26 19:23:35 matt
114 ; Do an int3 when we get a null vector when computing surface normal
116 ; Revision 1.27 1994/02/10 18:29:45 matt
117 ; Changed 'if DEBUG_ON' to 'ifndef NDEBUG'
119 ; Revision 1.26 1994/02/10 18:28:55 matt
120 ; Fixed bugs in extract angles function
122 ; Revision 1.25 1994/01/31 22:46:07 matt
123 ; Added vm_extract_angles_matrix() function
125 ; Revision 1.24 1994/01/30 19:29:55 matt
126 ; Put in debug_brk when vm_vec_2_matrix got zero-length vector
128 ; Revision 1.23 1994/01/25 15:27:59 matt
129 ; Added debugging check for dotprod overflow
131 ; Revision 1.22 1994/01/24 11:52:59 matt
132 ; Added checking for dest==src for several functions where this is not allowed
134 ; Revision 1.21 1994/01/19 23:13:02 matt
135 ; Fixed bug in vm_vec_ang_2_matrix()
137 ; Revision 1.20 1994/01/04 12:33:43 mike
138 ; Prevent divide overflow in vm_vec_scale2
140 ; Revision 1.19 1993/12/21 19:46:26 matt
141 ; Added function vm_dist_to_plane()
143 ; Revision 1.18 1993/12/13 17:26:23 matt
144 ; Added vm_vec_dist()
146 ; Revision 1.17 1993/12/02 12:43:39 matt
147 ; New functions: vm_vec_copy_scale(), vm_vec_scale2()
149 ; Revision 1.16 1993/10/29 22:39:29 matt
150 ; Changed matrix order, making direction vectors the rows
152 ; Revision 1.15 1993/10/29 18:06:01 matt
153 ; Fixed vm_vector_2_matrix() bug when forward vector was straight down
155 ; Revision 1.14 1993/10/26 18:51:26 matt
156 ; Fixed some register trashes in vm_vec_ang_2_matrix()
158 ; Revision 1.13 1993/10/25 11:49:37 matt
159 ; Made vm_vec_delta_ang() take optional forward vector to return signed delta
161 ; Revision 1.12 1993/10/20 01:09:42 matt
162 ; Added vm_vec_delta_ang(), vm_vec_delta_ang_norm(), and vm_vec_ang_2_matrix()
164 ; Revision 1.11 1993/10/17 17:03:08 matt
165 ; vm_vector_2_matrix() now takes optional right vector
167 ; Revision 1.10 1993/10/10 18:11:42 matt
168 ; Changed angles_2_matrix so that heading & bank rotate in the
169 ; correct directions.
171 ; Revision 1.9 1993/09/30 16:17:59 matt
172 ; Fixed bug in vector_2_matrix() by adding another normalize
174 ; Revision 1.8 1993/09/29 10:51:58 matt
175 ; Fixed bad register trashes in crossprod, perp, & normal
177 ; Revision 1.7 1993/09/28 12:16:46 matt
178 ; Fixed bugs in cross product
179 ; Added func vm_vector_2_matrix()
181 ; Revision 1.6 1993/09/24 21:19:37 matt
182 ; Added vm_vec_avg() and vm_vec_avg4()
184 ; Revision 1.5 1993/09/20 18:15:07 matt
185 ; Trap zero-length vectors in vm_vec_normalize(), vm_vec_perp(), and vm_vec_normal()
187 ; Revision 1.4 1993/09/20 14:56:43 matt
188 ; Fixed bug in vm_vec_normal(), made that routine normalize the results,
189 ; and added new function vm_vec_perp().
191 ; Revision 1.3 1993/09/20 10:12:06 mike
194 ; Revision 1.2 1993/09/17 11:10:33 matt
195 ; Added vm_vec_add2() and vm_vec_sub2(), which take 2 args (dest==src0)
197 ; Revision 1.1 1993/09/16 20:10:24 matt
208 ; Cater for linux ELF compilers which don't prefix underscores...
210 %define _vmd_zero_vector vmd_zero_vector
211 %define _vmd_identity_matrix vmd_identity_matrix
213 %define _vm_vec_add vm_vec_add
214 %define _vm_vec_sub vm_vec_sub
215 %define _vm_vec_add2 vm_vec_add2
216 %define _vm_vec_sub2 vm_vec_sub2
217 %define _vm_vec_avg vm_vec_avg
218 %define _vm_vec_scale vm_vec_scale
219 %define _vm_vec_copy_scale vm_vec_copy_scale
220 %define _vm_vec_scale2 vm_vec_scale2
221 %define _vm_vec_scale_add vm_vec_scale_add
222 %define _vm_vec_scale_add2 vm_vec_scale_add2
223 %define _vm_vec_mag vm_vec_mag
224 %define _vm_vec_dist vm_vec_dist
225 %define _vm_vec_mag_quick vm_vec_mag_quick
226 %define _vm_vec_dist_quick vm_vec_dist_quick
227 %define _vm_vec_normalize vm_vec_normalize
228 %define _vm_vec_normalize_quick vm_vec_normalize_quick
229 %define _vm_vec_normalized_dir vm_vec_normalized_dir
230 %define _vm_vec_normalized_dir_quick vm_vec_normalized_dir_quick
231 %define _vm_vec_copy_normalize vm_vec_copy_normalize
232 %define _vm_vec_copy_normalize_quick vm_vec_copy_normalize_quick
233 %define _vm_vec_dotprod vm_vec_dotprod
234 %define _vm_vec_crossprod vm_vec_crossprod
235 %define _vm_vec_perp vm_vec_perp
236 %define _vm_vec_normal vm_vec_normal
237 %define _vm_vec_rotate vm_vec_rotate
238 %define _vm_vec_delta_ang vm_vec_delta_ang
239 %define _vm_vec_delta_ang_norm vm_vec_delta_ang_norm
240 %define _vm_vector_2_matrix vm_vector_2_matrix
241 %define _vm_vec_ang_2_matrix vm_vec_ang_2_matrix
242 %define _vm_angles_2_matrix vm_angles_2_matrix
243 %define _vm_transpose_matrix vm_transpose_matrix
244 %define _vm_copy_transpose_matrix vm_copy_transpose_matrix
245 %define _vm_matrix_x_matrix vm_matrix_x_matrix
250 ;temporary vectors for surface normal calculation
260 ;sine & cosine values for angles_2_matrix
268 global _vmd_zero_vector,_vmd_identity_matrix
270 ;These should never be changed!
274 _vmd_identity_matrix:
281 extern fix_sincos_asm
284 ; calling convention is arguments on stack from right to left,
285 ; eax,ecx,edx possibly destroyed, ebx,esi,edi,ebp preserved,
286 ; caller removes arguments.
293 global _vm_vec_copy_scale
294 global _vm_vec_scale2
295 global _vm_vec_scale_add
296 global _vm_vec_scale_add2
299 global _vm_vec_mag_quick
300 global _vm_vec_dist_quick
301 global _vm_vec_normalize
302 global _vm_vec_normalize_quick
303 global _vm_vec_normalized_dir
304 global _vm_vec_normalized_dir_quick
305 global _vm_vec_copy_normalize
306 global _vm_vec_copy_normalize_quick
307 global _vm_vec_dotprod
308 global _vm_vec_crossprod
310 global _vm_vec_normal
311 global _vm_angles_2_matrix
312 global _vm_vec_rotate
313 global _vm_vec_delta_ang
314 global _vm_vec_delta_ang_norm
315 global _vm_transpose_matrix
316 global _vm_copy_transpose_matrix
317 global _vm_matrix_x_matrix
318 global _vm_vector_2_matrix
319 global _vm_vec_ang_2_matrix
352 ; offsets in fixang struct (packed)
366 ;vector offsets in matrix
371 ; vec *vm_vec_add(vec *dest, vec *src1, vec *src2);
389 ; vec *vm_vec_sub(vec *dest, vec *src1, vec *src2);
407 ; vec *vm_vec_add2(vec *dest, vec *src);
421 ; vec *vm_vec_sub2(vec *dest, vec *src);
435 ; vec *vm_vec_avg(vec *dest, vec *src1, vec *src2);
454 ; vec *vm_vec_scale(vec *dest, fix scale);
472 ; vec *vm_vec_copy_scale(vec *dest, vec *src, fix scale);
493 ; vec *vm_vec_scale_add(vec *dest, vec *src1, vec *src2, fix scale);
495 ; dest=src1+src2*scale
518 ; vec *vm_vec_scale_add2(vec *dest, vec *src, fix scale);
539 ; vec *vm_vec_scale2(vec *dest, fix n, fix d);
564 ;compute magnitude of vector. takes esi=vector, returns eax=mag
591 ;compute the distance between two points. (does sub and mag)
613 call quad_sqrt_asm ; asm version, takes eax,edx
620 ;computes an approximation of the magnitude of a vector
621 ;uses dist = largest + next_largest*3/8 + smallest*3/16
645 mag_quick_eax_ebx_ecx:
650 no_swap_ab: cmp ebx,ecx
657 do_add: sar ebx,2 ; b*1/4
659 add ebx,ecx ; b*1/4 + c*1/8
660 add eax,ebx ;a + b*1/4 + c*1/8
661 sar ebx,1 ; b*1/8 + c*1/16
662 add eax,ebx ;a + b*3/4 + c*3/16
669 ;computes an approximation of the distance between two points.
670 ;uses dist = largest + next_largest*3/8 + smallest*3/16
697 jmp mag_quick_eax_ebx_ecx
700 ;return the normalized direction vector between two points
701 ;dest = normalized(end - start).
702 ;takes edi=dest, esi=endpoint, ebx=startpoint. Returns mag of dir vec
703 ;NOTE: the order of the parameters matches the vector subtraction
704 _vm_vec_normalized_dir:
736 mov ecx,eax ;mag in ecx
755 ;normalize a vector in place.
763 jmp vm_vec_copy_normalize_nopar
765 ;normalize a vector. takes edi=dest, esi=vector
766 ;returns ecx=mag of source vec
767 _vm_vec_copy_normalize:
773 vm_vec_copy_normalize_nopar:
792 mov ecx,eax ;mag in ecx
810 ;normalize a vector in place.
812 _vm_vec_normalize_quick:
817 jmp vm_vec_copy_normalize_quick_nopar
819 ;save as vm_vec_normalized_dir, but with quick sqrt
820 ;takes dest, endpoint, startpoint. Returns mag of dir vec
821 _vm_vec_normalized_dir_quick:
835 jmp vm_vec_copy_normalize_quick_nopar
839 _vm_vec_copy_normalize_quick:
845 vm_vec_copy_normalize_quick_nopar:
847 call _vm_vec_mag_quick
850 mov ecx,eax ;mag in ecx
868 ;compute dot product of two vectors. takes esi,edi=vectors, returns eax=dotprod
893 ;ifndef NDEBUG ;check for overflow
894 ;always do overflow check, and return saturated value
895 sar edx,16 ;get real sign from high word
897 cdq ;get sign of our result
898 cmp bx,dx ;same sign?
900 ;;debug_brk 'overflow in vm_vec_dotprod'
902 or ebx,ebx ;check desired sign
913 ;computes cross product of two vectors.
914 ;Note: this magnitude of the resultant vector is the
915 ;product of the magnitudes of the two source vectors. This means it is
916 ;quite easy for this routine to overflow and underflow. Be careful that
918 ; takes dest, src vectors
930 break_if e,'crossprod: dest==src0'
932 break_if e,'crossprod: dest==src1'
944 %ifndef NDEBUG ;check for overflow
946 cdq ;get sign of result
947 shr ebx,16 ;get high 16 of quad result
948 cmp dx,bx ;sign extension the same?
949 break_if ne,'overflow in crossprod'
962 %ifndef NDEBUG ;check for overflow
964 cdq ;get sign of result
965 shr ebx,16 ;get high 16 of quad result
966 cmp dx,bx ;sign extension the same?
967 break_if ne,'overflow in crossprod'
980 %ifndef NDEBUG ;check for overflow
982 cdq ;get sign of result
983 shr ebx,16 ;get high 16 of quad result
984 cmp dx,bx ;sign extension the same?
985 break_if ne,'overflow in crossprod'
989 mov eax,ebp ;return dest in eax
998 ;computes surface normal from three points. takes ebx=dest, eax,esi,edi=vecs
999 ;returns eax=dest. Result vector is normalized.
1001 push dword [esp+16+00];src2
1002 push dword [esp+12+04];src1
1003 push dword [esp+08+08];src0
1004 push dword [esp+04+12];dest
1005 call _vm_vec_perp ;get unnormalized
1008 call _vm_vec_normalize
1013 ;make sure a vector is reasonably sized to go into a cross product
1014 ;takes vector in esi
1015 ;trashes eax,ebx,cl,edx
1028 xor cl,cl ;init shift count
1030 test ebx,0fffc0000h ;too big
1032 check_4_down: test ebx,000f00000h
1037 check_2_down: test ebx,0fffc0000h
1044 sar dword [esi+4],cl
1045 sar dword [esi+8],cl
1049 not_too_big: test ebx,0ffff8000h
1051 check_4_up: test ebx,0fffff000h
1056 check_2_up: test ebx,0ffff8000h
1063 sal dword [esi+4],cl
1064 sal dword [esi+8],cl
1069 ; debug_brk commented out by mk on 05/04/94
1070 ;** debug_brk "null vector in check_vec"
1074 ;computes surface normal from three points. takes ebx=dest, eax,esi,edi=vecs
1075 ;returns eax=dest. Result vector is NOT normalized, but this routine does
1076 ;make an effort that cross product does not overflow or underflow
1082 mov ebx,[esp+20] ;src0
1083 mov ecx,[esp+24] ;src1
1084 mov edx,[esp+28] ;src2
1088 %assign i 0 ;tempv1=src2-src1
1095 %assign i 0 ;tempv0=src1-src0
1102 ; esi=tempv0, edi=tempv1
1103 call check_vec ;make sure reasonable value
1105 call check_vec ;make sure reasonable value
1106 ; edi=tempv0, esi=tempv1
1109 push dword [esp+16+8] ;dest
1110 call _vm_vec_crossprod
1119 ;compute a rotation matrix from three angles. takes edi=dest matrix,
1120 ;esi=angles vector. returns dest matrix.
1121 _vm_angles_2_matrix:
1125 mov edi,[esp+16];dest
1126 mov esi,[esp+20];angles
1128 ;get sines & cosines
1144 ;alternate entry point with sines & cosines already computed.
1145 ;Note all the registers already pushed.
1148 ;now calculate the 9 elements
1152 mov ecx,eax ;save sbsh
1157 mov esi,eax ;save cbch
1159 mov [edi+m1],eax ;m1=cbch+sbspsh
1161 mov eax,esi ;get cbch
1163 add eax,ecx ;add sbsh
1164 mov [edi+m8],eax ;m8=sbsh+cbchsp
1169 mov ecx,eax ;save cbsh
1174 mov esi,eax ;save sbch
1176 mov [edi+m2],ebx ;m2=cbshsp-sbch
1178 mov eax,esi ;get sbch
1180 sub eax,ecx ;sub from cbsh
1181 mov [edi+m7],eax ;m7=sbchsp-cbsh
1186 mov [edi+m3],eax ;m3=shcp
1190 mov [edi+m4],eax ;m4=sbcp
1194 mov [edi+m5],eax ;m5=cbcp
1198 mov [edi+m6],eax ;m6=-sp
1202 mov [edi+m9],eax ;m9=chcp
1221 ;create a rotation matrix from one or two vectors.
1222 ;requires forward vec, and assumes zero bank if up & right vecs==NULL
1223 ;up/right vector need not be exactly perpendicular to forward vec
1224 ;takes edi=matrix, esi=forward vec, eax=up vec, ebx=right vec.
1225 ;returns edi=matrix. trashes eax,ebx,esi
1226 ;Note: this routine loses precision as the forward vector approaches
1227 ;straigt up or down (I think)
1228 _vm_vector_2_matrix:
1233 mov esi,[esp+20];fvec
1234 mov eax,[esp+24];uvec
1235 mov ebx,[esp+28];rvec
1239 break_if z,"vm_vector_2_matrix: forward vec cannot be NULL!"
1242 or eax,eax ;up vector present?
1243 jnz near use_up_vec ;..yep
1245 or ebx,ebx ;right vector present?
1246 jz near just_forward_vec ;..nope
1248 push edi ;save matrix
1252 call _vm_vec_copy_normalize
1259 call _vm_vec_copy_normalize
1264 push dword xvec;src1
1265 push dword zvec;src0
1266 push dword yvec;dest
1267 call _vm_vec_crossprod ;get y = z cross x
1270 ;normalize new perpendicular vector
1271 push eax ;get new vec (up) in esi
1272 call _vm_vec_normalize
1277 ;now recompute right vector, in case it wasn't entirely perpendiclar
1279 push dword zvec;src1
1280 push dword yvec;src0
1281 push dword xvec;dest
1282 call _vm_vec_crossprod ;x = y cross z
1285 pop edi ;get matrix back
1287 jmp copy_into_matrix
1290 ;one of the non-forward vectors caused a problem, so ignore them and
1291 ;use just the forward vector
1296 jmp just_forward_vec_norm
1298 ;use forward and up vectors
1300 push edi ;save matrix
1304 call _vm_vec_copy_normalize
1311 call _vm_vec_copy_normalize
1316 push dword zvec;src1
1317 push dword yvec;src0
1318 push dword xvec;dest
1319 call _vm_vec_crossprod ;get x = y cross z
1322 ;normalize new perpendicular vector
1323 push eax ;get new vec (up) in esi
1324 call _vm_vec_normalize
1329 ;now recompute right vector, in case it wasn't entirely perpendiclar
1331 push dword xvec;src1
1332 push dword zvec;src0
1333 push dword yvec;dest
1334 call _vm_vec_crossprod ;y = z cross x
1337 pop edi ;get matrix back
1340 vm_copy edi+rvec,xvec
1341 vm_copy edi+uvec,yvec
1342 vm_copy edi+fvec,zvec
1356 debug_brk '0-len vec in vec_2_mat'
1359 ;only the forward vector is present
1364 call _vm_vec_copy_normalize
1368 just_forward_vec_norm:
1371 or eax,[esi+8] ;check both x & z == 0
1374 ;forward vector is straight up (or down)
1376 mov dword [edi+m1],f1_0
1377 mov eax,[esi+4] ;get y componant
1381 sub eax,edx ;make sign correct
1393 m2m_neg [edi+8],[esi+0]
1395 call _vm_vec_normalize
1402 call _vm_vec_crossprod
1413 ;multiply (dot) two vectors. assumes dest ptr in ebp, src pointers in esi,edi.
1414 ;trashes ebx,ecx,edx
1417 ;macro dest,x0,y0,z0,x1,y1,z1
1433 shrd ebx,ecx,16 ;fixup ebx
1438 ;rotate a vector by a rotation matrix
1439 ;eax=dest vector, esi=src vector, edi=matrix. returns eax=dest vector
1443 break_if e,'vec_rotate: dest==src'
1449 mov ebp,[esp+20];dest vec
1450 mov esi,[esp+24];src vec
1451 mov edi,[esp+28];matrix
1454 vv_mul 0, 0,4,8, m1,m4,m7
1455 vv_mul 4, 0,4,8, m2,m5,m8
1456 vv_mul 8, 0,4,8, m3,m6,m9
1458 mov eax,ebp ;return eax=dest
1466 ;transpose a matrix in place. Takes matrix. returns matrix
1467 _vm_transpose_matrix:
1486 ;copy and transpose a matrix. Takes edi=dest, esi=src. returns edi=dest
1487 _vm_copy_transpose_matrix:
1488 mov edx,[esp+4];dest
1522 ;mulitply 2 matrices, fill in dest. returns ptr to dest
1523 ;takes dest, src0, scr1
1524 _vm_matrix_x_matrix:
1527 break_if e,'matrix_x_matrix: dest==src0'
1529 break_if e,'matrix_x_matrix: dest==src1'
1535 mov ebp,[esp+20] ;ebp=dest
1536 mov esi,[esp+24] ;esi=src0
1537 mov edi,[esp+28] ;edi=src1
1539 ;;This code would do the same as the nine lines below it, but I'm sure
1540 ;;Mike would disapprove
1541 ;; for s0,<<m1,m2,m3>,<m4,m5,m6>,<m7,m8,m9>>
1542 ;; for s1,<<m1,m4,m7>,<m2,m5,m8>,<m3,m6,m9>>
1543 ;; vv_mul @ArgI(1,s0)+@ArgI(1,s1), s0, s1
1547 vv_mul m1, m1,m2,m3, m1,m4,m7
1548 vv_mul m2, m1,m2,m3, m2,m5,m8
1549 vv_mul m3, m1,m2,m3, m3,m6,m9
1551 vv_mul m4, m4,m5,m6, m1,m4,m7
1552 vv_mul m5, m4,m5,m6, m2,m5,m8
1553 vv_mul m6, m4,m5,m6, m3,m6,m9
1555 vv_mul m7, m7,m8,m9, m1,m4,m7
1556 vv_mul m8, m7,m8,m9, m2,m5,m8
1557 vv_mul m9, m7,m8,m9, m3,m6,m9
1559 mov eax,ebp ;eax=ptr to dest
1566 ;computes the delta angle between two vectors
1567 ;two entry points: normalized and non-normalized vectors
1568 ;takes esi,edi=vectors, eax=optional forward vector
1569 ;returns ax=delta angle
1570 ;if the forward vector is NULL, the absolute values of the delta angle
1571 ;is returned. If it is specified, the rotation around that vector from
1572 ;esi to edi is returned.
1582 call _vm_vec_normalize
1585 call _vm_vec_normalize
1589 _vm_vec_delta_ang_norm:
1598 call _vm_vec_dotprod
1600 call fix_acos_asm ;now angle in ax
1601 mov ebx,[esp+24] ;get forward vec
1604 ;do cross product to find sign of angle
1605 push eax ;save angle
1609 push dword tempv0 ;new vec
1610 call _vm_vec_crossprod
1612 push ebx ;forward vec
1613 push eax ;new vector
1614 call _vm_vec_dotprod ;eax=dotprod
1620 sub eax,edx ;make sign correct
1628 ;compute a rotation matrix from the forward vector and a rotation around
1629 ;that vector. takes esi=vector, ax=angle, edi=matrix. returns edi=dest matrix.
1631 _vm_vec_ang_2_matrix:
1644 ;extract heading & pitch from vector
1646 mov eax,[esi+4] ;m6=-sp
1652 call long_sqrt_asm ;eax=cp
1668 ;compute the distance from a point to a plane. takes the normalized normal
1669 ;of the plane (ebx), a point on the plane (edi), and the point to check (esi).
1670 ;returns distance in eax
1671 ;distance is signed, so negative dist is on the back of the plane
1676 call vm_vec_sub ;vecs in esi,edi
1678 mov esi,eax ;vector plane -> point
1685 ;extract the angles from a matrix. takes esi=matrix, fills in edi=angvec
1686 vm_extract_angles_matrix:
1687 pushm eax,ebx,edx,ecx
1689 ;extract heading & pitch from forward vector
1691 mov eax,[esi].fvec.z ;ch
1692 mov ebx,[esi].fvec.x ;sh
1694 mov ecx,ebx ;check for z==x==0
1696 jz zero_head ;zero, use head=0
1698 zero_head: mov [edi].head,ax ;save heading
1700 call fix_sincos_asm ;get back sh
1704 mov ecx,eax ;save abs(sine)
1707 cmp eax,ecx ;which is larger?
1708 pop eax ;get sine back
1711 ;sine is larger, so use it
1712 mov ebx,eax ;ebx=sine heading
1713 mov eax,[esi].m3 ;cp = shcp / sh
1716 ;cosine is larger, so use it
1719 mov eax,[esi].fvec.z ;get chcp
1720 get_cosp: fixdiv ebx ;cp = chcp / ch
1726 mov ebx,[esi].fvec.y ;fvec.y = -sp
1727 neg ebx ;ebx = y (sin)
1728 mov ecx,ebx ;check for z==x==0
1730 jz zero_pitch ;bogus vec, set p=0
1732 zero_pitch: mov [edi].pitch,ax
1737 mov eax,[esi].m4 ;m4 = sbcp
1739 mov ebx,eax ;save sb
1741 mov eax,[esi].m5 ;get cbcp
1743 mov ecx,ebx ;check for z==x==0
1745 jz zero_bank ;bogus vec, set n=0
1747 zero_bank: mov [edi].bank,ax
1750 popm eax,ebx,edx,ecx
1754 ;the cosine of pitch is zero. we're pitched straight up. say no bank
1755 cp_zero: mov [edi].bank,0 ;no bank
1757 popm eax,ebx,edx,ecx
1761 ;extract the angles from a vector, assuming zero bank.
1762 ;takes esi=vec, edi=angvec
1763 ;note versions for normalized and not normalized vector
1764 ;unnormalized version TRASHES ESI
1765 vm_extract_angles_vector:
1768 call vm_vec_copy_normalize ;ecx=mag
1773 vm_extract_angles_vector_normalized:
1776 mov [edi].bank,0 ;always zero bank
1781 mov [edi].pitch,ax ;p = asin(-y)
1786 jz zero_head2 ;check for up vector
1788 mov ebx,[esi].x ;get x again
1790 zero_head2: mov [edi].head,ax ;h = atan2(x,z) (or zero)