home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #6 / amigaacscoverdisc1998-061998.iso / games / descent / source / 3d / horizon.asm < prev    next >
Assembly Source File  |  1998-06-08  |  14KB  |  743 lines

  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.
  11. ;
  12. ; $Source: f:/miner/source/3d/rcs/horizon.asm $
  13. ; $Revision: 1.5 $
  14. ; $Author: matt $
  15. ; $Date: 1994/06/14 18:14:40 $
  16. ;
  17. ; Source for horizon drawer
  18. ;
  19. ; $Log: horizon.asm $
  20. ; Revision 1.5  1994/06/14  18:14:40  matt
  21. ; Use texture-mapper flat shader
  22. ; Revision 1.4  1994/02/10  18:00:42  matt
  23. ; Changed 'if DEBUG_ON' to 'ifndef NDEBUG'
  24. ; Revision 1.3  1994/01/22  18:22:16  matt
  25. ; Fixed bug in horizon bitmap code
  26. ; Revision 1.2  1994/01/20  17:21:47  matt
  27. ; New function g3_compute_sky_polygon()
  28. ; Revision 1.1  1994/01/14  17:22:08  matt
  29. ; Initial revision
  30. ;
  31. ;
  32.  
  33. .386
  34.     option    oldstructs
  35.  
  36.     .nolist
  37.     include    types.inc
  38.     include    psmacros.inc
  39.     include    gr.inc
  40.     include    3d.inc
  41.     .list
  42.  
  43.     assume    cs:_TEXT, ds:_DATA
  44.  
  45. _DATA    segment    dword public USE32 'DATA'
  46.  
  47. rcsid    db    "$Id: horizon.asm 1.5 1994/06/14 18:14:40 matt Exp $"
  48.     align    4
  49.  
  50. sky_color    dd    ?
  51. ground_color    dd    ?
  52. top_color    dd    ?
  53. bot_color    dd    ?
  54.  
  55. color_swap    dw    ?    ;flag for if we swapped
  56. sky_ground_flag    dw    ?    ;0=both, 1=all sky, -1=all gnd
  57.  
  58. horizon_vec    vms_vector <>    ;unscaled up vector
  59.  
  60. up_right    fix    ?
  61. down_right    fix    ?
  62. down_left    fix    ?
  63. up_left    fix    ?
  64.  
  65. left_point    fix    ?,?    ;coords of left point
  66. left_point_edge    dd    ?    ;which edge point is on
  67. right_point    fix    ?,?    ;coords of right point
  68. right_point_edge    dd    ?    ;which edge point is on
  69.  
  70. ;the coordinates of the four corners of the screen (values are placeholders)
  71. corners    fix    0,0    ;up left
  72.     fix    319,0    ;up right
  73.     fix    319,199    ;down right
  74.     fix    0,199    ;down left
  75.  
  76. horizon_poly    dw    5 dup (?,?)    ;max of 5 points
  77.  
  78. ;for g3_compute_horz_vecs
  79. xfrac    fix    ?
  80. yfrac    fix    ?
  81.  
  82. vec_ptr    dd    ?
  83. corner_num    dd    ?
  84.  
  85. ;for compute corner vec
  86. m13    fix    ?    ;m1-m3
  87. m46    fix    ?
  88. m79    fix    ?
  89. m56    fix    ?
  90. m23    fix    ?
  91. m89    fix    ?
  92.  
  93. _DATA    ends
  94.  
  95.  
  96. _TEXT    segment    dword public USE32 'CODE'
  97.  
  98.     extn    gr_setcolor_,gr_clear_canvas_
  99.     extn    gr_upoly_tmap_
  100.  
  101. ;draws a horizon. takes eax=sky_color, edx=ground_color
  102. g3_draw_horizon:    pushm    eax,ebx,ecx,edx,esi,edi
  103.  
  104.     mov    sky_color,eax
  105.     mov    ground_color,edx
  106.  
  107.     mov    color_swap,0    ;assume no swap
  108.     mov    sky_ground_flag,0    ;assume both
  109.  
  110.     test    View_matrix.uvec.y,-1    ;check up
  111.     jg    sky_up
  112.     js    swap_colors
  113. ;y is zero. check x
  114.     test    View_matrix.uvec.x,-1
  115.     js    sky_up
  116. swap_colors:    xchg    eax,edx    ;make sky down
  117.     mov    color_swap,-1    ;we swapped
  118. sky_up:    mov    top_color,eax
  119.     mov    bot_color,edx
  120.  
  121. ;compute horizon_vector
  122.     mov    eax,Unscaled_matrix.rvec.y
  123.     fixmul    Matrix_scale.y
  124.     fixmul    Matrix_scale.z
  125.     mov    horizon_vec.x,eax
  126.     mov    esi,eax
  127.  
  128.     mov    eax,Unscaled_matrix.uvec.y
  129.     fixmul    Matrix_scale.x
  130.     fixmul    Matrix_scale.z
  131.     mov    horizon_vec.y,eax
  132.     mov    edi,eax
  133.  
  134.     mov    eax,Unscaled_matrix.fvec.y
  135.     fixmul    Matrix_scale.x
  136.     fixmul    Matrix_scale.y
  137.     mov    horizon_vec.z,eax
  138.  
  139. ;now compute values & flag for 4 corners. eax = z componant
  140.     mov    ebx,0ff00h    ;and/or flags
  141.  
  142.     add    eax,esi
  143.     add    eax,edi    ;eax = x+y+z
  144.     mov    up_right,eax
  145.     cdq
  146.     and    bh,dl    ;flags_and
  147.     or    bl,dl    ;flags_or
  148.  
  149.     sal    esi,1
  150.     sal    edi,1    ;get x*2, y*2
  151.  
  152.     sub    eax,edi    ;eax = x-y+z
  153.     mov    down_right,eax
  154.     cdq
  155.     and    bh,dl    ;flags_and
  156.     or    bl,dl    ;flags_or
  157.  
  158.     sub    eax,esi    ;eax = -x-y+z
  159.     mov    down_left,eax
  160.     cdq
  161.     and    bh,dl    ;flags_and
  162.     or    bl,dl    ;flags_or
  163.  
  164.     add    eax,edi    ;eax = -x+y+z
  165.     mov    up_left,eax
  166.     cdq
  167.  
  168. ;;    debug    "u: %x %x %x  c: %x %x %x %x\n",unscaled_matrix.uvec.y,unscaled_matrix.uvec.z,unscaled_matrix.uvec.x,up_left,up_right,down_right,down_left
  169.  
  170. ;check flags for all sky or all ground. dl=flag from last corner
  171.  
  172.     and    bh,dl    ;flags_and
  173.     jnz    all_ground
  174.     or    bl,dl    ;flags_or
  175.     jz    all_sky
  176.  
  177. ;fill in values for corners
  178.  
  179.     mov    eax,Canvas_width
  180.     sal    eax,16    ;make a fix
  181.     mov    corners+8,eax
  182.     mov    corners+16,eax
  183.  
  184.     mov    eax,Canvas_height
  185.     sal    eax,16    ;make a fix
  186.     mov    corners+20,eax
  187.     mov    corners+28,eax
  188.  
  189.  
  190. ;check for intesection with each of four edges & compute horizon line
  191.     lea    ebx,left_point
  192.  
  193. ;check intersection with left edge
  194.  
  195.     mov    eax,up_left
  196.     xor    eax,down_left    ;signs different?
  197.     jns    not_left    ;..no, so no isect with left
  198.  
  199.     mov    eax,corners+20
  200.     fixmuldiv    up_left,edi    ;eax = up_left * height / y*2
  201.     abs_eax
  202.  
  203.     mov    4[ebx],eax    ;y
  204.     xor    eax,eax
  205.     mov    [ebx],eax    ;x=0
  206.     mov    8[ebx],eax    ;edge 0
  207.     add    ebx,12
  208. not_left:
  209.     
  210. ;check intersection with top edge
  211.  
  212.     mov    eax,up_left
  213.     xor    eax,up_right    ;signs different?
  214.     jns    not_top    ;..no, so no isect with left
  215.  
  216.     mov    eax,corners+16
  217.     fixmuldiv    up_left,esi    ;eax = up_right * width / x*2
  218.     abs_eax
  219.  
  220.     mov    [ebx],eax    ;x
  221.     xor    eax,eax
  222.     mov    4[ebx],eax    ;y=0
  223.     inc    eax
  224.     mov    8[ebx],eax    ;edge 1
  225.     add    ebx,12
  226. not_top:
  227.     
  228. ;check intersection with right edge
  229.  
  230.     mov    eax,up_right
  231.     xor    eax,down_right    ;signs different?
  232.     jns    not_right    ;..no, so no isect with left
  233.  
  234.     mov    eax,corners+20
  235.     fixmuldiv    up_right,edi    ;eax = up_right * height / y*2
  236.     abs_eax
  237.  
  238.     ;neg    eax
  239.     ;add    eax,corners+20
  240.  
  241.     mov    4[ebx],eax    ;y
  242.     mov    eax,corners+16
  243.     mov    [ebx],eax    ;x=width-1
  244.     mov    eax,2
  245.     mov    8[ebx],eax    ;edge 2
  246.     add    ebx,12
  247. not_right:
  248.     
  249. ;check intersection with bottom edge
  250.  
  251.     mov    eax,down_right
  252.     xor    eax,down_left    ;signs different?
  253.     jns    not_bot    ;..no, so no isect with left
  254.  
  255.     mov    eax,corners+16
  256.     fixmuldiv    down_left,esi    ;eax = down_right * width / x*2
  257.     abs_eax
  258.  
  259.     mov    [ebx],eax    ;x
  260.     mov    eax,corners+20
  261.     mov    4[ebx],eax    ;y=height-1
  262.     mov    eax,3
  263.     mov    8[ebx],eax    ;edge 3
  264.     add    ebx,12
  265. not_bot:
  266.  
  267. ;make sure we wrote two and only two ends of horizon line
  268.     ifndef    NDEBUG
  269.      cmp    ebx,offset left_point+24
  270.      break_if    ne,'Wrong number of values for horizon_line'
  271.     endif
  272.  
  273. ;make sure first edge is left
  274.  
  275.     mov    eax,left_point
  276.     cmp    eax,right_point
  277.     jle    line_ok
  278.  
  279. ;swap left and right
  280.     xchg    eax,right_point
  281.     mov    left_point,eax
  282.  
  283.     mov    eax,left_point+4
  284.     xchg    eax,right_point+4
  285.     mov    left_point+4,eax
  286.  
  287.     mov    eax,left_point+8
  288.     xchg    eax,right_point+8
  289.     mov    left_point+8,eax
  290.  
  291. line_ok:
  292.  
  293. ;draw two polygons from horizon line
  294.  
  295.     mov    eax,top_color
  296.     cmp    eax,-1    ;no draw?
  297.     je    no_draw_top
  298.     call    gr_setcolor_
  299.     lea    esi,left_point
  300.     lea    edi,right_point
  301.     call    draw_horz_poly
  302. no_draw_top:
  303.  
  304.     mov    eax,bot_color
  305.     cmp    eax,-1    ;no draw?
  306.     je    no_draw_bot
  307.     call    gr_setcolor_
  308.     lea    esi,right_point
  309.     lea    edi,left_point
  310.     call    draw_horz_poly
  311. no_draw_bot:
  312.  
  313. ;draw lines for diagnostics
  314. ;;    xor    eax,eax
  315. ;;    call    gr_setcolor_
  316. ;;    mov    eax,left_point
  317. ;;    mov    edx,left_point+4
  318. ;;    mov    ebx,right_point
  319. ;;    mov    ecx,right_point+4
  320. ;;    call    gr_line_
  321.     
  322. done_horizon:    popm    eax,ebx,ecx,edx,esi,edi
  323.     ret
  324.  
  325. ;we see all sky or all ground.  clear screen with appropriate color
  326. all_ground:      mov    eax,ground_color
  327.     mov    sky_ground_flag,-1    ;all ground
  328.     jmp    do_clear
  329. all_sky:    mov    eax,sky_color
  330.     mov    sky_ground_flag,1    ;all sky
  331. do_clear:    call    gr_clear_canvas_
  332.     jmp    done_horizon
  333.  
  334.  
  335. ;draw a polygon (one half of horizon) from the horizon line
  336. draw_horz_poly:    lea    ebx,horizon_poly
  337.  
  338. ;copy horizon line as first points in poly
  339.  
  340.     mov    eax,[edi]
  341.     mov    [ebx],eax
  342.     mov    eax,4[edi]
  343.     mov    4[ebx],eax
  344.  
  345.     mov    eax,[esi]
  346.     mov    8[ebx],eax
  347.     mov    eax,4[esi]
  348.     mov    12[ebx],eax
  349.  
  350. ;add corners to polygon
  351.  
  352.     mov    eax,8[esi]    ;edge number of start edge
  353.  
  354.     mov    ecx,8[edi]    ;edge number of end point
  355.     sub    ecx,eax    ;number of edges
  356.     jns    edgenum_ok
  357.     add    ecx,4
  358. edgenum_ok:
  359.     mov    edx,ecx    ;save count
  360.     sal    eax,3    ;edge * 8
  361.     lea    esi,corners[eax]    ;first corner
  362.     lea    edi,16[ebx]    ;rest of poly
  363. corner_loop:    movsd
  364.     movsd        ;copy a corner
  365.     cmp    esi,offset corners+8*4    ;end of list?
  366.     jne    no_wrap
  367.     lea    esi,corners
  368. no_wrap:    loop    corner_loop
  369.  
  370. ;now draw the polygon
  371.     mov    eax,edx    ;get corner count
  372.     add    eax,2    ;..plus horz line end points
  373.     lea    edx,horizon_poly    ;get the points
  374. ;;    call    gr_poly_    ;draw it!
  375.  call gr_upoly_tmap_
  376.     ret
  377.  
  378. ;return information on the polygon that is the sky. 
  379. ;takes ebx=ptr to x,y pairs, ecx=ptr to vecs for each point
  380. ;returns eax=number of points
  381. ;IMPORTANT: g3_draw_horizon() must be called before this routine.
  382. g3_compute_sky_polygon:
  383.     test    sky_ground_flag,-1    ;what was drawn
  384.     js    was_all_ground
  385.     jg    was_all_sky    
  386.  
  387.     pushm    ebx,ecx,edx,esi,edi
  388.  
  389.     lea    esi,left_point
  390.     lea    edi,right_point
  391.     test    color_swap,-1
  392.     jz    no_swap_ends
  393.     xchg    esi,edi    ;sky isn't top
  394. no_swap_ends:
  395.  
  396. ;copy horizon line as first points in poly
  397.  
  398.     mov    eax,[edi]    ;copy end point
  399.     mov    [ebx],eax
  400.     mov    eax,4[edi]
  401.     mov    4[ebx],eax
  402.  
  403.     mov    eax,[esi]    ;copy start point
  404.     mov    8[ebx],eax
  405.     mov    eax,4[esi]
  406.     mov    12[ebx],eax
  407.  
  408.     pushm    ebx,ecx
  409.     push    edi    ;save end point
  410.     push    esi    ;save start point
  411.     mov    esi,edi    ;end point is first point
  412.     mov    edi,ecx    ;dest buffer
  413.     call    compute_horz_end_vec
  414.  
  415.     pop    esi    ;get back start point
  416.     add    edi,12    ;2nd vec
  417.     call    compute_horz_end_vec
  418.  
  419.     pop    edi    ;get back end point
  420.     popm    ebx,ecx
  421.     add    ebx,16    ;past two x,y pairs
  422.     add    ecx,24    ;past two vectors
  423.  
  424.     mov    vec_ptr,ecx
  425.  
  426. ;add corners to polygon
  427.  
  428.     mov    eax,8[esi]    ;edge number of start edge
  429.     mov    corner_num,eax
  430.  
  431.     mov    ecx,8[edi]    ;edge number of end point
  432.     sub    ecx,eax    ;number of edges
  433.     jns    edgenum_ok2
  434.     add    ecx,4
  435. edgenum_ok2:
  436.     push    ecx    ;save count
  437.     sal    eax,3    ;edge * 8
  438.     lea    esi,corners[eax]    ;first corner
  439.     mov    edi,ebx    ;rest of poly 2d points
  440. corner_loop2:
  441.     movsd
  442.     movsd        ;copy a corner
  443.     cmp    esi,offset corners+8*4    ;end of list?
  444.     jne    no_wrap2
  445.     lea    esi,corners
  446. no_wrap2:
  447.     pushm    ecx,esi,edi
  448.     mov    edi,vec_ptr
  449.     mov    eax,corner_num
  450.     call    compute_corner_vec
  451.     add    vec_ptr,12
  452.     inc    corner_num
  453.     popm    ecx,esi,edi
  454.  
  455.     loop    corner_loop2
  456.  
  457. ;now return with count
  458.     pop    eax    ;get corner count
  459.     add    eax,2    ;..plus horz line end points
  460.  
  461.     popm    ebx,ecx,edx,esi,edi
  462.  
  463.     ret
  464.  
  465. ;we drew all ground, so there was no horizon drawn
  466. was_all_ground:    xor    eax,eax    ;no points in poly
  467.     ret
  468.  
  469. ;we drew all sky, so find 4 corners
  470. was_all_sky:    pushm    ebx,ecx,edx,esi,edi
  471.     push    ecx
  472.     lea    esi,corners
  473.     mov    edi,ebx
  474.     mov    ecx,8
  475.     rep    movsd
  476.     pop    edi
  477.  
  478.     mov    ecx,4
  479.     xor    eax,eax    ;start corner 0
  480. sky_loop:    pushm    eax,ecx,edi
  481.     call    compute_corner_vec
  482.     popm    eax,ecx,edi
  483.     add    edi,12
  484.     inc    eax
  485.     loop    sky_loop
  486.     mov    eax,4    ;4 corners
  487.     popm    ebx,ecx,edx,esi,edi
  488.     ret
  489.  
  490. ;compute vector describing horizon intersection with a point.
  491. ;takes esi=2d point, edi=vec. trashes eax,ebx,ecx,edx
  492. compute_horz_end_vec:
  493.  
  494. ;compute rotated x/z & y/z ratios
  495.  
  496.     mov    eax,[esi]    ;get x coord
  497.       sub    eax,Canv_w2
  498.     fixdiv    Canv_w2
  499.     mov    xfrac,eax    ;save
  500.  
  501.     mov    eax,4[esi]    ;get y coord
  502.       sub    eax,Canv_h2
  503.     fixdiv    Canv_h2
  504.     neg    eax    ;y inversion
  505.     mov    yfrac,eax    ;save
  506.  
  507. ;compute fraction unrotated x/z
  508.  
  509.     mov    eax,xfrac
  510.     add    eax,yfrac
  511.     mov    ecx,eax    ;save
  512.     fixmul    View_matrix.m9
  513.     sub    eax,View_matrix.m7
  514.     sub    eax,View_matrix.m8
  515.     mov    ebx,eax    ;save numerator
  516.  
  517.     mov    eax,ecx
  518.     fixmul    View_matrix.m3
  519.     mov    ecx,eax
  520.     mov    eax,View_matrix.m1
  521.     add    eax,View_matrix.m2
  522.     sub    eax,ecx
  523.  
  524. ;now eax/ebx = z/x. do divide in way to give result < 0
  525.  
  526.     pushm    eax,ebx
  527.     abs_eax
  528.     xchg    eax,ebx
  529.     abs_eax
  530.     cmp    eax,ebx    ;which is bigger?
  531.     popm    eax,ebx
  532.     jl    do_xz
  533.  
  534. ;x is bigger, so do as z/x
  535.  
  536.     fixdiv    ebx
  537.     
  538. ;now eax = z/x ratio.  Compute vector by normalizing and correcting sign
  539.  
  540.     push    eax    ;save ratio
  541.  
  542.     imul    eax    ;compute z*z
  543.     inc    edx    ;+ x*x (x==1)
  544.     call    quad_sqrt
  545.  
  546.     mov    ecx,eax    ;mag in ecx
  547.     pop    eax    ;get ratio, x part
  548.  
  549.     fixdiv    ecx
  550.     mov    [edi].z,eax
  551.  
  552.     mov    eax,f1_0
  553.     fixdiv    ecx
  554.  
  555.     mov    [edi].x,eax
  556.  
  557.     jmp    finish_end
  558.  
  559. ;z is bigger, so do as x/z
  560. do_xz:
  561.     xchg    eax,ebx
  562.     fixdiv    ebx
  563.     
  564. ;now eax = x/z ratio.  Compute vector by normalizing and correcting sign
  565.  
  566.     push    eax    ;save ratio
  567.  
  568.     imul    eax    ;compute x*x
  569.     inc    edx    ;+ z*z (z==1)
  570.     call    quad_sqrt
  571.  
  572.     mov    ecx,eax    ;mag in ecx
  573.     pop    eax    ;get ratio, x part
  574.  
  575.     fixdiv    ecx
  576.     mov    [edi].x,eax
  577.  
  578.     mov    eax,f1_0
  579.     fixdiv    ecx
  580.  
  581.     mov    [edi].z,eax
  582.  
  583. finish_end:    xor    eax,eax    ;y = 0
  584.     mov    [edi].y,eax
  585.  
  586. ;now make sure that this vector is in front of you, not behind
  587.  
  588.     mov    eax,[edi].x
  589.     imul    View_matrix.m3
  590.     mov    ebx,eax
  591.     mov    ecx,edx
  592.     mov    eax,[edi].z
  593.     imul    View_matrix.m9
  594.     add    eax,ebx
  595.     adc    edx,ecx
  596.     jns    vec_ok    ;has positive z, ok
  597.  
  598. ;z is neg, flip vector
  599.  
  600.     neg    [edi].x
  601.     neg    [edi].z
  602. vec_ok:
  603.     ret
  604.  
  605. MIN_DEN equ 7fffh
  606.  
  607. sub2    macro    dest,src
  608.     mov    eax,src
  609.     sal    eax,1
  610.     sub    dest,eax
  611.     endm
  612.  
  613. ;compute vector decribing a corner of the screen.
  614. ;takes edi=vector, eax=corner num
  615. compute_corner_vec:
  616.  
  617.     cmp    eax,4
  618.     jl    num_ok
  619.     sub    eax,4
  620. num_ok:
  621.  
  622. ;compute all deltas
  623.     mov    ebx,View_matrix.m1
  624.     mov    ecx,View_matrix.m4
  625.     mov    edx,View_matrix.m7
  626.  
  627.     or    eax,eax
  628.     jz    neg_x
  629.     cmp    eax,3
  630.     jne    no_neg_x
  631. neg_x:
  632.     neg    ebx
  633.     neg    ecx
  634.     neg    edx
  635. no_neg_x:    
  636.     sub    ebx,View_matrix.m3
  637.     mov    m13,ebx    ;m1-m3
  638.     sub    ecx,View_matrix.m6
  639.     mov    m46,ecx    ;m4-m6
  640.     sub    edx,View_matrix.m9
  641.     mov    m79,edx    ;m7-m9
  642.  
  643.     mov    ebx,View_matrix.m5
  644.     mov    ecx,View_matrix.m2
  645.     mov    edx,View_matrix.m8
  646.  
  647.     cmp    eax,2
  648.     jl    no_neg_y
  649. neg_y:
  650.     neg    ebx
  651.     neg    ecx
  652.     neg    edx
  653. no_neg_y:    
  654.     sub    ebx,View_matrix.m6
  655.     mov    m56,ebx    ;m5-m6
  656.     sub    ecx,View_matrix.m3
  657.     mov    m23,ecx    ;m2-m3
  658.     sub    edx,View_matrix.m9
  659.     mov    m89,edx    ;m8-m9
  660.  
  661. ;compute x/z ratio
  662.  
  663. ;compute denomonator
  664.  
  665.     mov    eax,m46
  666.     fixmul    m23
  667.     mov    ebx,eax    ;save
  668.  
  669.     mov    eax,m56
  670.     fixmul    m13
  671.     sub    eax,ebx    ;eax = denominator
  672.  
  673. ;now we have the denominator.  If it is too small, try x/y, z/y or z/x, y/x
  674.  
  675.     mov    ecx,eax    ;save den
  676.  
  677.     abs_eax
  678.     cmp    eax,MIN_DEN
  679.     jl    z_too_small
  680.  
  681. z_too_small:
  682.  
  683. ;now do x/z numerator
  684.  
  685.     mov    eax,m79
  686.     fixmul    m56    ;* (m5-m6)
  687.     mov    ebx,eax
  688.  
  689.     mov    eax,m89
  690.     fixmul    m46    ;* (m4-m6)
  691.     sub    eax,ebx
  692.  
  693. ;now, eax/ecx = x/z ratio
  694.  
  695.     fixdiv    ecx    ;eax = x/z
  696.  
  697.     mov    [edi].x,eax    ;save x
  698.  
  699. ;now do y/z
  700.  
  701.     mov    eax,m89
  702.     fixmul    m13
  703.     mov    ebx,eax
  704.  
  705.     mov    eax,m79
  706.     fixmul    m23
  707.     sub    eax,ebx
  708.  
  709. ;now eax/ecx = y/z ratio
  710.  
  711.     fixdiv    ecx
  712.  
  713.     mov    [edi].y,eax
  714.  
  715.     mov    [edi].z,f1_0
  716.  
  717.     mov    esi,edi
  718.     call    vm_vec_normalize
  719.  
  720. ;make sure this vec is pointing in right direction
  721.  
  722.     lea    edi,View_matrix.fvec
  723.     call    vm_vec_dotprod
  724.     or    eax,eax    ;check sign
  725.     jg    vec_sign_ok
  726.  
  727.     neg    [esi].x
  728.     neg    [esi].y
  729.     neg    [esi].z
  730. vec_sign_ok:
  731.  
  732.     ret
  733.  
  734.  
  735. _TEXT    ends
  736.  
  737.     end
  738.