1 /*
2
3 Copyright (C) 2015-2018 Night Dive Studios, LLC.
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 */
19 //
20 // $Source: r:/prj/lib/src/3d/RCS/points.asm $
21 // $Revision: 1.17 $
22 // $Author: jaemz $
23 // $Date: 1994/09/28 19:00:52 $
24 //
25 // Point definition routines
26 //
27
28 //#include <FixMath.h>
29 #include "3d.h"
30 #include "GlobalV.h"
31 #include "lg.h"
32
33 // prototypes
34 void rotate_norm(g3s_vector *v, fix *x, fix *y, fix *z);
35 void do_norm_rotate(fix x, fix y, fix z, fix *rx, fix *ry, fix *rz);
36
37 void do_rotate(fix x, fix y, fix z, fix *rx, fix *ry, fix *rz);
38
39 // void xlate_rotate_point(g3s_vector *v, fix *x, fix *y, fix *z);
40 #define xlate_rotate_point(v, x, y, z) \
41 do_rotate(v->gX - _view_position.gX, v->gY - _view_position.gY, v->gZ - _view_position.gZ, x, y, z)
42
43 extern int code_point(g3s_point *pt);
44 extern char SubLongWithOverflow(int32_t *result, int32_t src, int32_t dest);
45 extern bool AddLongWithOverflow(int32_t *result, int32_t src, int32_t dest);
46
47 // for temp use in rotate_list, etc.
48 g3s_codes g_codes;
49
50 // rotate a normal or gradient vector. esi=vector, returns edi=point, bl=codes.
51 // assumes perspective mapper scale factor will be set to _scrw.
g3_rotate_norm(g3s_vector * v)52 g3s_phandle g3_rotate_norm(g3s_vector *v) {
53 fix x, y, z;
54 fix temp, temp2, temp3;
55 g3s_point *point;
56
57 rotate_norm(v, &x, &y, &z);
58
59 temp = fix_div(z, _matrix_scale.gZ);
60 temp2 = fix_div(x, _matrix_scale.gX);
61 temp3 = fix_div(y, _matrix_scale.gY);
62
63 temp3 = -fix_mul_div(temp3, _scrw, _scrh); // because projecting negates too, of course. Grrr.
64
65 getpnt(point);
66 point->gX = temp2;
67 point->gY = temp3;
68 point->gZ = temp;
69 point->p3_flags = 0;
70
71 return (point);
72 }
73
g3_rotate_point(g3s_vector * v)74 g3s_phandle g3_rotate_point(g3s_vector *v) {
75 g3s_point *point;
76
77 getpnt(point);
78 xlate_rotate_point(v, &point->gX, &point->gY, &point->gZ);
79 point->p3_flags = 0;
80
81 code_point(point);
82 return (point);
83 }
84
85 // matrix multiply and project a point. esi=vector, returns edi=point
g3_transform_point(g3s_vector * v)86 g3s_phandle g3_transform_point(g3s_vector *v) {
87 g3s_phandle tempH;
88
89 // printf("g3_transform_point\n");
90
91 tempH = g3_rotate_point(v);
92 g3_project_point(tempH);
93 return (tempH);
94 }
95
96 // takes edi = ptr to point. projects, fills in sx,sy, sets flag.
97 // returns 0 if z<=0, 1 if z>0.
98 // trashes eax,ecx,edx.
g3_project_point(g3s_phandle p)99 int g3_project_point(g3s_phandle p) {
100 fix x, y, z, res;
101
102 #ifdef stereo_on
103 test _g3d_stereo,
104 1 jz no_stereo1
105 // is this a sister point?
106 cmp edi,
107 _g3d_stereo_list jl not_sister
108
109 // debug_brk 'yo, found projecting sister'
110
111 // copy the point and add
112 mov esi,
113 edi sub esi, _g3d_stereo_base mov ecx,
114 (size g3s_point) / 4 rep movsd
115
116 mov eax,
117 _g3d_eyesep sub edi,
118 (size g3s_point) // restore edi
119 add[edi]
120 .x,
121 eax
122
123 // call clip encoder on this point
124 mov ecx,
125 ebx call code_point mov ebx,
126 ecx
127
128 // project point like a normal point
129 mov _g3d_stereo,
130 0 pop esi call g3_project_point mov _g3d_stereo,
131 1
132
133 ret
134
135 not_sister :
136 // copy the point
137 mov esi,
138 edi add edi,
139 _g3d_stereo_base mov ecx,
140 (size g3s_point) / 4 rep movsd mov eax,
141 _g3d_eyesep sub edi,
142 (size g3s_point) // restore edi
143 add[edi]
144 .x,
145 eax
146
147 // call clip encoder
148 mov ecx,
149 ebx call code_point mov ebx,
150 ecx
151
152 sub edi,
153 _g3d_stereo_base no_stereo1 :
154 #endif
155
156 /*printf("g3_project_point\n");
157
158 char printy[100];
159 fix_sprint(printy, p->gX);
160 printf("%s\n", printy);
161
162 fix_sprint(printy, p->gY);
163 printf("%s\n", printy);
164
165 fix_sprint(printy, p->gZ);
166 printf("%s\n", printy);*/
167
168 // check if this point is in front of the back plane.
169 z = p->gZ;
170 if (z <= 0)
171 return 0;
172 x = p->gX;
173 y = p->gY;
174
175 // point is in front of back plane---do projection.
176 // project y coordinate.
177 res = fix_mul_div(y, _scrh, z);
178 if (gOVResult) {
179 p->codes |= CC_CLIP_OVERFLOW;
180 return 1;
181 }
182 res = -res;
183 if (AddLongWithOverflow(&res, res, _biasy)) {
184 p->codes |= CC_CLIP_OVERFLOW;
185 return 1;
186 }
187 p->sy = res;
188
189 // now project x point
190 res = fix_mul_div(x, _scrw, z);
191 if (gOVResult) {
192 p->codes |= CC_CLIP_OVERFLOW;
193 return 1;
194 }
195 if (AddLongWithOverflow(&res, res, _biasx)) {
196 p->codes |= CC_CLIP_OVERFLOW;
197 return 1;
198 }
199 p->sx = res;
200
201 // modify point flags to indicate projection.
202 p->p3_flags |= PF_PROJECTED;
203
204 #ifdef stereo_on
205 test _g3d_stereo, 1 jz no_stereo2 mov eax,
206 [edi].sy // copy over old sy
207 add edi,
208 _g3d_stereo_base // load twin address
209 mov[edi]
210 .sy,
211 eax // make new sy, could add the .5 addition here too
212
213 mov eax,
214 [edi].x
215 // reproject the x coord
216 imul _scrw //* screen width
217 proj_div_2 : idiv ecx /// z
218 add eax,
219 _biasx //+center
220 mov[edi]
221 .sx,
222 eax // save
223
224 // indicate projection
225 or [edi].p3_flags,
226 PF_PROJECTED
227
228 // restore edi
229 sub edi,
230 _g3d_stereo_base no_stereo2 :
231 #endif
232
233 // point has been projected.
234 return 1;
235 }
236
237 // MLA - all the divide exception handler overflow stuff was removed, and
238 // checked before each divide. So all of this stuf isn't needed
239 /*
240 public proj_div_0,proj_div_1,divide_overflow_3d
241 ifdef stereo_on
242 public proj_div_2,divide_overflow_r3d
243 endif
244
245 //this gets called by the system divide overflow handler when there is an
246 //overflow at proj_div_0, proj_div_1
247 divide_overflow_3d:
248 // fall project_overflow
249 project_overflow:
250 or [edi].codes,CC_CLIP_OVERFLOW
251
252 ifdef stereo_on
253 test _g3d_stereo,1
254 jz no_stereo3
255 add edi,_g3d_stereo_base
256 divide_overflow_r3d:
257 or [edi].codes,CC_CLIP_OVERFLOW
258 sub edi,_g3d_stereo_base
259 no_stereo3:
260 endif
261
262 cspew "!" //"project overflow!"
263 // this did not use to restore this
264 ex_set_div_action esi
265 pop esi
266 ret
267 */
268
269 // takes esi=ptr to array of vectors, edi=ptr to list for point handles,
270 // ecx=count
g3_transform_list(short n,g3s_phandle * dest_list,g3s_vector * v)271 g3s_codes g3_transform_list(short n, g3s_phandle *dest_list, g3s_vector *v) {
272 int i;
273 g3s_phandle temphand;
274
275 g_codes.or_ = 0;
276 g_codes.and_ = 0xff;
277
278 for (i = n; i > 0; i--) {
279 temphand = g3_transform_point(v++);
280 g_codes.or_ |= temphand->codes;
281 g_codes.and_ &= temphand->codes;
282
283 *(dest_list++) = temphand;
284 }
285 return (g_codes);
286 }
287
288 // takes esi=ptr to array of vectors, edi=ptr to list for point handles,
289 // ecx=count returns bh=codes and, bl=codes or
g3_rotate_list(short n,g3s_phandle * dest_list,g3s_vector * v)290 g3s_codes g3_rotate_list(short n, g3s_phandle *dest_list, g3s_vector *v) {
291 int i;
292 g3s_phandle temphand;
293
294 g_codes.or_ = 0;
295 g_codes.and_ = 0xff;
296
297 for (i = n; i > 0; i--) {
298 temphand = g3_rotate_point(v++);
299 g_codes.or_ |= temphand->codes;
300 g_codes.and_ &= temphand->codes;
301
302 *(dest_list++) = temphand;
303 }
304 return (g_codes);
305 }
306
307 // takes esi=ptr to array of point handles, ecx=count
g3_project_list(short n,g3s_phandle * point_list)308 g3s_codes g3_project_list(short n, g3s_phandle *point_list) {
309 int i;
310 g3s_phandle temphand;
311
312 g_codes.or_ = 0;
313 g_codes.and_ = 0xff;
314
315 for (i = n; i > 0; i--) {
316 temphand = *(point_list++);
317 g_codes.or_ |= temphand->codes;
318 g_codes.and_ &= temphand->codes;
319
320 g3_project_point(temphand);
321 }
322
323 return (g_codes);
324 }
325
326 // takes esi=ptr to array of vectors, edi=ptr to dest vectors
g3_rotate_light_norm(g3s_vector * v)327 g3s_phandle g3_rotate_light_norm(g3s_vector *v) {
328 g3s_point *point;
329
330 getpnt(point);
331 do_rotate(v->gX, v->gY, v->gZ, &point->gX, &point->gY, &point->gZ);
332 return (point);
333 }
334
335 // takes esi=ptr to normal vector. returns in <ecx,esi,eax>. trashes all regs
rotate_norm(g3s_vector * v,fix * x,fix * y,fix * z)336 void rotate_norm(g3s_vector *v, fix *x, fix *y, fix *z) { do_norm_rotate(v->gX, v->gY, v->gZ, x, y, z); }
337
338 // does the rotate with the view matrix.
339 // takes <x,y,z> = <esi,edi,ebp>, returns <x,y,z> = <ecx,esi,eax>
do_norm_rotate(fix x,fix y,fix z,fix * rx,fix * ry,fix * rz)340 void do_norm_rotate(fix x, fix y, fix z, fix *rx, fix *ry, fix *rz) {
341 int64_t r;
342
343 // this matrix multiply here will someday be optimized for zero and one terms
344 // uses unscaled rotation matrix.
345
346 // first column
347 r = fix64_mul(x, uvm1) + fix64_mul(y, uvm4) + fix64_mul(z, uvm7);
348 *rx = fix64_to_fix(r);
349
350 // second column
351 r = fix64_mul(x, uvm2) + fix64_mul(y, uvm5) + fix64_mul(z, uvm8);
352 *ry = fix64_to_fix(r);
353
354 // third column
355 r = fix64_mul(x, uvm3) + fix64_mul(y, uvm6) + fix64_mul(z, uvm9);
356 *rz = fix64_to_fix(r);
357 }
358
359 // made this a define - MLA
360 /*//takes esi=ptr to vector. returns <x,y,z> in <ecx,esi,eax>. trashes all regs
361 void xlate_rotate_point(g3s_vector *v, fix *x, fix *y, fix *z)
362 {
363 do_rotate(v->gX-_view_position.gX, v->gY-_view_position.gY,
364 v->gZ-_view_position.gZ,x,y,z);
365 }*/
366
367 // does the rotate with the view matrix.
368 // takes <x,y,z> = <esi,edi,ebp>, returns <x,y,z> = <ecx,esi,eax>
do_rotate(fix x,fix y,fix z,fix * rx,fix * ry,fix * rz)369 void do_rotate(fix x, fix y, fix z, fix *rx, fix *ry, fix *rz) {
370 // this matrix multiply here will someday be optimized for zero and one terms
371 int64_t r;
372 // first column
373 r = fix64_mul(x, vm1) + fix64_mul(y, vm4) + fix64_mul(z, vm7);
374 *rx = fix64_to_fix(r);
375
376 // second column
377 r = fix64_mul(x, vm2) + fix64_mul(y, vm5) + fix64_mul(z, vm8);
378 *ry = fix64_to_fix(r);
379
380 // third column
381 r = fix64_mul(x, vm3) + fix64_mul(y, vm6) + fix64_mul(z, vm9);
382 *rz = fix64_to_fix(r);
383 }
384
385 // rotate an x delta. takes edi=dest vector, eax=dx
386 // trashes eax,ebx,edx
g3_rotate_delta_x(g3s_vector * dest,fix dx)387 void g3_rotate_delta_x(g3s_vector *dest, fix dx) {
388 dest->gX = fix_mul(dx, vm1);
389 dest->gY = fix_mul(dx, vm2);
390 dest->gZ = fix_mul(dx, vm3);
391 }
392
393 // rotate a y delta. takes edi=dest vector, eax=dy
394 // trashes eax,ebx,edx
g3_rotate_delta_y(g3s_vector * dest,fix dy)395 void g3_rotate_delta_y(g3s_vector *dest, fix dy) {
396 dest->gX = fix_mul(dy, vm4);
397 dest->gY = fix_mul(dy, vm5);
398 dest->gZ = fix_mul(dy, vm6);
399 }
400
401 // rotate a z delta. takes edi=dest vector, eax=dz
402 // trashes eax,ebx,edx
g3_rotate_delta_z(g3s_vector * dest,fix dz)403 void g3_rotate_delta_z(g3s_vector *dest, fix dz) {
404 dest->gX = fix_mul(dz, vm7);
405 dest->gY = fix_mul(dz, vm8);
406 dest->gZ = fix_mul(dz, vm9);
407 }
408
409 // rotate an xz delta. takes edi=dest vector, eax=dx, ebx=dz
410 // trashes eax,ebx,edx
g3_rotate_delta_xz(g3s_vector * dest,fix dx,fix dz)411 void g3_rotate_delta_xz(g3s_vector *dest, fix dx, fix dz) {
412 int64_t r;
413
414 // first column
415 r = fix64_mul(dx, vm1) + fix64_mul(dz, vm7);
416 dest->gX = fix64_to_fix(r);
417
418 // second column
419 r = fix64_mul(dx, vm2) + fix64_mul(dz, vm8);
420 dest->gY = fix64_to_fix(r);
421
422 // third column
423 r = fix64_mul(dx, vm3) + fix64_mul(dz, vm9);
424 dest->gZ = fix64_to_fix(r);
425 }
426
427 // rotate an xy delta. takes edi=dest vector, eax=dx, ebx=dy
428 // trashes eax,ebx,edx
g3_rotate_delta_xy(g3s_vector * dest,fix dx,fix dy)429 void g3_rotate_delta_xy(g3s_vector *dest, fix dx, fix dy) {
430 int64_t r;
431
432 // first column
433 r = fix64_mul(dx, vm1) + fix64_mul(dy, vm4);
434 dest->gX = fix64_to_fix(r);
435
436 // second column
437 r = fix64_mul(dx, vm2) + fix64_mul(dy, vm5);
438 dest->gY = fix64_to_fix(r);
439
440 // third column
441 r = fix64_mul(dx, vm3) + fix64_mul(dy, vm6);
442 dest->gZ = fix64_to_fix(r);
443 }
444
445 // rotate a yz delta. takes edi=dest vector, eax=dy, ebx=dz
446 // trashes eax,ebx,edx
g3_rotate_delta_yz(g3s_vector * dest,fix dy,fix dz)447 void g3_rotate_delta_yz(g3s_vector *dest, fix dy, fix dz) {
448 int64_t r;
449
450 // first column
451 r = fix64_mul(dy, vm4) + fix64_mul(dz, vm7);
452 dest->gX = fix64_to_fix(r);
453
454 // second column
455 r = fix64_mul(dy, vm5) + fix64_mul(dz, vm8);
456 dest->gY = fix64_to_fix(r);
457
458 // third column
459 r = fix64_mul(dy, vm6) + fix64_mul(dz, vm9);
460 dest->gZ = fix64_to_fix(r);
461 }
462
463 // rotate a delta vector. takes edi=dest, eax,ebx,ecx=dx,dy,dz
464 // trashes all but ebp,edi
g3_rotate_delta_xyz(g3s_vector * dest,fix dx,fix dy,fix dz)465 void g3_rotate_delta_xyz(g3s_vector *dest, fix dx, fix dy, fix dz) {
466 do_rotate(dx, dy, dz, &dest->gX, &dest->gY, &dest->gZ);
467 }
468
469 // rotate a delta vector. takes edi=dest, esi=src
470 // trashes all but ebp,edi
g3_rotate_delta_v(g3s_vector * dest,g3s_vector * src)471 void g3_rotate_delta_v(g3s_vector *dest, g3s_vector *src) {
472 do_rotate(src->gX, src->gY, src->gZ, &dest->gX, &dest->gY, &dest->gZ);
473 }
474
475 // like add_delta, but creates and returns a new point
476 // takes esi=src, ebx=delta, returns edi=new point
477 // trashes eax,ebx
g3_copy_add_delta_v(g3s_phandle src,g3s_vector * delta)478 g3s_phandle g3_copy_add_delta_v(g3s_phandle src, g3s_vector *delta) {
479 g3s_point *point;
480
481 getpnt(point);
482 point->gX = src->gX + delta->gX;
483 point->gY = src->gY + delta->gY;
484 point->gZ = src->gZ + delta->gZ;
485 point->p3_flags = 0;
486 code_point(point);
487 return (point);
488 }
489
490 // adds a delta vector (created by rotate delta) to a point
491 // takes edi=point, esi=delta. clears projected bit, computes codes
492 // trashes eax,esi,bl
g3_add_delta_v(g3s_phandle p,g3s_vector * delta)493 void g3_add_delta_v(g3s_phandle p, g3s_vector *delta) {
494 p->gX += delta->gX;
495 p->gY += delta->gY;
496 p->gZ += delta->gZ;
497
498 p->p3_flags &= ~PF_PROJECTED;
499 code_point(p);
500 }
501
502 // add an x delta to a point. takes edi=point, eax=dx
503 // trashes eax,ebx,edx
g3_add_delta_x(g3s_phandle p,fix dx)504 void g3_add_delta_x(g3s_phandle p, fix dx) {
505 p->gX += fix_mul(vm1, dx);
506 p->gY += fix_mul(vm2, dx);
507 p->gZ += fix_mul(vm3, dx);
508 p->p3_flags &= ~PF_PROJECTED;
509
510 code_point(p);
511 }
512
513 // add a y delta to a point. takes edi=point, eax=dy
514 // trashes eax,ebx,edx
g3_add_delta_y(g3s_phandle p,fix dy)515 void g3_add_delta_y(g3s_phandle p, fix dy) {
516 p->gX += fix_mul(vm4, dy);
517 p->gY += fix_mul(vm5, dy);
518 p->gZ += fix_mul(vm6, dy);
519 p->p3_flags &= ~PF_PROJECTED;
520
521 code_point(p);
522 }
523
524 // add a z delta to a point. takes edi=point, eax=dz
525 // trashes eax,ebx,edx
g3_add_delta_z(g3s_phandle p,fix dz)526 void g3_add_delta_z(g3s_phandle p, fix dz) {
527 p->gX += fix_mul(vm7, dz);
528 p->gY += fix_mul(vm8, dz);
529 p->gZ += fix_mul(vm9, dz);
530 p->p3_flags &= ~PF_PROJECTED;
531
532 code_point(p);
533 }
534
535 // add an xy delta to a point. takes edi=point, eax=dx, ebx=dy
536 // trashes eax,ebx,ecx,edx,esi
g3_add_delta_xy(g3s_phandle p,fix dx,fix dy)537 void g3_add_delta_xy(g3s_phandle p, fix dx, fix dy) {
538 int64_t r;
539
540 // first column
541 r = fix64_mul(dx, vm1) + fix64_mul(dy, vm4);
542 p->gX += fix64_to_fix(r);
543
544 // second column
545 r = fix64_mul(dx, vm2) + fix64_mul(dy, vm5);
546 p->gY += fix64_to_fix(r);
547
548 // third column
549 r = fix64_mul(dx, vm3) + fix64_mul(dy, vm6);
550 p->gZ += fix64_to_fix(r);
551
552 p->p3_flags &= ~PF_PROJECTED;
553 code_point(p);
554 }
555
556 // add an xz delta to a point. takes edi=point, eax=dx, ebx=dz
557 // trashes eax,ebx,ecx,edx,esi
g3_add_delta_xz(g3s_phandle p,fix dx,fix dz)558 void g3_add_delta_xz(g3s_phandle p, fix dx, fix dz) {
559 int64_t r;
560
561 // first column
562 r = fix64_mul(dx, vm1) + fix64_mul(dz, vm7);
563 p->gX += fix64_to_fix(r);
564
565 // second column
566 r = fix64_mul(dx, vm2) + fix64_mul(dz, vm8);
567 p->gY += fix64_to_fix(r);
568
569 // third column
570 r = fix64_mul(dx, vm3) + fix64_mul(dz, vm9);
571 p->gZ += fix64_to_fix(r);
572
573 p->p3_flags &= ~PF_PROJECTED;
574 code_point(p);
575 }
576
577 // add an yz delta to a point. takes edi=point, eax=dy, ebx=dz
578 // trashes eax,ebx,ecx,edx,esi
g3_add_delta_yz(g3s_phandle p,fix dy,fix dz)579 void g3_add_delta_yz(g3s_phandle p, fix dy, fix dz) {
580 int64_t r;
581
582 // first column
583 r = fix64_mul(dy, vm4) + fix64_mul(dz, vm7);
584 p->gX += fix64_to_fix(r);
585
586 // second column
587 r = fix64_mul(dy, vm5) + fix64_mul(dz, vm8);
588 p->gY += fix64_to_fix(r);
589
590 // third column
591 r = fix64_mul(dy, vm6) + fix64_mul(dz, vm9);
592 p->gZ += fix64_to_fix(r);
593
594 p->p3_flags &= ~PF_PROJECTED;
595 code_point(p);
596 }
597
598 // add an xyz delta to a point. takes edi=point, eax=dx, ebx=dy, ecx=dz
599 // trashes eax,ebx,ecx,edx,esi
g3_add_delta_xyz(g3s_phandle p,fix dx,fix dy,fix dz)600 void g3_add_delta_xyz(g3s_phandle p, fix dx, fix dy, fix dz) {
601 fix rx, ry, rz;
602
603 do_rotate(dx, dy, dz, &rx, &ry, &rz);
604
605 p->gX += rx;
606 p->gY += ry;
607 p->gZ += rz;
608
609 p->p3_flags &= ~PF_PROJECTED;
610 code_point(p);
611 }
612
613 // like add_delta, but creates and returns a new point in edi
614 // add an x delta to a point. takes esi=point, eax=dx
615 // trashes eax,ebx,edx
g3_copy_add_delta_x(g3s_phandle src,fix dx)616 g3s_phandle g3_copy_add_delta_x(g3s_phandle src, fix dx) {
617 g3s_point *point;
618
619 getpnt(point);
620 point->gX = src->gX + fix_mul(dx, vm1);
621 point->gY = src->gY + fix_mul(dx, vm2);
622 point->gZ = src->gZ + fix_mul(dx, vm3);
623 point->p3_flags = 0;
624 code_point(point);
625 return (point);
626 }
627
628 // like add_delta, but creates and returns a new point in edi
629 // add a y delta to a point. takes esi=point, eax=dy
630 // trashes eax,ebx,edx
g3_copy_add_delta_y(g3s_phandle src,fix dy)631 g3s_phandle g3_copy_add_delta_y(g3s_phandle src, fix dy) {
632 g3s_point *point;
633
634 getpnt(point);
635 point->gX = src->gX + fix_mul(dy, vm4);
636 point->gY = src->gY + fix_mul(dy, vm5);
637 point->gZ = src->gZ + fix_mul(dy, vm6);
638 point->p3_flags = 0;
639 code_point(point);
640 return (point);
641 }
642
643 // like add_delta, but creates and returns a new point in edi
644 // add a z delta to a point. takes esi=point, eax=dz
645 // trashes eax,ebx,edx
g3_copy_add_delta_z(g3s_phandle src,fix dz)646 g3s_phandle g3_copy_add_delta_z(g3s_phandle src, fix dz) {
647 g3s_point *point;
648
649 getpnt(point);
650 point->gX = src->gX + fix_mul(dz, vm7);
651 point->gY = src->gY + fix_mul(dz, vm8);
652 point->gZ = src->gZ + fix_mul(dz, vm9);
653 point->p3_flags = 0;
654 code_point(point);
655 return (point);
656 }
657
658 // like add_delta, but modifies an existing point in edi
659 // add an x delta to a point. takes esi=src point, edi=replace point, ax=dx
660 // trashes eax,ebx,edx
g3_replace_add_delta_x(g3s_phandle src,g3s_phandle dst,fix dx)661 g3s_phandle g3_replace_add_delta_x(g3s_phandle src, g3s_phandle dst, fix dx) {
662 dst->gX = src->gX + fix_mul(dx, vm1);
663 dst->gY = src->gY + fix_mul(dx, vm2);
664 dst->gZ = src->gZ + fix_mul(dx, vm3);
665 dst->p3_flags = 0;
666 code_point(dst);
667 return (dst);
668 }
669
670 // like add_delta, but modifies an existing point in edi
671 // add a y delta to a point. takes esi=src point, edi=replace point, ax=dy
672 // trashes eax,ebx,edx
g3_replace_add_delta_y(g3s_phandle src,g3s_phandle dst,fix dy)673 g3s_phandle g3_replace_add_delta_y(g3s_phandle src, g3s_phandle dst, fix dy) {
674 dst->gX = src->gX + fix_mul(dy, vm4);
675 dst->gY = src->gY + fix_mul(dy, vm5);
676 dst->gZ = src->gZ + fix_mul(dy, vm6);
677 dst->p3_flags = 0;
678 code_point(dst);
679 return (dst);
680 }
681
682 // like add_delta, but modifies an existing point in edi
683 // add a z delta to a point. takes esi=src point, edi=replace point, ax=dz
684 // trashes eax,ebx,edx
g3_replace_add_delta_z(g3s_phandle src,g3s_phandle dst,fix dz)685 g3s_phandle g3_replace_add_delta_z(g3s_phandle src, g3s_phandle dst, fix dz) {
686 dst->gX = src->gX + fix_mul(dz, vm7);
687 dst->gY = src->gY + fix_mul(dz, vm8);
688 dst->gZ = src->gZ + fix_mul(dz, vm9);
689 dst->p3_flags = 0;
690 code_point(dst);
691 return (dst);
692 }
693
694 // like add_delta, but creates and returns a new point in edi
695 // add an xy delta to a point. takes edi=point, eax=dx, ebx=dy
696 // trashes eax,ebx,ecx,edx,esi
g3_copy_add_delta_xy(g3s_phandle src,fix dx,fix dy)697 g3s_phandle g3_copy_add_delta_xy(g3s_phandle src, fix dx, fix dy) {
698 g3s_point *point;
699 int64_t r;
700
701 getpnt(point);
702
703 // first column
704 r = fix64_mul(dx, vm1) + fix64_mul(dy, vm4);
705 point->gX = src->gX + fix64_to_fix(r);
706
707 // second column
708 r = fix64_mul(dx, vm2) + fix64_mul(dy, vm5);
709 point->gY = src->gY + fix64_to_fix(r);
710
711 // third column
712 r = fix64_mul(dx, vm3) + fix64_mul(dy, vm6);
713 point->gZ = src->gZ + fix64_to_fix(r);
714
715 point->p3_flags = 0;
716 code_point(point);
717 return (point);
718 }
719
720 // like add_delta, but creates and returns a new point in edi
721 // add an xz delta to a point. takes edi=point, eax=dx, ebx=dz
722 // trashes eax,ebx,ecx,edx,esi
g3_copy_add_delta_xz(g3s_phandle src,fix dx,fix dz)723 g3s_phandle g3_copy_add_delta_xz(g3s_phandle src, fix dx, fix dz) {
724 g3s_point *point;
725 int64_t r;
726
727 getpnt(point);
728
729 // first column
730 r = fix64_mul(dx, vm1) + fix64_mul(dz, vm7);
731 point->gX = src->gX + fix64_to_fix(r);
732
733 // second column
734 r = fix64_mul(dx, vm2) + fix64_mul(dz, vm8);
735 point->gY = src->gY + fix64_to_fix(r);
736
737 // third column
738 r = fix64_mul(dx, vm3) + fix64_mul(dz, vm9);
739 point->gZ = src->gZ + fix64_to_fix(r);
740
741 point->p3_flags = 0;
742 code_point(point);
743 return (point);
744 }
745
746 // like add_delta, but creates and returns a new point in edi
747 // add an yz delta to a point. takes edi=point, eax=dy, ebx=dz
748 // trashes eax,ebx,ecx,edx,esi
g3_copy_add_delta_yz(g3s_phandle src,fix dy,fix dz)749 g3s_phandle g3_copy_add_delta_yz(g3s_phandle src, fix dy, fix dz) {
750 g3s_point *point;
751 int64_t r;
752
753 getpnt(point);
754
755 // first column
756 r = fix64_mul(dy, vm4) + fix64_mul(dz, vm7);
757 point->gX = src->gX + fix64_to_fix(r);
758
759 // second column
760 r = fix64_mul(dy, vm5) + fix64_mul(dz, vm8);
761 point->gY = src->gY + fix64_to_fix(r);
762
763 // third column
764 r = fix64_mul(dy, vm6) + fix64_mul(dz, vm9);
765 point->gZ = src->gZ + fix64_to_fix(r);
766
767 point->p3_flags = 0;
768 code_point(point);
769 return (point);
770 }
771
772 // like add_delta, but creates and returns a new point in edi
773 // add an xyz delta to a point. takes edi=point, eax=dx, ebx=dy, ecx=dz
774 // trashes eax,ebx,ecx,edx,esi
g3_copy_add_delta_xyz(g3s_phandle src,fix dx,fix dy,fix dz)775 g3s_phandle g3_copy_add_delta_xyz(g3s_phandle src, fix dx, fix dy, fix dz) {
776 g3s_point *point;
777
778 getpnt(point);
779 do_rotate(dx, dy, dz, &point->gX, &point->gY, &point->gZ);
780
781 point->gX += src->gX;
782 point->gY += src->gY;
783 point->gZ += src->gZ;
784
785 point->p3_flags = 0;
786 code_point(point);
787 return (point);
788 }
789