home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Raytrace & Morphing / SOS-RAYTRACE.ISO / programm / source / devel5 / matrix.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-20  |  16.9 KB  |  1,045 lines

  1. /* Matrix math, assembly by Dave Stampe */
  2.  
  3. /* Copyright 1992 by Dave Stampe and Bernie Roehl.
  4.      May be freely used to write software for release into the public domain;
  5.      all commercial endeavours MUST contact Bernie Roehl and Dave Stampe
  6.      for permission to incorporate any part of this software into their
  7.      products!
  8.  
  9.      ATTRIBUTION:  If you use any part of this source code or the libraries
  10.      in your projects, you must give attribution to REND386, Dave Stampe,
  11.      and Bernie Roehl in your documentation, source code, and at startup
  12.      of your program.  Let's keep the freeware ball rolling!
  13.  */
  14.  
  15. /* Contact: broehl@sunee.waterloo.edu or dstampe@sunee.waterloo.edu */
  16.  
  17. #pragma inline
  18.  
  19. #include <mem.h>   /* memcpy() */
  20.  
  21. #include "3dstruct.h"
  22.  
  23. #define XFSC 536870912   /* 2**29 for shifting xform coeffs to long */
  24.  
  25. /*************** TRIGNOMETRIC FUNCTIONS *****************/
  26.  
  27. /* (from inttrig.c) */
  28.  
  29. extern long isine(long x);
  30. extern long icosine(long x);
  31. extern long arcsine(long x);
  32. extern long arccosine(long x);
  33. extern long arctan2(long y, long x);
  34.  
  35. /***************** MATRIX-VECTOR OPERATIONS **************/
  36.  
  37.                 /* rotate/translate XYZ by matrix */
  38.  
  39. void matrix_point(MATRIX m, long *xp, long *yp, long *zp)
  40. {
  41.  long x = *xp;
  42.  long y = *yp;
  43.  long z = *zp;
  44.  
  45.  long xr,yr,zr;
  46.  
  47.  asm {
  48.     .386
  49.     push    si
  50.     push    di
  51.     push    cx
  52.     push    dx
  53.     les    di,DWORD PTR m
  54.  
  55.     mov    eax,es:[di]
  56.     imul    DWORD PTR x
  57.     mov    ecx,edx
  58.     mov    ebx,eax
  59.     mov    eax,es:[di+4]
  60.     imul    DWORD PTR y
  61.     add    ebx,eax
  62.     adc    ecx,edx
  63.     mov    eax,es:[di+8]
  64.     imul    DWORD PTR z
  65.     add    eax,ebx
  66.     adc    edx,ecx
  67.     shrd    eax,edx,29
  68.     adc    eax,es:[di+36]
  69.     mov    xr,eax
  70.  
  71.     mov    eax,es:[di+12]
  72.     imul    DWORD PTR x
  73.     mov    ecx,edx
  74.     mov    ebx,eax
  75.     mov    eax,es:[di+16]
  76.     imul    DWORD PTR y
  77.     add    ebx,eax
  78.     adc    ecx,edx
  79.     mov    eax,es:[di+20]
  80.     imul    DWORD PTR z
  81.     add    eax,ebx
  82.     adc    edx,ecx
  83.     shrd    eax,edx,29
  84.     adc    eax,es:[di+40]
  85.     mov    yr,eax
  86.  
  87.     mov    eax,es:[di+24]
  88.     imul    DWORD PTR x
  89.     mov    ecx,edx
  90.     mov    ebx,eax
  91.     mov    eax,es:[di+28]
  92.     imul    DWORD PTR y
  93.     add    ebx,eax
  94.     adc    ecx,edx
  95.     mov    eax,es:[di+32]
  96.     imul    DWORD PTR z
  97.     add    eax,ebx
  98.     adc    edx,ecx
  99.     shrd    eax,edx,29
  100.     adc    eax,es:[di+44]
  101.     mov    zr,eax
  102.  
  103.     pop    dx
  104.     pop    cx
  105.     pop    di
  106.     pop    si
  107.          }
  108.  
  109.  *xp = xr;
  110.  *yp = yr;
  111.  *zp = zr;
  112. }
  113.  
  114.                 /* rotate XYZ by matrix */
  115.  
  116. void matrix_rotate(MATRIX m, long *xp, long *yp, long *zp)
  117. {
  118.  long x = *xp;
  119.  long y = *yp;
  120.  long z = *zp;
  121.  
  122.  long xr,yr,zr;
  123.  
  124.  asm {
  125.     .386
  126.     push    si
  127.     push    di
  128.     push    cx
  129.     push    dx
  130.     les    di,DWORD PTR m
  131.  
  132.     mov    eax,es:[di]
  133.     imul    DWORD PTR x
  134.     mov    ecx,edx
  135.     mov    ebx,eax
  136.     mov    eax,es:[di+4]
  137.     imul    DWORD PTR y
  138.     add    ebx,eax
  139.     adc    ecx,edx
  140.     mov    eax,es:[di+8]
  141.     imul    DWORD PTR z
  142.     add    eax,ebx
  143.     adc    edx,ecx
  144.     shrd    eax,edx,29
  145.     adc    eax,0
  146.     mov    xr,eax
  147.  
  148.     mov    eax,es:[di+12]
  149.     imul    DWORD PTR x
  150.     mov    ecx,edx
  151.     mov    ebx,eax
  152.     mov    eax,es:[di+16]
  153.     imul    DWORD PTR y
  154.     add    ebx,eax
  155.     adc    ecx,edx
  156.     mov    eax,es:[di+20]
  157.     imul    DWORD PTR z
  158.     add    eax,ebx
  159.     adc    edx,ecx
  160.     shrd    eax,edx,29
  161.     adc    eax,0
  162.     mov    yr,eax
  163.  
  164.     mov    eax,es:[di+24]
  165.     imul    DWORD PTR x
  166.     mov    ecx,edx
  167.     mov    ebx,eax
  168.     mov    eax,es:[di+28]
  169.     imul    DWORD PTR y
  170.     add    ebx,eax
  171.     adc    ecx,edx
  172.     mov    eax,es:[di+32]
  173.     imul    DWORD PTR z
  174.     add    eax,ebx
  175.     adc    edx,ecx
  176.     shrd    eax,edx,29
  177.     adc    eax,0
  178.     mov    zr,eax
  179.  
  180.     pop    dx
  181.     pop    cx
  182.     pop    di
  183.     pop    si
  184.       }
  185.  
  186.  *xp = xr;
  187.  *yp = yr;
  188.  *zp = zr;
  189. }
  190.  
  191.  
  192.  
  193. /******************** MISC. VECTOR MATH ****************/
  194.  
  195.         /* replaces column N of a matrix with cross of other 2 */
  196.         /* used to speed computations, repair matrix scaling   */
  197.  
  198. void cross_column(MATRIX m, int col)
  199. {
  200.  long x, y, z;
  201.  long x1, y1, z1, x2, y2, z2;
  202.  
  203.  switch (col)
  204.   {
  205.    case 0:
  206.     x1 = m[0][1];
  207.     y1 = m[1][1];
  208.     z1 = m[2][1];
  209.     x2 = m[0][2];
  210.     y2 = m[1][2];
  211.     z2 = m[2][2];
  212.     break;
  213.  
  214.    case 1:
  215.     x1 = m[0][2];
  216.     y1 = m[1][2];
  217.     z1 = m[2][2];
  218.     x2 = m[0][0];
  219.     y2 = m[1][0];
  220.     z2 = m[2][0];
  221.     break;
  222.  
  223.    case 2:
  224.     x1 = m[0][0];
  225.     y1 = m[1][0];
  226.     z1 = m[2][0];
  227.     x2 = m[0][1];
  228.     y2 = m[1][1];
  229.     z2 = m[2][1];
  230.     break;
  231.   }
  232.  
  233.  asm {
  234.     push    dx
  235.     push    si
  236.     push    di
  237.  
  238.     mov    eax,y1        /* compute cross product */
  239.     mov    edx,z2
  240.     imul    edx
  241.     mov    edi,edx
  242.     mov    esi,eax
  243.     mov    eax,y2
  244.     mov    edx,z1
  245.     imul    edx
  246.     sub    esi,eax
  247.     sbb    edi,edx
  248.     shrd    esi,edi,29
  249.     adc    esi,0
  250.     mov    x,esi
  251.  
  252.     mov    eax,z1
  253.     mov    edx,x2
  254.     imul    edx
  255.     mov    edi,edx
  256.     mov    esi,eax
  257.     mov    eax,z2
  258.     mov    edx,x1
  259.     imul    edx
  260.     sub    esi,eax
  261.     sbb    edi,edx
  262.     shrd    esi,edi,29
  263.     adc    esi,0
  264.     mov    y,esi
  265.  
  266.     mov    eax,x1
  267.     mov    edx,y2
  268.     imul    edx
  269.     mov    edi,edx
  270.     mov    esi,eax
  271.     mov    eax,x2
  272.     mov    edx,y1
  273.     imul    edx
  274.     sub    esi,eax
  275.     sbb    edi,edx
  276.     shrd    esi,edi,29
  277.     adc    esi,0
  278.     mov    z,esi
  279.  
  280.     pop    di
  281.     pop    si
  282.     pop    dx
  283.      }
  284.  
  285.  
  286.  switch (col)
  287.   {
  288.    case 0:
  289.     m[0][0] = x;
  290.     m[1][0] = y;
  291.     m[2][0] = z;
  292.     break;
  293.  
  294.    case 1:
  295.     m[0][1] = x;
  296.     m[1][1] = y;
  297.     m[2][1] = z;
  298.     break;
  299.  
  300.    case 2:
  301.     m[0][2] = x;
  302.     m[1][2] = y;
  303.     m[2][2] = z;
  304.     break;
  305.   }
  306. }
  307.  
  308.  
  309. long m_mult(long a, long b)    /* perform mult. by matrix element         */
  310. {                              /* where either a or b is in <3.29> format */
  311.  long result;
  312.  
  313.  asm {
  314.     push    edx
  315.     mov    eax,DWORD PTR a
  316.     imul    DWORD PTR b
  317.     shrd    eax,edx,29
  318.     adc    eax,0
  319.     mov    DWORD PTR result,eax
  320.     pop    edx
  321.      }
  322.  return result;
  323. }
  324.  
  325.  
  326. long dot_prod_29(long a, long b, long c, long x, long y, long z)
  327. {
  328.  /* computes (Ax + By + Cz)>>29 */
  329.  
  330.  long result;
  331.  
  332.  asm {
  333.     push    si
  334.     push    di
  335.  
  336.     mov    eax,a
  337.     imul    DWORD PTR x
  338.     mov    esi,eax
  339.     mov    edi,edx
  340.  
  341.     mov    eax,b
  342.     imul    DWORD PTR y
  343.     add    esi,eax
  344.     adc    edi,edx
  345.  
  346.     mov    eax,c
  347.     imul    DWORD PTR z
  348.     add    esi,eax
  349.     adc    edi,edx
  350.  
  351.     shrd    esi,edi,29
  352.     adc    esi,0
  353.     mov    result,esi
  354.  
  355.     pop    di
  356.     pop    si
  357.      }
  358.  return result;
  359. }
  360.  
  361. /****************** MATRIX MANIPULATION ***************/
  362.  
  363.  
  364. void matrix_mult(MATRIX a, MATRIX b, MATRIX c)
  365. {
  366.     long r1,r2,r3,r4,r5,r6,r7,r8,r9;
  367.  
  368.  asm {
  369.     .386                    /* 3x3 section of matrixs: A*B->C       */
  370.     push    ds              /* now gets z column from cross product */
  371.     push    si
  372.     push    di
  373.     push    cx
  374.     push    dx
  375.  
  376.     les    si,DWORD PTR a
  377.     lds    di,DWORD PTR b
  378.  
  379.     mov    eax,es:[si]
  380.     imul    DWORD PTR ds:[di]
  381.     mov    ebx,eax
  382.     mov    ecx,edx
  383.     mov    eax,es:[si+4]
  384.     imul    DWORD PTR ds:[di+12]
  385.     add    ebx,eax
  386.     adc    ecx,edx
  387.     mov    eax,es:[si+8]
  388.     imul    DWORD PTR ds:[di+24]
  389.     add    ebx,eax
  390.     adc    ecx,edx
  391.     shrd    ebx,ecx,29
  392.     adc    ebx,0
  393.     mov    r1,ebx
  394.  
  395.     mov    eax,es:[si]
  396.     imul    DWORD PTR ds:[di+4]
  397.     mov    ebx,eax
  398.     mov    ecx,edx
  399.     mov    eax,es:[si+4]
  400.     imul    DWORD PTR ds:[di+16]
  401.     add    ebx,eax
  402.     adc    ecx,edx
  403.     mov    eax,es:[si+8]
  404.     imul    DWORD PTR ds:[di+28]
  405.     add    ebx,eax
  406.     adc    ecx,edx
  407.     shrd    ebx,ecx,29
  408.     adc    ebx,0
  409.     mov    r2,ebx
  410.  
  411. #ifndef CROSS_Z
  412.     mov    eax,es:[si]
  413.     imul    DWORD PTR ds:[di+8]
  414.     mov    ebx,eax
  415.     mov    ecx,edx
  416.     mov    eax,es:[si+4]
  417.     imul    DWORD PTR ds:[di+20]
  418.     add    ebx,eax
  419.     adc    ecx,edx
  420.     mov    eax,es:[si+8]
  421.     imul    DWORD PTR ds:[di+32]
  422.     add    ebx,eax
  423.     adc    ecx,edx
  424.     shrd    ebx,ecx,29
  425.     adc    ebx,0
  426.     mov    r3,ebx
  427. #endif
  428.  
  429.     mov    eax,es:[si+12]
  430.     imul    DWORD PTR ds:[di]
  431.     mov    ebx,eax
  432.     mov    ecx,edx
  433.     mov    eax,es:[si+16]
  434.     imul    DWORD PTR ds:[di+12]
  435.     add    ebx,eax
  436.     adc    ecx,edx
  437.     mov    eax,es:[si+20]
  438.     imul    DWORD PTR ds:[di+24]
  439.     add    ebx,eax
  440.     adc    ecx,edx
  441.     shrd    ebx,ecx,29
  442.     adc    ebx,0
  443.     mov    r4,ebx
  444.  
  445.     mov    eax,es:[si+12]
  446.     imul    DWORD PTR ds:[di+4]
  447.     mov    ebx,eax
  448.     mov    ecx,edx
  449.     mov    eax,es:[si+16]
  450.     imul    DWORD PTR ds:[di+16]
  451.     add    ebx,eax
  452.     adc    ecx,edx
  453.     mov    eax,es:[si+20]
  454.     imul    DWORD PTR ds:[di+28]
  455.     add    ebx,eax
  456.     adc    ecx,edx
  457.     shrd    ebx,ecx,29
  458.     adc    ebx,0
  459.     mov    r5,ebx
  460.  
  461. #ifndef CROSS_Z
  462.     mov    eax,es:[si+12]
  463.     imul    DWORD PTR ds:[di+8]
  464.     mov    ebx,eax
  465.     mov    ecx,edx
  466.     mov    eax,es:[si+16]
  467.     imul    DWORD PTR ds:[di+20]
  468.     add    ebx,eax
  469.     adc    ecx,edx
  470.     mov    eax,es:[si+20]
  471.     imul    DWORD PTR ds:[di+32]
  472.     add    ebx,eax
  473.     adc    ecx,edx
  474.     shrd    ebx,ecx,29
  475.     adc    ebx,0
  476.     mov    r6,ebx
  477. #endif
  478.  
  479.     mov    eax,es:[si+24]
  480.     imul    DWORD PTR ds:[di]
  481.     mov    ebx,eax
  482.     mov    ecx,edx
  483.     mov    eax,es:[si+28]
  484.     imul    DWORD PTR ds:[di+12]
  485.     add    ebx,eax
  486.     adc    ecx,edx
  487.     mov    eax,es:[si+32]
  488.     imul    DWORD PTR ds:[di+24]
  489.     add    ebx,eax
  490.     adc    ecx,edx
  491.     shrd    ebx,ecx,29
  492.     adc    ebx,0
  493.     mov    r7,ebx
  494.  
  495.     mov    eax,es:[si+24]
  496.     imul    DWORD PTR ds:[di+4]
  497.     mov    ebx,eax
  498.     mov    ecx,edx
  499.     mov    eax,es:[si+28]
  500.     imul    DWORD PTR ds:[di+16]
  501.     add    ebx,eax
  502.     adc    ecx,edx
  503.     mov    eax,es:[si+32]
  504.     imul    DWORD PTR ds:[di+28]
  505.     add    ebx,eax
  506.     adc    ecx,edx
  507.     shrd    ebx,ecx,29
  508.     adc    ebx,0
  509.     mov    r8,ebx
  510.  
  511. #ifndef CROSS_Z
  512.     mov    eax,es:[si+24]
  513.     imul    DWORD PTR ds:[di+8]
  514.     mov    ebx,eax
  515.     mov    ecx,edx
  516.     mov    eax,es:[si+28]
  517.     imul    DWORD PTR ds:[di+20]
  518.     add    ebx,eax
  519.     adc    ecx,edx
  520.     mov    eax,es:[si+32]
  521.     imul    DWORD PTR ds:[di+32]
  522.     add    ebx,eax
  523.     adc    ecx,edx
  524.     shrd    ebx,ecx,29
  525.     adc    ebx,0
  526.     mov    r9,ebx
  527. #endif
  528.  
  529. #ifdef CROSS_Z
  530.     mov    eax,r4        /* compute cross product of  */
  531.     mov    edx,r8        /* columns 1&2 to get col. 3 */
  532.     imul    edx
  533.     mov    edi,edx
  534.     mov    esi,eax
  535.     mov    eax,r5
  536.     mov    edx,r7
  537.     imul    edx
  538.     sub    esi,eax
  539.     sbb    edi,edx
  540.     shrd    esi,edi,29
  541.     adc    esi,0
  542.     mov     r3,esi
  543.  
  544.     mov    eax,r7
  545.     mov    edx,r2
  546.     imul    edx
  547.     mov    edi,edx
  548.     mov    esi,eax
  549.     mov    eax,r8
  550.     mov    edx,r1
  551.     imul    edx
  552.     sub    esi,eax
  553.     sbb    edi,edx
  554.     shrd    esi,edi,29
  555.     adc    esi,0
  556.     mov     r6,esi
  557.  
  558.     mov    eax,r1
  559.     mov    edx,r5
  560.     imul    edx
  561.     mov    edi,edx
  562.     mov    esi,eax
  563.     mov    eax,r2
  564.     mov    edx,r4
  565.     imul    edx
  566.     sub    esi,eax
  567.     sbb    edi,edx
  568.     shrd    esi,edi,29
  569.     adc    esi,0
  570.     mov     r9,esi
  571. #endif
  572.  
  573.     les    di,DWORD PTR c
  574.     mov    eax,r1
  575.     mov    es:[di],eax
  576.     mov    eax,r2
  577.     mov    es:[di+4],eax
  578.     mov    eax,r4
  579.     mov    es:[di+12],eax
  580.     mov    eax,r5
  581.     mov    es:[di+16],eax
  582.     mov    eax,r7
  583.     mov    es:[di+24],eax
  584.     mov    eax,r8
  585.     mov    es:[di+28],eax
  586.     mov    eax,r3
  587.     mov    es:[di+8],eax
  588.     mov    eax,r6
  589.     mov    es:[di+20],eax
  590.     mov    eax,r9
  591.     mov    es:[di+32],eax
  592.  
  593.     pop    dx
  594.     pop    cx
  595.     pop    di
  596.     pop    si
  597.     pop    ds
  598.     }
  599.  
  600. }
  601.  
  602.          /* full homogenous matrix multiply */
  603.  
  604. void matrix_product(MATRIX a, MATRIX b, MATRIX c)
  605. {
  606.  MATRIX d;
  607.  long x, y, z;
  608.  matrix_mult(a, b, d);
  609.  x = b[3][0];
  610.  y = b[3][1];
  611.  z = b[3][2];
  612.  matrix_point(a, &x, &y, &z);
  613.  d[3][0] = x;
  614.  d[3][1] = y;
  615.  d[3][2] = z;
  616.  memcpy (c, &d, sizeof(MATRIX));
  617. }
  618.  
  619.  
  620. void matrix_transpose(MATRIX a, MATRIX b)
  621. {
  622.  long s;
  623.  
  624.     b[0][0] = a[0][0];     /* generate inverse of rotate matrix (transpose) */
  625.     b[1][1] = a[1][1];     /* ONLY WORKS FOR ORTHOGONAL MATRICES            */
  626.     b[2][2] = a[2][2];     /* will do self_transpose as well as copy */
  627.  
  628.     s = a[0][1];
  629.     b[0][1] = a[1][0];
  630.     b[1][0] = s;
  631.  
  632.     s = a[2][0];
  633.     b[2][0] = a[0][2];
  634.     b[0][2] = s;
  635.  
  636.     s = a[2][1];
  637.     b[2][1] = a[1][2];
  638.     b[1][2] = s;
  639. }
  640.  
  641.  
  642. void inverse_matrix(MATRIX a, MATRIX b)
  643. {
  644.     long x = -a[3][0];       /* generate inverse of    */
  645.     long y = -a[3][1];       /* full homogenous matrix */
  646.     long z = -a[3][2];
  647.  
  648.     matrix_transpose(a,b);
  649.                 /* old: Ax+b = c      */
  650.     b[3][0] = 0;            /* b' = (1/A)(-b)     */
  651.     b[3][1] = 0;               /* (1/A) = t(A)       */
  652.     b[3][2] = 0;               /* new: (1/A)c+b' = x */
  653.  
  654.     matrix_point(b,&x,&y,&z);
  655.  
  656.     b[3][0] = x;
  657.     b[3][1] = y;
  658.     b[3][2] = z;
  659. }
  660.  
  661.  
  662.  
  663. void identity_matrix(MATRIX m)
  664. {
  665.  int i, j;
  666.  
  667.  m[0][0] = m[1][1] = m[2][2] = XFSC;
  668.  m[1][0] = m[2][0] = m[3][0] = 0;
  669.  m[0][1] = m[2][1] = m[3][1] = 0;
  670.  m[0][2] = m[1][2] = m[3][2] = 0;
  671. }
  672.  
  673.             /* copy 3x4 matrix */
  674.  
  675. void matrix_copy(MATRIX m, MATRIX n)
  676. {
  677.  memcpy (n, m, sizeof(MATRIX));
  678. }
  679.  
  680.             /* copy 3x3 rotation part of matrix */
  681.  
  682. void matrix_rot_copy(MATRIX m, MATRIX n)
  683. {
  684.  memcpy (n, m, sizeof(MATRIX));
  685.  n[3][0] = n[3][1] = n[3][2] = 0;
  686. }
  687.  
  688.  
  689.  
  690. /*************** ANGLE/POSITION TO HOMOGENOUS MATRIX ************/
  691.  
  692.  
  693. #define RXYZ 1        /* matrix rotation types */
  694. #define RYXZ 0          /* ONLY RYXZ guaranteed to be tested */
  695. #define RXZY 2
  696. #define RZYX 5
  697. #define RZXY 4
  698. #define RYZX 6                       /* create rotation/translation */
  699.                      /* "matrix" from angle data    */
  700.  
  701. void multi_matrix(MATRIX m, long rx, long ry, long rz,
  702.           long tx, long ty, long tz, int type )
  703. {
  704.  long sinx,cosx,siny,cosy,sinz,cosz;
  705.  long result;
  706.  
  707.  if (rx == 0)            /* tests for single-axis rotates */
  708.   {                   /* much faster to directly make  */
  709.    if (ry == 0)
  710.     {
  711.      identity_matrix(m);
  712.      if (rz != 0)
  713.       {
  714.        m[0][0] = m[1][1] = icosine(rz);
  715.        m[1][0] = isine(rz);
  716.        m[0][1] = -m[1][0];
  717.       }
  718.      goto shortcut;
  719.     }
  720.    else if (rz == 0)
  721.     {
  722.      identity_matrix(m);
  723.      m[0][0] = m[2][2] = icosine(ry);
  724.          m[0][2] = isine(ry);
  725.      m[2][0] = -m[0][2];
  726.      goto shortcut;
  727.     }
  728.   }
  729.  else if (ry == 0 && rz == 0)
  730.     {
  731.    identity_matrix(m);
  732.    m[1][1] = m[2][2] = icosine(rx);
  733.    m[2][1] = isine(rx);
  734.    m[1][2] = -m[2][1];
  735.    goto shortcut;
  736.   }
  737.  
  738.  cosx = icosine(rx);          /* angle compute */
  739.  cosy = icosine(ry);
  740.  cosz = icosine(rz);
  741.  sinx = isine(rx);
  742.  siny = isine(ry);
  743.  sinz = isine(rz);
  744.  
  745.  asm {
  746.     .386
  747.     push    si
  748.     push    di
  749.     push    cx
  750.     push    dx
  751.      }
  752.  
  753.  
  754.  if (type & 4)              /* negate angles? */
  755.   asm {
  756.     neg    DWORD PTR sinx
  757.     neg    DWORD PTR siny
  758.     neg    DWORD PTR sinz
  759.       }
  760.  
  761.  switch (type & 3)
  762.   {
  763.      case RXYZ:
  764.     {
  765.       asm {
  766.     mov    eax,cosz
  767.     imul    DWORD PTR cosy
  768.     shrd    eax,edx,29
  769.     adc    eax,0
  770.     mov    result,eax
  771.      }
  772.       m[0][0] = result;
  773.  
  774.      asm {
  775.     mov    eax,cosx
  776.     imul    DWORD PTR sinz
  777.     shrd    eax,edx,29
  778.     adc    eax,0
  779.     mov    ecx,eax
  780.     mov    eax,cosz
  781.     imul    DWORD PTR sinx
  782.     shrd    eax,edx,29
  783.     adc    eax,0
  784.     imul    DWORD PTR siny
  785.     shrd    eax,edx,29
  786.     adc    ecx,eax
  787.     mov    result,ecx
  788.      }
  789.       m[1][0] = result;
  790.  
  791.      asm {
  792.     mov    eax,sinz
  793.     imul    DWORD PTR sinx
  794.     shrd    eax,edx,29
  795.     adc    eax,0
  796.     mov    ecx,eax
  797.     mov    eax,cosz
  798.     imul    DWORD PTR cosx
  799.     shrd    eax,edx,29
  800.     adc    eax,0
  801.     imul    DWORD PTR siny
  802.     shrd    eax,edx,29
  803.     adc    eax,0
  804.     sub    ecx,eax
  805.     mov    result,ecx
  806.      }
  807.       m[2][0] = result;
  808.  
  809.       m[0][2] = siny;
  810.  
  811.       asm {
  812.     mov    eax,cosy
  813.     imul    DWORD PTR sinx
  814.     shrd    eax,edx,29
  815.     adc    eax,0
  816.     neg    eax
  817.     mov    result,eax
  818.      }
  819.       m[1][2] = result;
  820.  
  821.       asm {
  822.     mov    eax,cosx
  823.     imul    DWORD PTR cosy
  824.     shrd    eax,edx,29
  825.     adc    eax,0
  826.     mov    result,eax
  827.      }
  828.             m[2][2] = result;
  829.  
  830.       cross_column(m,1);
  831.       break;
  832.     }
  833.  
  834.    case RYXZ:
  835.     {
  836.      asm {
  837.     mov    eax,cosz
  838.     imul    DWORD PTR cosy
  839.     shrd    eax,edx,29
  840.     adc    eax,0
  841.     mov    ecx,eax
  842.     mov    eax,sinz
  843.     imul    DWORD PTR sinx
  844.     shrd    eax,edx,29
  845.     adc    eax,0
  846.     imul    DWORD PTR siny
  847.     shrd    eax,edx,29
  848.     adc    ecx,eax
  849.     mov    result,ecx
  850.      }
  851.       m[0][0] = result;
  852.  
  853.       asm {
  854.     mov    eax,cosx
  855.     imul    DWORD PTR sinz
  856.     shrd    eax,edx,29
  857.     adc    eax,0
  858.     mov    result,eax
  859.      }
  860.       m[1][0] = result;
  861.  
  862.          asm {
  863.     mov    eax,cosy
  864.     imul    DWORD PTR sinz
  865.     shrd    eax,edx,29
  866.     adc    eax,0
  867.     imul    DWORD PTR sinx
  868.     shrd    eax,edx,29
  869.     adc    eax,0
  870.     mov    ecx,eax
  871.     mov    eax,cosz
  872.     imul    DWORD PTR siny
  873.     shrd    eax,edx,29
  874.     adc    eax,0
  875.     sub    ecx,eax
  876.     mov    result,ecx
  877.      }
  878.       m[2][0] = result;
  879.  
  880.       asm {
  881.     mov    eax,cosx
  882.     imul    DWORD PTR siny
  883.     shrd    eax,edx,29
  884.     adc    eax,0
  885.     mov    result,eax
  886.      }
  887.       m[0][2] = result;
  888.  
  889.       m[1][2] = -sinx;
  890.  
  891.       asm {
  892.     mov    eax,cosx
  893.     imul    DWORD PTR cosy
  894.     shrd    eax,edx,29
  895.     adc    eax,0
  896.     mov    result,eax
  897.      }
  898.       m[2][2] = result;
  899.  
  900.       cross_column(m,1);
  901.       break;
  902.     }
  903.  
  904.    case RXZY:
  905.     {
  906.       asm {
  907.     mov    eax,cosz
  908.     imul    DWORD PTR cosy
  909.     shrd    eax,edx,29
  910.     adc    eax,0
  911.     mov    result,eax
  912.      }
  913.       m[0][0] = result;
  914.  
  915.      asm {
  916.     mov    eax,sinx
  917.     imul    DWORD PTR siny
  918.     shrd    eax,edx,29
  919.     adc    eax,0
  920.     mov    ecx,eax
  921.     mov    eax,cosx
  922.     imul    DWORD PTR cosy
  923.     shrd    eax,edx,29
  924.     adc    eax,0
  925.     imul    DWORD PTR sinz
  926.     shrd    eax,edx,29
  927.     adc    ecx,eax
  928.     mov    result,ecx
  929.      }
  930.       m[1][0] = result;
  931.  
  932.      asm {
  933.     mov    eax,cosy
  934.     imul    DWORD PTR sinz
  935.     shrd    eax,edx,29
  936.     adc    eax,0
  937.     imul    DWORD PTR sinx
  938.     shrd    eax,edx,29
  939.     adc    eax,0
  940.     mov    ecx,eax
  941.     mov    eax,cosx
  942.     imul    DWORD PTR siny
  943.     shrd    eax,edx,29
  944.     adc    eax,0
  945.     sub    ecx,eax
  946.     mov    result,ecx
  947.      }
  948.       m[2][0] = result;
  949.  
  950.       m[0][1] = -sinz;
  951.  
  952.       asm {
  953.     mov    eax,cosz
  954.     imul    DWORD PTR cosx
  955.     shrd    eax,edx,29
  956.     adc    eax,0
  957.     mov    result,eax
  958.      }
  959.       m[1][1] = result;
  960.  
  961.             asm {
  962.     mov    eax,cosz
  963.     imul    DWORD PTR sinx
  964.     shrd    eax,edx,29
  965.     adc    eax,0
  966.     mov    result,eax
  967.      }
  968.       m[2][1] = result;
  969.  
  970.       cross_column(m,2);
  971.       break;
  972.     }
  973.   }
  974.  
  975.  asm {
  976.     pop    dx
  977.     pop    cx
  978.     pop    di
  979.     pop    si
  980.      }
  981.  
  982.  if (type & 4) matrix_transpose(m,m);
  983.  
  984. shortcut:
  985.  m[3][0] = tx;
  986.  m[3][1] = ty;
  987.  m[3][2] = tz;
  988. }
  989.  
  990.         /* the default matrix: RYXZ  */
  991.         /* used for camera transform */
  992.  
  993. void std_matrix(MATRIX m, long rx, long ry, long rz,
  994.     long tx, long ty, long tz)
  995. {
  996.  multi_matrix(m, rx, ry, rz, tx, ty, tz, RYXZ);
  997. }
  998.  
  999.  
  1000. /*************** MATRIX-TO-ANGLES (RYXZ ONLY) *************/
  1001.  
  1002.  
  1003. extern long slow_magnitude(long a, long b);  /* done the float way */
  1004.  
  1005. void matrix_to_angle(MATRIX m, long *rx, long *ry, long *rz)
  1006. {
  1007.  long t,p,a;
  1008.  long c2;
  1009.  
  1010.  if (m[1][2] > 536334041 || m[1][2] < -536334041)
  1011.   {
  1012.    c2 = slow_magnitude(m[0][2],m[2][2]);    /* need accuracy for this one */
  1013.    if (c2 > 2000000)
  1014.     {
  1015.      p = arccosine(c2);
  1016.          if (m[1][2] < 0) p = -p;
  1017.     }
  1018.    else
  1019.     {
  1020. /*
  1021.      t = (m[1][2] < 0) ? 90*65536L : -90*65536L;
  1022.      p = 0;
  1023.      a = arctan2(m[0][1], m[0][0]);
  1024. */
  1025.      t = (m[1][2] < 0) ? 90*65536L : -90*65536L;  /* works with Z-axis rule */
  1026.      a = 0;
  1027.      p = arccosine(m[1][0]);
  1028.      if (m[1][2] > 0) p = -p;
  1029.  
  1030.      goto assign;
  1031.     }
  1032.   }
  1033.  else p = -arcsine(m[1][2]);
  1034.  
  1035.  t = arctan2(m[0][2], m[2][2]);
  1036.  a = arctan2(m[1][0], m[1][1]);
  1037.  
  1038. assign:
  1039.  
  1040.  *ry = t;
  1041.  *rx = p;
  1042.  *rz = a;
  1043. }
  1044.  
  1045.