+++ /dev/null
-COMMENT /\r
- Fixed-point math functions and 3D transforms\r
- Copyright (c) 1993,94 by Alessandro Scotti\r
-/\r
-WARN PRO\r
-P386\r
-JUMPS\r
-LOCALS\r
-\r
-INCLUDE MATH.INC\r
-\r
-PUBLIC tdFixedMul\r
-PUBLIC tdGetNormal\r
-PUBLIC tdRotate\r
-PUBLIC tdGetSurfaceLight\r
-PUBLIC tdSetLight\r
-PUBLIC tdSetRotation\r
-PUBLIC tdSetTranslation\r
-PUBLIC tdTransform\r
-PUBLIC tdTransformToImage\r
-PUBLIC tdTransformLight\r
-PUBLIC tdBackPlaneCull\r
-PUBLIC tdSetPerspective\r
-\r
-;-----------------------------------------------------------\r
-;\r
-; Data segment\r
-;\r
-MATH_DATA SEGMENT USE16 PARA PUBLIC 'DATA'\r
- ASSUME ds:MATH_DATA\r
-\r
-INCLUDE SINCOS.INC ; Fixed 8:24 sin/cos table\r
-\r
-XRotation TPOINT <> ; 3x3 rotation matrix\r
-YRotation TPOINT <>\r
-ZRotation TPOINT <>\r
-\r
-Translation TPOINT <> ; Translation vector\r
-\r
-Light TPOINT <> ; Light vector\r
-AmbientLight DW 00 ; Ambient light\r
-\r
-XScale DD 10000h ; Scaling factor for X coordinate\r
-YScale DD 10000h ; Scaling factor for Y coordinate\r
-PerspectiveDistance DD 20000000h\r
-\r
-MATH_DATA ENDS\r
-\r
-;-----------------------------------------------------------\r
-;\r
-; Code segment\r
-;\r
-MATH_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
- ASSUME cs:MATH_TEXT, es:NOTHING, fs:NOTHING\r
-\r
-tdSetPerspective PROC PASCAL FAR\r
- ARG Perspective:DWORD, \\r
- ScaleX:DWORD, \\r
- ScaleY:DWORD\r
- USES ds\r
-\r
- mov ax, SEG MATH_DATA\r
- mov ds, ax\r
- ASSUME ds:MATH_DATA\r
-\r
- mov eax, [Perspective]\r
- mov [PerspectiveDistance], eax\r
- mov eax, [ScaleX]\r
- mov [XScale], eax\r
- mov eax, [ScaleY]\r
- mov [YScale], eax\r
-\r
- ret\r
-tdSetPerspective ENDP\r
-\r
-\r
-;-----------------------------------------------------------\r
-;\r
-; Sets the rotation matrix.\r
-;\r
-; Input:\r
-; RX = X-axis rotation angle\r
-; RY = X-axis rotation angle\r
-; RZ = X-axis rotation angle\r
-; Output:\r
-; none\r
-;\r
-tdSetRotation PROC PASCAL FAR\r
- ARG RX:WORD, \\r
- RY:WORD, \\r
- RZ:WORD\r
- USES ds, si, di\r
-\r
- mov ax, SEG MATH_DATA\r
- mov ds, ax\r
- ASSUME ds:MATH_DATA\r
-\r
- mov bx, [RZ]\r
- mov si, [RY]\r
- mov di, [RX]\r
- shl bx, 2\r
- shl si, 2\r
- shl di, 2\r
-\r
- push ebp ; We use EBP as a scratch register\r
-\r
-; Set X rotation\r
- mov eax, tblCos[bx]\r
- imul tblCos[si]\r
- mov [XRotation.X], edx\r
-\r
- mov eax, tblSin[bx]\r
- imul tblCos[si]\r
- mov [XRotation.Y], edx\r
-\r
- mov eax, tblSin[si]\r
- sar eax, 8 ; Convert fixed 8:24 to fixed 16:16\r
- mov [XRotation.Z], eax\r
-\r
-; Set Y rotation\r
- mov eax, tblCos[bx]\r
- imul tblSin[si] ; EDX:EAX = fixed 16:48\r
- shrd eax, edx, 24 ; EAX = fixed 8:24\r
- imul tblSin[di] ; EDX:EAX = fixed 16:48\r
- mov ebp, eax\r
- mov ecx, edx\r
- mov eax, tblSin[bx]\r
- imul tblCos[di]\r
- add eax, ebp\r
- adc edx, ecx ; EDX:EAX = fixed 16:48\r
- neg edx\r
- mov [YRotation.X], edx\r
-\r
- mov eax, tblSin[bx]\r
- imul tblSin[si]\r
- shrd eax, edx, 24\r
- imul tblSin[di]\r
- mov ebp, eax\r
- mov ecx, edx\r
- mov eax, tblCos[bx]\r
- imul tblCos[di]\r
- sub eax, ebp\r
- sbb edx, ecx\r
- mov [YRotation.Y], edx\r
-\r
- mov eax, tblCos[si]\r
- imul tblSin[di]\r
- mov [YRotation.Z], edx\r
-\r
-; Set Z rotation\r
- mov eax, tblCos[bx]\r
- imul tblSin[si]\r
- shrd eax, edx, 24\r
- imul tblCos[di]\r
- mov ebp, eax\r
- mov ecx, edx\r
- mov eax, tblSin[bx]\r
- imul tblSin[di]\r
- sub eax, ebp\r
- sbb edx, ecx\r
- mov [ZRotation.X], edx\r
-\r
- mov eax, tblSin[bx]\r
- imul tblSin[si]\r
- shrd eax, edx, 24\r
- imul tblCos[di]\r
- mov ebp, eax\r
- mov ecx, edx\r
- mov eax, tblCos[bx]\r
- imul tblSin[di]\r
- add eax, ebp\r
- add edx, ecx\r
- neg edx\r
- mov [ZRotation.Y], edx\r
-\r
- mov eax, tblCos[si]\r
- imul tblCos[di]\r
- mov [ZRotation.Z], edx\r
-\r
- pop ebp ; Restore EBP\r
-\r
- ret\r
-tdSetRotation ENDP\r
-\r
-;-----------------------------------------------------------\r
-;\r
-; Sets the translation vector.\r
-;\r
-; Input:\r
-; TV = pointer to translation vector\r
-; Output:\r
-; none\r
-;\r
-tdSetTranslation PROC PASCAL FAR\r
- ARG TV:DWORD\r
- USES ds, es, di\r
-\r
- mov ax, SEG MATH_DATA\r
- mov ds, ax\r
- ASSUME ds:MATH_DATA\r
-\r
- les di, [TV]\r
- mov eax, es:[di].X\r
- mov [Translation.X], eax\r
- mov eax, es:[di].Y\r
- mov [Translation.Y], eax\r
- mov eax, es:[di].Z\r
- mov [Translation.Z], eax\r
-\r
- ret\r
-tdSetTranslation ENDP\r
-\r
-;-----------------------------------------------------------\r
-;\r
-; Transforms an array of TPOINT.\r
-;\r
-; Input:\r
-; Source = pointer to source array of TPOINT\r
-; Dest = pointer to destination array of TPOINT\r
-; Count = number of entries to transform\r
-; Output:\r
-; none\r
-;\r
-tdTransform PROC PASCAL FAR\r
- ARG Source:DWORD, \\r
- Dest:DWORD, \\r
- Count:WORD\r
- LOCAL Adjust:DWORD\r
- USES ds, si, es, di, fs\r
-\r
- mov ax, SEG MATH_DATA\r
- mov ds, ax\r
- ASSUME ds:MATH_DATA\r
-\r
- lfs si, [Source]\r
- les di, [Dest]\r
-\r
- ALIGN DWORD\r
-@@Loop:\r
-; Transform Z coordinate\r
- mov eax, fs:[si].X\r
- imul [ZRotation.X]\r
- mov ecx, eax\r
- mov ebx, edx\r
- mov eax, fs:[si].Y\r
- imul [ZRotation.Y]\r
- add ecx, eax\r
- adc ebx, edx\r
- mov eax, fs:[si].Z\r
- imul [ZRotation.Z]\r
- add eax, ecx\r
- adc edx, ebx\r
- mov ebx, eax\r
- shrd eax, edx, 16\r
- add eax, [Translation.Z] ; EAX = new Z coord (fixed 16:16)\r
- mov es:[di].Z, eax\r
-; Get perspective factor\r
- mov ebx, [PerspectiveDistance]\r
- sub eax, ebx\r
- neg eax ; EAX = PD - Z\r
- xor edx, edx\r
- shld edx, eax, 16\r
- shl eax, 16\r
- idiv ebx ; EAX = fixed 16:16 result\r
- mov [Adjust], eax\r
-\r
-; Transform X coordinate\r
- mov eax, fs:[si].X\r
- imul [XRotation.X]\r
- mov ecx, eax\r
- mov ebx, edx\r
- mov eax, fs:[si].Y\r
- imul [XRotation.Y]\r
- add ecx, eax\r
- adc ebx, edx\r
- mov eax, fs:[si].Z\r
- imul [XRotation.Z]\r
- add eax, ecx\r
- adc edx, ebx\r
- shrd eax, edx, 16\r
- add eax, [Translation.X]\r
- imul [Adjust]\r
- shrd eax, edx, 16\r
- mov es:[di].X, eax\r
-\r
-; Transform Y coordinate\r
- mov eax, fs:[si].X\r
- imul [YRotation.X]\r
- mov ecx, eax\r
- mov ebx, edx\r
- mov eax, fs:[si].Y\r
- imul [YRotation.Y]\r
- add ecx, eax\r
- adc ebx, edx\r
- mov eax, fs:[si].Z\r
- imul [YRotation.Z]\r
- add eax, ecx\r
- adc edx, ebx\r
- shrd eax, edx, 16\r
- add eax, [Translation.Y]\r
- imul [Adjust]\r
- shrd eax, edx, 16\r
- mov es:[di].Y, eax\r
-\r
- add si, SIZE TPOINT\r
- add di, SIZE TPOINT\r
- dec [Count]\r
- jnz @@Loop\r
-\r
- ret\r
-tdTransform ENDP\r
-\r
-;-----------------------------------------------------------\r
-;\r
-; Transforms an array of TPOINT into an array of TIMAGEPOINT.\r
-;\r
-; Input:\r
-; Source = pointer to source array of TPOINT\r
-; Dest = pointer to destination array of TIMAGEPOINT\r
-; Count = number of entries to transform\r
-; DeltaX = translation distance for the X coordinate\r
-; DeltaY = translation distance for the Y coordinate\r
-; Output:\r
-; the maximum Z value\r
-;\r
-tdTransformToImage PROC PASCAL FAR\r
- ARG Source:DWORD, \\r
- Dest:DWORD, \\r
- Count:WORD, \\r
- DeltaX:WORD, \\r
- DeltaY:WORD\r
- LOCAL Adjust:DWORD, \\r
- Max:DWORD\r
- USES ds, si, es, di, fs\r
-\r
- mov ax, SEG MATH_DATA\r
- mov ds, ax\r
- ASSUME ds:MATH_DATA\r
-\r
- lfs si, [Source]\r
- les di, [Dest]\r
- mov [Max], 80000000h\r
-\r
-@@Loop:\r
-; Check max Z\r
- mov eax, fs:[si].Z\r
- cmp eax, [Max]\r
- jle @@1\r
- mov [Max], eax\r
-@@1:\r
-\r
-; Transform X coordinate\r
- mov ax, WORD PTR fs:[si].X[2]\r
- add ax, [DeltaX]\r
- mov es:[di].IX, ax\r
-\r
-; Transform Y coordinate\r
- mov ax, WORD PTR fs:[si].Y[2]\r
- add ax, [DeltaY]\r
- mov es:[di].IY, ax\r
-\r
- add si, SIZE TPOINT\r
- add di, SIZE TIMAGEPOINT\r
- dec [Count]\r
- jnz @@Loop\r
-\r
- mov eax, [Max]\r
- shld edx, eax, 16\r
- ret\r
-tdTransformToImage ENDP\r
-\r
-;-----------------------------------------------------------\r
-;\r
-; Sets the light source.\r
-;\r
-; Input:\r
-; Light = pointer to light vector\r
-; Output:\r
-; none\r
-;\r
-tdSetLight PROC PASCAL FAR\r
- ARG L:DWORD\r
- USES ds, es, di\r
-\r
- mov ax, SEG MATH_DATA\r
- mov ds, ax\r
- ASSUME ds:MATH_DATA\r
-\r
- les di, [L]\r
- mov eax, es:[di].X\r
- mov [Light.X], eax\r
- mov eax, es:[di].Y\r
- mov [Light.Y], eax\r
- mov eax, es:[di].Z\r
- mov [Light.Z], eax\r
-\r
- ret\r
-tdSetLight ENDP\r
-\r
-;-----------------------------------------------------------\r
-;\r
-; Computes light intensity for an array of surfaces.\r
-;\r
-; Input:\r
-; Normals = pointer to an array of surface normals\r
-; Lights = pointer to an array of integer to be filled with\r
-; light intensity\r
-; Count = number of elements to transform\r
-; Output:\r
-; none\r
-;\r
-tdTransformLight PROC PASCAL FAR\r
- ARG Normals:DWORD, \\r
- Lights:DWORD, \\r
- Count:WORD\r
- USES ds, si, es, di, fs\r
-\r
- mov ax, SEG MATH_DATA\r
- mov fs, ax\r
- ASSUME fs:MATH_DATA\r
-\r
- lds si, [Normals]\r
- les di, [Lights]\r
- ASSUME ds:NOTHING\r
-\r
-; Intensity is given by the dot product between the Light vector and\r
-; the surface normal\r
-@@Loop:\r
- mov eax, ds:[si].Z\r
- imul [Light.Z]\r
- mov ebx, eax\r
- mov ecx, edx\r
- mov eax, ds:[si].Y\r
- imul [Light.Y]\r
- add ebx, eax\r
- adc ecx, edx\r
- mov eax, ds:[si].X\r
- imul [Light.X]\r
- add eax, ebx\r
- adc edx, ecx ; EDX:EAX = fixed 32:32 intensity\r
- add dx, [AmbientLight]\r
- test dx, dx\r
- jg @@1\r
- xor dx, dx ; Return 0 for no light\r
-@@1:\r
- mov es:[di], dx\r
- inc di\r
- inc di\r
- add si, SIZE TPOINT\r
- dec [Count]\r
- jnz @@Loop\r
-\r
- ASSUME fs:NOTHING\r
- ret\r
-tdTransformLight ENDP\r
-\r
-;-----------------------------------------------------------\r
-;\r
-; Returns the light value given the normal to a surface.\r
-;\r
-; Input:\r
-; Normal = pointer to TPOINT surface normal vector\r
-; Output:\r
-; AX = light intensity (>=0)\r
-; Notes:\r
-; the normal is rotated according to the current setting.\r
-;\r
-tdGetSurfaceLight PROC PASCAL FAR\r
- ARG Normal:DWORD\r
- USES ds, esi, es, di\r
-\r
- mov ax, SEG MATH_DATA\r
- mov ds, ax\r
- ASSUME ds:MATH_DATA\r
-\r
- les di, [Normal]\r
-\r
-; Transform Z coordinate\r
- mov eax, es:[di].X\r
- imul [ZRotation.X]\r
- mov ecx, eax\r
- mov ebx, edx\r
- mov eax, es:[di].Y\r
- imul [ZRotation.Y]\r
- add ecx, eax\r
- adc ebx, edx\r
- mov eax, es:[di].Z\r
- imul [ZRotation.Z]\r
- add eax, ecx\r
- adc edx, ebx\r
- shrd eax, edx, 16\r
- imul [Light.Z]\r
- shrd eax, edx, 16\r
- mov esi, eax\r
-\r
-; Transform X coordinate\r
- mov eax, es:[di].X\r
- imul [XRotation.X]\r
- mov ecx, eax\r
- mov ebx, edx\r
- mov eax, es:[di].Y\r
- imul [XRotation.Y]\r
- add ecx, eax\r
- adc ebx, edx\r
- mov eax, es:[di].Z\r
- imul [XRotation.Z]\r
- add eax, ecx\r
- adc edx, ebx\r
- shrd eax, edx, 16\r
- imul [Light.X]\r
- shrd eax, edx, 16\r
- add esi, eax\r
-\r
-; Transform Y coordinate\r
- mov eax, es:[di].X\r
- imul [YRotation.X]\r
- mov ecx, eax\r
- mov ebx, edx\r
- mov eax, es:[di].Y\r
- imul [YRotation.Y]\r
- add ecx, eax\r
- adc ebx, edx\r
- mov eax, es:[di].Z\r
- imul [YRotation.Z]\r
- add eax, ecx\r
- adc edx, ebx\r
- shrd eax, edx, 16\r
- imul [Light.X]\r
- shrd eax, edx, 16\r
- add eax, esi\r
- shr eax, 16\r
-\r
-; Add ambient light\r
- add ax, [AmbientLight]\r
- test ax, ax\r
- jge @@Exit\r
- xor ax, ax\r
-\r
-@@Exit:\r
- ret\r
-tdGetSurfaceLight ENDP\r
-\r
-;-----------------------------------------------------------\r
-;\r
-; Rotates an array of TPOINT.\r
-;\r
-; Input:\r
-; Source = pointer to source array of TPOINT\r
-; Dest = pointer to destination array of TPOINT\r
-; Count = number of entries to transform\r
-; Output:\r
-; none\r
-;\r
-tdRotate PROC PASCAL FAR\r
- ARG Source:DWORD, \\r
- Dest:DWORD, \\r
- Count:WORD\r
- USES ds, si, es, di, fs\r
-\r
- mov ax, SEG MATH_DATA\r
- mov ds, ax\r
- ASSUME ds:MATH_DATA\r
-\r
- lfs si, [Source]\r
- les di, [Dest]\r
-\r
-@@Loop:\r
-; Transform Z coordinate\r
- mov eax, fs:[si].X\r
- imul [ZRotation.X]\r
- mov ecx, eax\r
- mov ebx, edx\r
- mov eax, fs:[si].Y\r
- imul [ZRotation.Y]\r
- add ecx, eax\r
- adc ebx, edx\r
- mov eax, fs:[si].Z\r
- imul [ZRotation.Z]\r
- add eax, ecx\r
- adc edx, ebx\r
- shrd eax, edx, 16\r
- mov es:[di].Z, eax\r
-\r
-; Transform X coordinate\r
- mov eax, fs:[si].X\r
- imul [XRotation.X]\r
- mov ecx, eax\r
- mov ebx, edx\r
- mov eax, fs:[si].Y\r
- imul [XRotation.Y]\r
- add ecx, eax\r
- adc ebx, edx\r
- mov eax, fs:[si].Z\r
- imul [XRotation.Z]\r
- add eax, ecx\r
- adc edx, ebx\r
- shrd eax, edx, 16\r
- mov es:[di].X, eax\r
-\r
-; Transform Y coordinate\r
- mov eax, fs:[si].X\r
- imul [YRotation.X]\r
- mov ecx, eax\r
- mov ebx, edx\r
- mov eax, fs:[si].Y\r
- imul [YRotation.Y]\r
- add ecx, eax\r
- adc ebx, edx\r
- mov eax, fs:[si].Z\r
- imul [YRotation.Z]\r
- add eax, ecx\r
- adc edx, ebx\r
- shrd eax, edx, 16\r
- mov es:[di].Y, eax\r
-\r
- add si, SIZE TPOINT\r
- add di, SIZE TPOINT\r
- dec [Count]\r
- jnz @@Loop\r
-\r
- ret\r
-tdRotate ENDP\r
-\r
-tdFixedMul PROC PASCAL FAR\r
- ARG F1:DWORD, \\r
- F2:DWORD\r
-\r
- mov eax, [F1]\r
- imul [F2]\r
- shr eax, 16\r
-\r
- ret\r
-tdFixedMul ENDP\r
-\r
-;-----------------------------------------------------------\r
-;\r
-; Returns in EAX the square root of EDX:EAX.\r
-;\r
-subSqrt PROC NEAR\r
- push esi\r
- push edi\r
-\r
- add eax, eax\r
- adc edx, 0\r
- mov eax, edx ; Just discard the low bits\r
-\r
- mov esi, eax\r
- xor edi, edi\r
- shld edi, esi, 16\r
- shl esi, 16\r
-@@Loop:\r
- mov ebx, eax\r
- mul eax\r
- add eax, esi\r
- adc edx, edi\r
- shrd eax, edx, 1\r
- shr edx, 1\r
- div ebx\r
- cmp eax, ebx\r
- jne @@Loop\r
-\r
-; Adjust EAX\r
- shl eax, 8\r
-\r
- pop edi\r
- pop esi\r
- ret\r
-subSqrt ENDP\r
-\r
-;-----------------------------------------------------------\r
-;\r
-; Finds the unitary normal to a given surface.\r
-;\r
-; Input:\r
-; Dest = pointer to TPOINT (vector) result\r
-; P1, P2, P3 = pointer to TPOINT points on surface\r
-; Output:\r
-; none\r
-; Notes:\r
-; the normal is given by the cross-product between (P3-P1) and\r
-; (P2-P1), so its orientation depends on the parameters order.\r
-;\r
-tdGetNormal PROC PASCAL FAR\r
- ARG Dest:DWORD, \\r
- P1:DWORD, \\r
- P2:DWORD, \\r
- P3:DWORD\r
- LOCAL V1:TPOINT, \\r
- V2:TPOINT, \\r
- N:TPOINT\r
- USES ds, si, es, di\r
-\r
-; Get vector V1\r
- lds si, [P1]\r
- les di, [P3]\r
- mov eax, es:[di].X\r
- sub eax, ds:[si].X\r
- mov [V1.X], eax\r
- mov eax, es:[di].Y\r
- sub eax, ds:[si].Y\r
- mov [V1.Y], eax\r
- mov eax, es:[di].Z\r
- sub eax, ds:[si].Z\r
- mov [V1.Z], eax\r
-\r
-; Get vector V2\r
- les di, [P2]\r
- mov eax, es:[di].X\r
- sub eax, ds:[si].X\r
- mov [V2.X], eax\r
- mov eax, es:[di].Y\r
- sub eax, ds:[si].Y\r
- mov [V2.Y], eax\r
- mov eax, es:[di].Z\r
- sub eax, ds:[si].Z\r
- mov [V2.Z], eax\r
-\r
-; Get normal vector (V1 x V2)\r
- mov eax, [V1.Z]\r
- imul [V2.Y]\r
- mov ebx, eax\r
- mov ecx, edx\r
- mov eax, [V1.Y]\r
- imul [V2.Z]\r
- sub eax, ebx\r
- sbb edx, ecx\r
- shrd eax, edx, 16\r
- mov [N.X], eax\r
-\r
- mov eax, [V1.X]\r
- imul [V2.Z]\r
- mov ebx, eax\r
- mov ecx, edx\r
- mov eax, [V1.Z]\r
- imul [V2.X]\r
- sub eax, ebx\r
- sbb edx, ecx\r
- shrd eax, edx, 16\r
- mov [N.Y], eax\r
-\r
- mov eax, [V1.Y]\r
- imul [V2.X]\r
- mov ebx, eax\r
- mov ecx, edx\r
- mov eax, [V1.X]\r
- imul [V2.Y]\r
- sub eax, ebx\r
- sbb edx, ecx\r
- shrd eax, edx, 16\r
- mov [N.Z], eax\r
-\r
-; Get normal length\r
- mov eax, [N.X]\r
- imul eax\r
- mov ebx, eax\r
- mov ecx, edx\r
- mov eax, [N.Y]\r
- imul eax\r
- add ebx, eax\r
- adc ecx, edx\r
- mov eax, [N.Z]\r
- imul eax\r
- add eax, ebx\r
- adc edx, ecx ; EDX:EAX = N.X*N.X + N.Y*N.Y + N.Z*N.Z\r
- call subSqrt ; EAX = normal length\r
- mov ebx, eax\r
-\r
-; Adjust vector and save it\r
- les di, [Dest]\r
- mov eax, [N.X]\r
- cdq\r
- shld edx, eax, 16\r
- shl eax, 16\r
- idiv ebx\r
- mov es:[di].X, eax\r
- mov eax, [N.Y]\r
- cdq\r
- shld edx, eax, 16\r
- shl eax, 16\r
- idiv ebx\r
- mov es:[di].Y, eax\r
- mov eax, [N.Z]\r
- cdq\r
- shld edx, eax, 16\r
- shl eax, 16\r
- idiv ebx\r
- mov es:[di].Z, eax\r
-\r
- ret\r
-tdGetNormal ENDP\r
-\r
-TPOLY STRUC\r
- Vtx DW 4 DUP(?)\r
-TPOLY ENDS\r
-\r
-;-----------------------------------------------------------\r
-;\r
-; Performs surface removal on an array of polygons.\r
-;\r
-; Input:\r
-; Poly = pointer to an array of TPOLY\r
-; Vertex = pointer to an array of TPOINT\r
-; Dest = pointer to an array of integer\r
-; Count = number of polygons to check\r
-; Step = size of TPOLY structure\r
-; Output:\r
-; if the n-th polygon is invisible the n-th entry of the\r
-; Dest array is set to -1, other entries are not modified\r
-; (so it's possible to use the Light array for Dest, because\r
-; the light intensity is always >= 0)\r
-;\r
-tdBackPlaneCull PROC PASCAL FAR\r
- ARG Step:WORD, \\r
- Poly:DWORD, \\r
- Vertex:DWORD, \\r
- Dest:DWORD, \\r
- Count:WORD\r
- USES ds, si, es, di, fs\r
- ASSUME ds:NOTHING\r
-\r
- mov ds, WORD PTR Vertex[2]\r
- les di, [Poly]\r
- mov fs, WORD PTR Dest[2]\r
-\r
-@@Loop:\r
- mov ax, es:[di].Vtx[2] ; Index of 2nd vertex\r
- shl ax, 2\r
- mov bx, ax\r
- shl ax, 1\r
- add bx, ax ; BX = index*SIZE TPOINT\r
- add bx, WORD PTR [Vertex] ; BX = offset of 2nd vertex\r
- mov ax, es:[di].Vtx[4] ; Index of 3rd vertex\r
- shl ax, 2\r
- mov si, ax\r
- shl ax, 1\r
- add si, ax\r
- add si, WORD PTR [Vertex] ; SI = offset of 3rd vertex\r
- mov ecx, ds:[si].X\r
- sub ecx, ds:[bx].X ; ECX = V3.X-V2.X\r
- mov edx, ds:[si].Y\r
- sub edx, ds:[bx].Y ; EDX = V3.Y-V2.Y\r
- mov ax, es:[di].Vtx[0] ; Index of 1st vertex\r
- shl ax, 2\r
- mov si, ax\r
- shl ax, 1\r
- add si, ax\r
- add si, WORD PTR [Vertex] ; SI = offset of 1st vertex\r
- mov eax, ds:[si].X\r
- sub eax, ds:[bx].X ; EAX = V1.X-V2.X\r
- mov esi, ds:[si].Y\r
- sub esi, ds:[bx].Y ; ESI = V1.Y-V2.Y\r
- imul edx\r
- mov ebx, eax\r
- xchg ecx, edx ; ECX:EBX = (V1.X-V2.X)*(V3.Y-V2.Y)\r
- mov eax, esi\r
- imul edx ; EDX:EAX = (V1.Y-V2.Y)*(V3.X-V2.X)\r
- sub eax, ebx\r
- sbb edx, ecx\r
- jl @@Next ; Polygon is visible\r
- mov bx, WORD PTR [Dest] ; FS:BX -> current Dest entry\r
- mov WORD PTR fs:[bx], -1 ; Remove polygon\r
-@@Next:\r
- add WORD PTR [Dest], 2 ; Next entry for dest\r
- add di, [Step] ; Next polygon\r
- dec [Count]\r
- jnz @@Loop\r
-\r
- ret\r
-tdBackPlaneCull ENDP\r
-\r
-MATH_TEXT ENDS\r
-END\r