]> 4ch.mooo.com Git - 16.git/blob - 16/xw__/modex/THREED.ASM
====++++==== undid the reversion back at b6af468f5932336434d2fd956a30af42b58c20bf...
[16.git] / 16 / xw__ / modex / THREED.ASM
1 COMMENT /\r
2         Fixed-point math functions and 3D transforms\r
3         Copyright (c) 1993,94 by Alessandro Scotti\r
4 /\r
5 WARN    PRO\r
6 P386\r
7 JUMPS\r
8 LOCALS\r
9 \r
10 INCLUDE MATH.INC\r
11 \r
12 PUBLIC  tdFixedMul\r
13 PUBLIC  tdGetNormal\r
14 PUBLIC  tdRotate\r
15 PUBLIC  tdGetSurfaceLight\r
16 PUBLIC  tdSetLight\r
17 PUBLIC  tdSetRotation\r
18 PUBLIC  tdSetTranslation\r
19 PUBLIC  tdTransform\r
20 PUBLIC  tdTransformToImage\r
21 PUBLIC  tdTransformLight\r
22 PUBLIC  tdBackPlaneCull\r
23 PUBLIC  tdSetPerspective\r
24 \r
25 ;-----------------------------------------------------------\r
26 ;\r
27 ; Data segment\r
28 ;\r
29 MATH_DATA       SEGMENT USE16 PARA PUBLIC 'DATA'\r
30                 ASSUME ds:MATH_DATA\r
31 \r
32 INCLUDE         SINCOS.INC              ; Fixed 8:24 sin/cos table\r
33 \r
34 XRotation       TPOINT  <>              ; 3x3 rotation matrix\r
35 YRotation       TPOINT  <>\r
36 ZRotation       TPOINT  <>\r
37 \r
38 Translation     TPOINT  <>              ; Translation vector\r
39 \r
40 Light           TPOINT  <>              ; Light vector\r
41 AmbientLight    DW      00              ; Ambient light\r
42 \r
43 XScale                  DD      10000h  ; Scaling factor for X coordinate\r
44 YScale                  DD      10000h  ; Scaling factor for Y coordinate\r
45 PerspectiveDistance     DD      20000000h\r
46 \r
47 MATH_DATA       ENDS\r
48 \r
49 ;-----------------------------------------------------------\r
50 ;\r
51 ; Code segment\r
52 ;\r
53 MATH_TEXT       SEGMENT USE16 PARA PUBLIC 'CODE'\r
54                 ASSUME cs:MATH_TEXT, es:NOTHING, fs:NOTHING\r
55 \r
56 tdSetPerspective        PROC PASCAL FAR\r
57         ARG     Perspective:DWORD,      \\r
58                 ScaleX:DWORD,           \\r
59                 ScaleY:DWORD\r
60         USES    ds\r
61 \r
62         mov     ax, SEG MATH_DATA\r
63         mov     ds, ax\r
64         ASSUME  ds:MATH_DATA\r
65 \r
66         mov     eax, [Perspective]\r
67         mov     [PerspectiveDistance], eax\r
68         mov     eax, [ScaleX]\r
69         mov     [XScale], eax\r
70         mov     eax, [ScaleY]\r
71         mov     [YScale], eax\r
72 \r
73         ret\r
74 tdSetPerspective        ENDP\r
75 \r
76 \r
77 ;-----------------------------------------------------------\r
78 ;\r
79 ; Sets the rotation matrix.\r
80 ;\r
81 ; Input:\r
82 ;       RX      = X-axis rotation angle\r
83 ;       RY      = X-axis rotation angle\r
84 ;       RZ      = X-axis rotation angle\r
85 ; Output:\r
86 ;       none\r
87 ;\r
88 tdSetRotation   PROC PASCAL FAR\r
89         ARG     RX:WORD,        \\r
90                 RY:WORD,        \\r
91                 RZ:WORD\r
92         USES    ds, si, di\r
93 \r
94         mov     ax, SEG MATH_DATA\r
95         mov     ds, ax\r
96         ASSUME  ds:MATH_DATA\r
97 \r
98         mov     bx, [RZ]\r
99         mov     si, [RY]\r
100         mov     di, [RX]\r
101         shl     bx, 2\r
102         shl     si, 2\r
103         shl     di, 2\r
104 \r
105         push    ebp                     ; We use EBP as a scratch register\r
106 \r
107 ; Set X rotation\r
108         mov     eax, tblCos[bx]\r
109         imul    tblCos[si]\r
110         mov     [XRotation.X], edx\r
111 \r
112         mov     eax, tblSin[bx]\r
113         imul    tblCos[si]\r
114         mov     [XRotation.Y], edx\r
115 \r
116         mov     eax, tblSin[si]\r
117         sar     eax, 8                  ; Convert fixed 8:24 to fixed 16:16\r
118         mov     [XRotation.Z], eax\r
119 \r
120 ; Set Y rotation\r
121         mov     eax, tblCos[bx]\r
122         imul    tblSin[si]              ; EDX:EAX = fixed 16:48\r
123         shrd    eax, edx, 24            ; EAX = fixed 8:24\r
124         imul    tblSin[di]              ; EDX:EAX = fixed 16:48\r
125         mov     ebp, eax\r
126         mov     ecx, edx\r
127         mov     eax, tblSin[bx]\r
128         imul    tblCos[di]\r
129         add     eax, ebp\r
130         adc     edx, ecx                ; EDX:EAX = fixed 16:48\r
131         neg     edx\r
132         mov     [YRotation.X], edx\r
133 \r
134         mov     eax, tblSin[bx]\r
135         imul    tblSin[si]\r
136         shrd    eax, edx, 24\r
137         imul    tblSin[di]\r
138         mov     ebp, eax\r
139         mov     ecx, edx\r
140         mov     eax, tblCos[bx]\r
141         imul    tblCos[di]\r
142         sub     eax, ebp\r
143         sbb     edx, ecx\r
144         mov     [YRotation.Y], edx\r
145 \r
146         mov     eax, tblCos[si]\r
147         imul    tblSin[di]\r
148         mov     [YRotation.Z], edx\r
149 \r
150 ; Set Z rotation\r
151         mov     eax, tblCos[bx]\r
152         imul    tblSin[si]\r
153         shrd    eax, edx, 24\r
154         imul    tblCos[di]\r
155         mov     ebp, eax\r
156         mov     ecx, edx\r
157         mov     eax, tblSin[bx]\r
158         imul    tblSin[di]\r
159         sub     eax, ebp\r
160         sbb     edx, ecx\r
161         mov     [ZRotation.X], edx\r
162 \r
163         mov     eax, tblSin[bx]\r
164         imul    tblSin[si]\r
165         shrd    eax, edx, 24\r
166         imul    tblCos[di]\r
167         mov     ebp, eax\r
168         mov     ecx, edx\r
169         mov     eax, tblCos[bx]\r
170         imul    tblSin[di]\r
171         add     eax, ebp\r
172         add     edx, ecx\r
173         neg     edx\r
174         mov     [ZRotation.Y], edx\r
175 \r
176         mov     eax, tblCos[si]\r
177         imul    tblCos[di]\r
178         mov     [ZRotation.Z], edx\r
179 \r
180         pop     ebp                     ; Restore EBP\r
181 \r
182         ret\r
183 tdSetRotation   ENDP\r
184 \r
185 ;-----------------------------------------------------------\r
186 ;\r
187 ; Sets the translation vector.\r
188 ;\r
189 ; Input:\r
190 ;       TV      = pointer to translation vector\r
191 ; Output:\r
192 ;       none\r
193 ;\r
194 tdSetTranslation        PROC PASCAL FAR\r
195         ARG     TV:DWORD\r
196         USES    ds, es, di\r
197 \r
198         mov     ax, SEG MATH_DATA\r
199         mov     ds, ax\r
200         ASSUME  ds:MATH_DATA\r
201 \r
202         les     di, [TV]\r
203         mov     eax, es:[di].X\r
204         mov     [Translation.X], eax\r
205         mov     eax, es:[di].Y\r
206         mov     [Translation.Y], eax\r
207         mov     eax, es:[di].Z\r
208         mov     [Translation.Z], eax\r
209 \r
210         ret\r
211 tdSetTranslation        ENDP\r
212 \r
213 ;-----------------------------------------------------------\r
214 ;\r
215 ; Transforms an array of TPOINT.\r
216 ;\r
217 ; Input:\r
218 ;       Source  = pointer to source array of TPOINT\r
219 ;       Dest    = pointer to destination array of TPOINT\r
220 ;       Count   = number of entries to transform\r
221 ; Output:\r
222 ;       none\r
223 ;\r
224 tdTransform     PROC PASCAL FAR\r
225         ARG     Source:DWORD,   \\r
226                 Dest:DWORD,     \\r
227                 Count:WORD\r
228         LOCAL   Adjust:DWORD\r
229         USES    ds, si, es, di, fs\r
230 \r
231         mov     ax, SEG MATH_DATA\r
232         mov     ds, ax\r
233         ASSUME  ds:MATH_DATA\r
234 \r
235         lfs     si, [Source]\r
236         les     di, [Dest]\r
237 \r
238         ALIGN   DWORD\r
239 @@Loop:\r
240 ; Transform Z coordinate\r
241         mov     eax, fs:[si].X\r
242         imul    [ZRotation.X]\r
243         mov     ecx, eax\r
244         mov     ebx, edx\r
245         mov     eax, fs:[si].Y\r
246         imul    [ZRotation.Y]\r
247         add     ecx, eax\r
248         adc     ebx, edx\r
249         mov     eax, fs:[si].Z\r
250         imul    [ZRotation.Z]\r
251         add     eax, ecx\r
252         adc     edx, ebx\r
253         mov     ebx, eax\r
254         shrd    eax, edx, 16\r
255         add     eax, [Translation.Z]    ; EAX = new Z coord (fixed 16:16)\r
256         mov     es:[di].Z, eax\r
257 ; Get perspective factor\r
258         mov     ebx, [PerspectiveDistance]\r
259         sub     eax, ebx\r
260         neg     eax                     ; EAX = PD - Z\r
261         xor     edx, edx\r
262         shld    edx, eax, 16\r
263         shl     eax, 16\r
264         idiv    ebx                     ; EAX = fixed 16:16 result\r
265         mov     [Adjust], eax\r
266 \r
267 ; Transform X coordinate\r
268         mov     eax, fs:[si].X\r
269         imul    [XRotation.X]\r
270         mov     ecx, eax\r
271         mov     ebx, edx\r
272         mov     eax, fs:[si].Y\r
273         imul    [XRotation.Y]\r
274         add     ecx, eax\r
275         adc     ebx, edx\r
276         mov     eax, fs:[si].Z\r
277         imul    [XRotation.Z]\r
278         add     eax, ecx\r
279         adc     edx, ebx\r
280         shrd    eax, edx, 16\r
281         add     eax, [Translation.X]\r
282         imul    [Adjust]\r
283         shrd    eax, edx, 16\r
284         mov     es:[di].X, eax\r
285 \r
286 ; Transform Y coordinate\r
287         mov     eax, fs:[si].X\r
288         imul    [YRotation.X]\r
289         mov     ecx, eax\r
290         mov     ebx, edx\r
291         mov     eax, fs:[si].Y\r
292         imul    [YRotation.Y]\r
293         add     ecx, eax\r
294         adc     ebx, edx\r
295         mov     eax, fs:[si].Z\r
296         imul    [YRotation.Z]\r
297         add     eax, ecx\r
298         adc     edx, ebx\r
299         shrd    eax, edx, 16\r
300         add     eax, [Translation.Y]\r
301         imul    [Adjust]\r
302         shrd    eax, edx, 16\r
303         mov     es:[di].Y, eax\r
304 \r
305         add     si, SIZE TPOINT\r
306         add     di, SIZE TPOINT\r
307         dec     [Count]\r
308         jnz     @@Loop\r
309 \r
310         ret\r
311 tdTransform     ENDP\r
312 \r
313 ;-----------------------------------------------------------\r
314 ;\r
315 ; Transforms an array of TPOINT into an array of TIMAGEPOINT.\r
316 ;\r
317 ; Input:\r
318 ;       Source  = pointer to source array of TPOINT\r
319 ;       Dest    = pointer to destination array of TIMAGEPOINT\r
320 ;       Count   = number of entries to transform\r
321 ;       DeltaX  = translation distance for the X coordinate\r
322 ;       DeltaY  = translation distance for the Y coordinate\r
323 ; Output:\r
324 ;       the maximum Z value\r
325 ;\r
326 tdTransformToImage      PROC PASCAL FAR\r
327         ARG     Source:DWORD,   \\r
328                 Dest:DWORD,     \\r
329                 Count:WORD,     \\r
330                 DeltaX:WORD,    \\r
331                 DeltaY:WORD\r
332         LOCAL   Adjust:DWORD,   \\r
333                 Max:DWORD\r
334         USES    ds, si, es, di, fs\r
335 \r
336         mov     ax, SEG MATH_DATA\r
337         mov     ds, ax\r
338         ASSUME  ds:MATH_DATA\r
339 \r
340         lfs     si, [Source]\r
341         les     di, [Dest]\r
342         mov     [Max], 80000000h\r
343 \r
344 @@Loop:\r
345 ; Check max Z\r
346         mov     eax, fs:[si].Z\r
347         cmp     eax, [Max]\r
348         jle     @@1\r
349         mov     [Max], eax\r
350 @@1:\r
351 \r
352 ; Transform X coordinate\r
353         mov     ax, WORD PTR fs:[si].X[2]\r
354         add     ax, [DeltaX]\r
355         mov     es:[di].IX, ax\r
356 \r
357 ; Transform Y coordinate\r
358         mov     ax, WORD PTR fs:[si].Y[2]\r
359         add     ax, [DeltaY]\r
360         mov     es:[di].IY, ax\r
361 \r
362         add     si, SIZE TPOINT\r
363         add     di, SIZE TIMAGEPOINT\r
364         dec     [Count]\r
365         jnz     @@Loop\r
366 \r
367         mov     eax, [Max]\r
368         shld    edx, eax, 16\r
369         ret\r
370 tdTransformToImage      ENDP\r
371 \r
372 ;-----------------------------------------------------------\r
373 ;\r
374 ; Sets the light source.\r
375 ;\r
376 ; Input:\r
377 ;       Light   = pointer to light vector\r
378 ; Output:\r
379 ;       none\r
380 ;\r
381 tdSetLight      PROC PASCAL FAR\r
382         ARG     L:DWORD\r
383         USES    ds, es, di\r
384 \r
385         mov     ax, SEG MATH_DATA\r
386         mov     ds, ax\r
387         ASSUME  ds:MATH_DATA\r
388 \r
389         les     di, [L]\r
390         mov     eax, es:[di].X\r
391         mov     [Light.X], eax\r
392         mov     eax, es:[di].Y\r
393         mov     [Light.Y], eax\r
394         mov     eax, es:[di].Z\r
395         mov     [Light.Z], eax\r
396 \r
397         ret\r
398 tdSetLight      ENDP\r
399 \r
400 ;-----------------------------------------------------------\r
401 ;\r
402 ; Computes light intensity for an array of surfaces.\r
403 ;\r
404 ; Input:\r
405 ;       Normals = pointer to an array of surface normals\r
406 ;       Lights  = pointer to an array of integer to be filled with\r
407 ;                 light intensity\r
408 ;       Count   = number of elements to transform\r
409 ; Output:\r
410 ;       none\r
411 ;\r
412 tdTransformLight        PROC PASCAL FAR\r
413         ARG     Normals:DWORD,  \\r
414                 Lights:DWORD,   \\r
415                 Count:WORD\r
416         USES    ds, si, es, di, fs\r
417 \r
418         mov     ax, SEG MATH_DATA\r
419         mov     fs, ax\r
420         ASSUME  fs:MATH_DATA\r
421 \r
422         lds     si, [Normals]\r
423         les     di, [Lights]\r
424         ASSUME  ds:NOTHING\r
425 \r
426 ; Intensity is given by the dot product between the Light vector and\r
427 ; the surface normal\r
428 @@Loop:\r
429         mov     eax, ds:[si].Z\r
430         imul    [Light.Z]\r
431         mov     ebx, eax\r
432         mov     ecx, edx\r
433         mov     eax, ds:[si].Y\r
434         imul    [Light.Y]\r
435         add     ebx, eax\r
436         adc     ecx, edx\r
437         mov     eax, ds:[si].X\r
438         imul    [Light.X]\r
439         add     eax, ebx\r
440         adc     edx, ecx                ; EDX:EAX = fixed 32:32 intensity\r
441         add     dx, [AmbientLight]\r
442         test    dx, dx\r
443         jg      @@1\r
444         xor     dx, dx                  ; Return 0 for no light\r
445 @@1:\r
446         mov     es:[di], dx\r
447         inc     di\r
448         inc     di\r
449         add     si, SIZE TPOINT\r
450         dec     [Count]\r
451         jnz     @@Loop\r
452 \r
453         ASSUME  fs:NOTHING\r
454         ret\r
455 tdTransformLight        ENDP\r
456 \r
457 ;-----------------------------------------------------------\r
458 ;\r
459 ; Returns the light value given the normal to a surface.\r
460 ;\r
461 ; Input:\r
462 ;       Normal  = pointer to TPOINT surface normal vector\r
463 ; Output:\r
464 ;       AX      = light intensity (>=0)\r
465 ; Notes:\r
466 ;       the normal is rotated according to the current setting.\r
467 ;\r
468 tdGetSurfaceLight       PROC PASCAL FAR\r
469         ARG     Normal:DWORD\r
470         USES    ds, esi, es, di\r
471 \r
472         mov     ax, SEG MATH_DATA\r
473         mov     ds, ax\r
474         ASSUME  ds:MATH_DATA\r
475 \r
476         les     di, [Normal]\r
477 \r
478 ; Transform Z coordinate\r
479         mov     eax, es:[di].X\r
480         imul    [ZRotation.X]\r
481         mov     ecx, eax\r
482         mov     ebx, edx\r
483         mov     eax, es:[di].Y\r
484         imul    [ZRotation.Y]\r
485         add     ecx, eax\r
486         adc     ebx, edx\r
487         mov     eax, es:[di].Z\r
488         imul    [ZRotation.Z]\r
489         add     eax, ecx\r
490         adc     edx, ebx\r
491         shrd    eax, edx, 16\r
492         imul    [Light.Z]\r
493         shrd    eax, edx, 16\r
494         mov     esi, eax\r
495 \r
496 ; Transform X coordinate\r
497         mov     eax, es:[di].X\r
498         imul    [XRotation.X]\r
499         mov     ecx, eax\r
500         mov     ebx, edx\r
501         mov     eax, es:[di].Y\r
502         imul    [XRotation.Y]\r
503         add     ecx, eax\r
504         adc     ebx, edx\r
505         mov     eax, es:[di].Z\r
506         imul    [XRotation.Z]\r
507         add     eax, ecx\r
508         adc     edx, ebx\r
509         shrd    eax, edx, 16\r
510         imul    [Light.X]\r
511         shrd    eax, edx, 16\r
512         add     esi, eax\r
513 \r
514 ; Transform Y coordinate\r
515         mov     eax, es:[di].X\r
516         imul    [YRotation.X]\r
517         mov     ecx, eax\r
518         mov     ebx, edx\r
519         mov     eax, es:[di].Y\r
520         imul    [YRotation.Y]\r
521         add     ecx, eax\r
522         adc     ebx, edx\r
523         mov     eax, es:[di].Z\r
524         imul    [YRotation.Z]\r
525         add     eax, ecx\r
526         adc     edx, ebx\r
527         shrd    eax, edx, 16\r
528         imul    [Light.X]\r
529         shrd    eax, edx, 16\r
530         add     eax, esi\r
531         shr     eax, 16\r
532 \r
533 ; Add ambient light\r
534         add     ax, [AmbientLight]\r
535         test    ax, ax\r
536         jge     @@Exit\r
537         xor     ax, ax\r
538 \r
539 @@Exit:\r
540         ret\r
541 tdGetSurfaceLight       ENDP\r
542 \r
543 ;-----------------------------------------------------------\r
544 ;\r
545 ; Rotates an array of TPOINT.\r
546 ;\r
547 ; Input:\r
548 ;       Source  = pointer to source array of TPOINT\r
549 ;       Dest    = pointer to destination array of TPOINT\r
550 ;       Count   = number of entries to transform\r
551 ; Output:\r
552 ;       none\r
553 ;\r
554 tdRotate        PROC PASCAL FAR\r
555         ARG     Source:DWORD,   \\r
556                 Dest:DWORD,     \\r
557                 Count:WORD\r
558         USES    ds, si, es, di, fs\r
559 \r
560         mov     ax, SEG MATH_DATA\r
561         mov     ds, ax\r
562         ASSUME  ds:MATH_DATA\r
563 \r
564         lfs     si, [Source]\r
565         les     di, [Dest]\r
566 \r
567 @@Loop:\r
568 ; Transform Z coordinate\r
569         mov     eax, fs:[si].X\r
570         imul    [ZRotation.X]\r
571         mov     ecx, eax\r
572         mov     ebx, edx\r
573         mov     eax, fs:[si].Y\r
574         imul    [ZRotation.Y]\r
575         add     ecx, eax\r
576         adc     ebx, edx\r
577         mov     eax, fs:[si].Z\r
578         imul    [ZRotation.Z]\r
579         add     eax, ecx\r
580         adc     edx, ebx\r
581         shrd    eax, edx, 16\r
582         mov     es:[di].Z, eax\r
583 \r
584 ; Transform X coordinate\r
585         mov     eax, fs:[si].X\r
586         imul    [XRotation.X]\r
587         mov     ecx, eax\r
588         mov     ebx, edx\r
589         mov     eax, fs:[si].Y\r
590         imul    [XRotation.Y]\r
591         add     ecx, eax\r
592         adc     ebx, edx\r
593         mov     eax, fs:[si].Z\r
594         imul    [XRotation.Z]\r
595         add     eax, ecx\r
596         adc     edx, ebx\r
597         shrd    eax, edx, 16\r
598         mov     es:[di].X, eax\r
599 \r
600 ; Transform Y coordinate\r
601         mov     eax, fs:[si].X\r
602         imul    [YRotation.X]\r
603         mov     ecx, eax\r
604         mov     ebx, edx\r
605         mov     eax, fs:[si].Y\r
606         imul    [YRotation.Y]\r
607         add     ecx, eax\r
608         adc     ebx, edx\r
609         mov     eax, fs:[si].Z\r
610         imul    [YRotation.Z]\r
611         add     eax, ecx\r
612         adc     edx, ebx\r
613         shrd    eax, edx, 16\r
614         mov     es:[di].Y, eax\r
615 \r
616         add     si, SIZE TPOINT\r
617         add     di, SIZE TPOINT\r
618         dec     [Count]\r
619         jnz     @@Loop\r
620 \r
621         ret\r
622 tdRotate        ENDP\r
623 \r
624 tdFixedMul      PROC PASCAL FAR\r
625         ARG     F1:DWORD,       \\r
626                 F2:DWORD\r
627 \r
628         mov     eax, [F1]\r
629         imul    [F2]\r
630         shr     eax, 16\r
631 \r
632         ret\r
633 tdFixedMul      ENDP\r
634 \r
635 ;-----------------------------------------------------------\r
636 ;\r
637 ; Returns in EAX the square root of EDX:EAX.\r
638 ;\r
639 subSqrt PROC NEAR\r
640         push    esi\r
641         push    edi\r
642 \r
643         add     eax, eax\r
644         adc     edx, 0\r
645         mov     eax, edx                ; Just discard the low bits\r
646 \r
647         mov     esi, eax\r
648         xor     edi, edi\r
649         shld    edi, esi, 16\r
650         shl     esi, 16\r
651 @@Loop:\r
652         mov     ebx, eax\r
653         mul     eax\r
654         add     eax, esi\r
655         adc     edx, edi\r
656         shrd    eax, edx, 1\r
657         shr     edx, 1\r
658         div     ebx\r
659         cmp     eax, ebx\r
660         jne     @@Loop\r
661 \r
662 ; Adjust EAX\r
663         shl     eax, 8\r
664 \r
665         pop     edi\r
666         pop     esi\r
667         ret\r
668 subSqrt ENDP\r
669 \r
670 ;-----------------------------------------------------------\r
671 ;\r
672 ; Finds the unitary normal to a given surface.\r
673 ;\r
674 ; Input:\r
675 ;       Dest            = pointer to TPOINT (vector) result\r
676 ;       P1, P2, P3      = pointer to TPOINT points on surface\r
677 ; Output:\r
678 ;       none\r
679 ; Notes:\r
680 ;       the normal is given by the cross-product between (P3-P1) and\r
681 ;       (P2-P1), so its orientation depends on the parameters order.\r
682 ;\r
683 tdGetNormal     PROC PASCAL FAR\r
684         ARG     Dest:DWORD,     \\r
685                 P1:DWORD,       \\r
686                 P2:DWORD,       \\r
687                 P3:DWORD\r
688         LOCAL   V1:TPOINT,      \\r
689                 V2:TPOINT,      \\r
690                 N:TPOINT\r
691         USES    ds, si, es, di\r
692 \r
693 ; Get vector V1\r
694         lds     si, [P1]\r
695         les     di, [P3]\r
696         mov     eax, es:[di].X\r
697         sub     eax, ds:[si].X\r
698         mov     [V1.X], eax\r
699         mov     eax, es:[di].Y\r
700         sub     eax, ds:[si].Y\r
701         mov     [V1.Y], eax\r
702         mov     eax, es:[di].Z\r
703         sub     eax, ds:[si].Z\r
704         mov     [V1.Z], eax\r
705 \r
706 ; Get vector V2\r
707         les     di, [P2]\r
708         mov     eax, es:[di].X\r
709         sub     eax, ds:[si].X\r
710         mov     [V2.X], eax\r
711         mov     eax, es:[di].Y\r
712         sub     eax, ds:[si].Y\r
713         mov     [V2.Y], eax\r
714         mov     eax, es:[di].Z\r
715         sub     eax, ds:[si].Z\r
716         mov     [V2.Z], eax\r
717 \r
718 ; Get normal vector (V1 x V2)\r
719         mov     eax, [V1.Z]\r
720         imul    [V2.Y]\r
721         mov     ebx, eax\r
722         mov     ecx, edx\r
723         mov     eax, [V1.Y]\r
724         imul    [V2.Z]\r
725         sub     eax, ebx\r
726         sbb     edx, ecx\r
727         shrd    eax, edx, 16\r
728         mov     [N.X], eax\r
729 \r
730         mov     eax, [V1.X]\r
731         imul    [V2.Z]\r
732         mov     ebx, eax\r
733         mov     ecx, edx\r
734         mov     eax, [V1.Z]\r
735         imul    [V2.X]\r
736         sub     eax, ebx\r
737         sbb     edx, ecx\r
738         shrd    eax, edx, 16\r
739         mov     [N.Y], eax\r
740 \r
741         mov     eax, [V1.Y]\r
742         imul    [V2.X]\r
743         mov     ebx, eax\r
744         mov     ecx, edx\r
745         mov     eax, [V1.X]\r
746         imul    [V2.Y]\r
747         sub     eax, ebx\r
748         sbb     edx, ecx\r
749         shrd    eax, edx, 16\r
750         mov     [N.Z], eax\r
751 \r
752 ; Get normal length\r
753         mov     eax, [N.X]\r
754         imul    eax\r
755         mov     ebx, eax\r
756         mov     ecx, edx\r
757         mov     eax, [N.Y]\r
758         imul    eax\r
759         add     ebx, eax\r
760         adc     ecx, edx\r
761         mov     eax, [N.Z]\r
762         imul    eax\r
763         add     eax, ebx\r
764         adc     edx, ecx                ; EDX:EAX = N.X*N.X + N.Y*N.Y + N.Z*N.Z\r
765         call    subSqrt                 ; EAX = normal length\r
766         mov     ebx, eax\r
767 \r
768 ; Adjust vector and save it\r
769         les     di, [Dest]\r
770         mov     eax, [N.X]\r
771         cdq\r
772         shld    edx, eax, 16\r
773         shl     eax, 16\r
774         idiv    ebx\r
775         mov     es:[di].X, eax\r
776         mov     eax, [N.Y]\r
777         cdq\r
778         shld    edx, eax, 16\r
779         shl     eax, 16\r
780         idiv    ebx\r
781         mov     es:[di].Y, eax\r
782         mov     eax, [N.Z]\r
783         cdq\r
784         shld    edx, eax, 16\r
785         shl     eax, 16\r
786         idiv    ebx\r
787         mov     es:[di].Z, eax\r
788 \r
789         ret\r
790 tdGetNormal     ENDP\r
791 \r
792 TPOLY   STRUC\r
793         Vtx     DW      4 DUP(?)\r
794 TPOLY   ENDS\r
795 \r
796 ;-----------------------------------------------------------\r
797 ;\r
798 ; Performs surface removal on an array of polygons.\r
799 ;\r
800 ; Input:\r
801 ;       Poly    = pointer to an array of TPOLY\r
802 ;       Vertex  = pointer to an array of TPOINT\r
803 ;       Dest    = pointer to an array of integer\r
804 ;       Count   = number of polygons to check\r
805 ;       Step    = size of TPOLY structure\r
806 ; Output:\r
807 ;       if the n-th polygon is invisible the n-th entry of the\r
808 ;       Dest array is set to -1, other entries are not modified\r
809 ;       (so it's possible to use the Light array for Dest, because\r
810 ;       the light intensity is always >= 0)\r
811 ;\r
812 tdBackPlaneCull PROC PASCAL FAR\r
813         ARG     Step:WORD,      \\r
814                 Poly:DWORD,     \\r
815                 Vertex:DWORD,   \\r
816                 Dest:DWORD,     \\r
817                 Count:WORD\r
818         USES    ds, si, es, di, fs\r
819         ASSUME  ds:NOTHING\r
820 \r
821         mov     ds, WORD PTR Vertex[2]\r
822         les     di, [Poly]\r
823         mov     fs, WORD PTR Dest[2]\r
824 \r
825 @@Loop:\r
826         mov     ax, es:[di].Vtx[2]      ; Index of 2nd vertex\r
827         shl     ax, 2\r
828         mov     bx, ax\r
829         shl     ax, 1\r
830         add     bx, ax                  ; BX = index*SIZE TPOINT\r
831         add     bx, WORD PTR [Vertex]   ; BX = offset of 2nd vertex\r
832         mov     ax, es:[di].Vtx[4]      ; Index of 3rd vertex\r
833         shl     ax, 2\r
834         mov     si, ax\r
835         shl     ax, 1\r
836         add     si, ax\r
837         add     si, WORD PTR [Vertex]   ; SI = offset of 3rd vertex\r
838         mov     ecx, ds:[si].X\r
839         sub     ecx, ds:[bx].X          ; ECX = V3.X-V2.X\r
840         mov     edx, ds:[si].Y\r
841         sub     edx, ds:[bx].Y          ; EDX = V3.Y-V2.Y\r
842         mov     ax, es:[di].Vtx[0]      ; Index of 1st vertex\r
843         shl     ax, 2\r
844         mov     si, ax\r
845         shl     ax, 1\r
846         add     si, ax\r
847         add     si, WORD PTR [Vertex]   ; SI = offset of 1st vertex\r
848         mov     eax, ds:[si].X\r
849         sub     eax, ds:[bx].X          ; EAX = V1.X-V2.X\r
850         mov     esi, ds:[si].Y\r
851         sub     esi, ds:[bx].Y          ; ESI = V1.Y-V2.Y\r
852         imul    edx\r
853         mov     ebx, eax\r
854         xchg    ecx, edx                ; ECX:EBX = (V1.X-V2.X)*(V3.Y-V2.Y)\r
855         mov     eax, esi\r
856         imul    edx                     ; EDX:EAX = (V1.Y-V2.Y)*(V3.X-V2.X)\r
857         sub     eax, ebx\r
858         sbb     edx, ecx\r
859         jl      @@Next                  ; Polygon is visible\r
860         mov     bx, WORD PTR [Dest]     ; FS:BX -> current Dest entry\r
861         mov     WORD PTR fs:[bx], -1    ; Remove polygon\r
862 @@Next:\r
863         add     WORD PTR [Dest], 2      ; Next entry for dest\r
864         add     di, [Step]              ; Next polygon\r
865         dec     [Count]\r
866         jnz     @@Loop\r
867 \r
868         ret\r
869 tdBackPlaneCull ENDP\r
870 \r
871 MATH_TEXT       ENDS\r
872 END\r