home *** CD-ROM | disk | FTP | other *** search
/ DOS/V Power Report 1997 March / VPR9703A.ISO / VPR_DATA / DOGA / SOURCES / REND.LZH / REND / VIEWCONV.C < prev   
C/C++ Source or Header  |  1996-07-29  |  16KB  |  714 lines

  1. /*
  2.         透視変換関数
  3.  
  4.             1989.6.18
  5.             Copyright    T.Kobayashi
  6.  
  7. */
  8.  
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <math.h>
  13. #include <assert.h>
  14.  
  15. #ifdef FLOAT
  16.                     /*(2^24-1)<<7*/
  17. #define MAXLONGF    2147483520.0
  18. #else
  19.                     /*(2^31-1)*/
  20. #define MAXLONGF    2147483647.0
  21. #endif
  22.  
  23.  
  24. #include "reader.h"
  25. #include "glib.h"
  26.  
  27. static    Matrix        view ;            /*    視点変換行列                    */
  28. static    Matrix        world ;            /*    ワールド座標変換行列            */
  29. static    Matrix        worldit ;        /*    ワールド座標変換転置逆行列        */
  30. static    Matrix        conv ;            /*    座標変換行列                    */
  31.  
  32. static    Float        fxpixel ;
  33. static    Float        fypixel ;        /*    ピクセル数                        */
  34. static    long        polynum ;        /*    登録したポリゴンの数            */
  35.  
  36. static    Point        *convbuf ;        /*    ワーク領域                        */
  37. static    Point        *clipbuf ;        /*    ワーク領域(クリッピング用)    */
  38. static    AtrTable    *atrconvbuf ;    /*    アトリビュートデータバッファ    */
  39. static    AtrTable    *atrclipbuf ;    /*    アトリビュートデータバッファ    */
  40. static    int            bufsize = 0 ;    /*    領域のサイズ                    */
  41. /*static    int            inbg = FALSE;*/
  42. /*
  43.     proto -s viewconv.c > temp
  44. */
  45. static    void    conv_poly( Poly*, Frame* );
  46. static    int        clipcheck( Point*, int );
  47. static    int        screenclip( Point*, AtrTable*, int );
  48. static    int        clip( Point*, AtrTable*, int, int, Float, int );
  49. static    void    lineclip( int, Point*, AtrTable*, int, int, int, Float);
  50. static    void    viewconvbg(Frame *frame);
  51.  
  52. /*
  53.         視点座標変換(エッジリストの作成)
  54.         戻り値    プリミティブの数
  55.                 -1:エラー
  56. */
  57. long    ViewConv( frame )
  58. Frame    *frame ;
  59. {
  60.     int        i, j, n ;
  61.     int        lockop, lockpoly ;
  62.     Matrix    m ;
  63.     ObjPos    *op ;
  64.     Object    *obj ;
  65.     Poly    *poly ;
  66.     Point    bound[8*2] ;    /*    バウンディングポックス    */
  67. #ifdef MOB
  68.     extern int TimeAnti;
  69.     static    int tpos = 0;
  70.     static int ax[16] = {0,2,2,0,1,3,3,1,1,3,3,1,0,2,2,0};
  71.     static int ay[16] = {0,2,0,2,1,3,1,3,0,2,0,2,1,3,1,3};
  72. #endif
  73.  
  74.     fxpixel = (Float)XPixel ;
  75.     fypixel = (Float)YPixel ;
  76.  
  77.     /*    視点変換行列の生成    奥行き方向はzに変換 */
  78.     m_inv( view, frame->eye.mat );
  79.  
  80.     /*    奥行き座標軸の変更    */
  81.     m_unit( m );
  82.     m[0][0] = m[1][1] = m[2][2] = 0.0 ;
  83.     m[0][2] = m[1][0] = m[2][1] = 1.0 ;
  84.     m_mult( view, view, m );
  85.  
  86.     /*    スクリーン座標変換    */
  87.     m_unit( m );
  88.     m[2][0] = fxpixel / 2.0 ;
  89.     m[2][1] = fypixel / 2.0 ;
  90.     m[0][0] = - frame->eye.dist * fxpixel ;
  91.     m[1][1] = - frame->eye.dist * fxpixel / PixelRatio ;
  92. #ifdef MOB
  93.     if (TimeAnti > 1) {
  94.         m[2][0] -= 0.25 * (Float)ax[tpos];
  95.         m[2][1] -= 0.25 * (Float)ay[tpos];
  96.         if (TimeAnti == 2) {
  97.             if (++tpos == 4) {
  98.                 tpos = 0;
  99.             }
  100.         } else {
  101.             if (++tpos == 16) {
  102.                 tpos = 0;
  103.             }
  104.         }
  105.     }
  106. #endif
  107.     m_mult( view, view, m );
  108. #ifdef STAR
  109.     Star(frame->env.star, view, frame->eye.dist);
  110. #endif
  111.  
  112.  
  113.     /*    初期化    */
  114.     InitEdgeList() ;    /*    エッジリストの初期化  */
  115.     polynum = 0 ;
  116. #ifdef BGMAKE
  117.     if (BgMake && ShadingModel == GOURAUD_SHADE ) {
  118.         viewconvbg(frame);
  119.     }
  120. #endif
  121.     op = pointer( frame->objpos );
  122.     if ( op == NULL )
  123.         return 0;
  124.  
  125.     /*    メインループ  */
  126.     for( ; op != NULL ; op = pointer( op->next ) )
  127.     {
  128.         lockop = datalock() ;
  129.         /*    行列のセット  */
  130.  
  131.         m_copy( world, op->mat );
  132.         m_inv( m, world );
  133.         m_trans( worldit, m );
  134.         m_mult( conv, world, view );
  135.         /*    物体のクリッピング    */
  136.         obj = pointer( op->obj );
  137.         for( i = 0 ; i < 8 ; ++i )
  138.         {
  139.             for( j = 0 ; j < 3 ; ++j )
  140.             {
  141.                 if ( i & ( 1 << j ) )
  142.                     bound[i][j] = obj->max[j] ;
  143.                 else
  144.                     bound[i][j] = obj->min[j] ;
  145.             }
  146.         }
  147.  
  148.         /*    座標変換  */
  149.         vec_mult_mat( bound, bound, conv, 8, 1 );
  150.  
  151.         /*    クリッピングチェック    */
  152.         if ( clipcheck( bound, 8 ) == 0 ) {
  153.             continue ;
  154.         }
  155.  
  156.         /*    物体の描画    */
  157.         n = obj->polynum ;
  158.         poly = pointer( obj->poly );
  159.         for( i = 0 ; i < n ; ++i )
  160.         {
  161.             assert( poly != NULL );
  162.             lockpoly = datalock();
  163.             conv_poly( poly, frame );
  164.             dataunlock( lockpoly );
  165.             poly = pointer( poly->next );
  166.         }
  167.         dataunlock( lockop );
  168.     }
  169.     return( polynum );
  170. }
  171.  
  172. #ifdef BGMAKE
  173. static void viewconvbg(Frame *frame)
  174. {
  175.     int x, y;
  176.     int px, py;
  177.     Poly pol;
  178.     Point point[4];
  179.     Vector uv[4];
  180.     double theta, phi, nphi;
  181.  
  182.     pol.type = UVPOLY;
  183.     pol.atr = NULL;
  184.     pol.atrid = 0;
  185.     pol.pointnum = 4;
  186.     pol.point = point;
  187.     pol.vec = NULL;
  188.     pol.uv = uv;
  189.     pol.coe[0] = pol.coe[1] = pol.coe[2] = pol.coe[3] = 0.0;
  190.     pol.next = NULL;
  191.  
  192.     m_unit(world);
  193.     world[3][0] = frame->eye.mat[3][0];
  194.     world[3][1] = frame->eye.mat[3][1];
  195.     world[3][2] = frame->eye.mat[3][2];
  196.  
  197.     m_unit(worldit);
  198.     m_mult( conv, world, view );
  199.  
  200. /*#define RADIUS ((double)FrontClip * (double)(MAXLONGF/8))*/
  201. #define RADIUS (MAXLONGF/1024)
  202. #define STEPX 8
  203. #define STEPY 8
  204. #define PI 3.14159265358979
  205. #define STEPPHI (PI/(3*STEPY))
  206. #define STEPTHETA (PI * 2 / (4*STEPX))
  207. /*    inbg = TRUE;*/
  208. /*    phi = 0.0;    */
  209. #define STEPPHI (PI * 3 / 8 / STEPY)
  210.     phi = (PI - STEPPHI * 3 * STEPY) * 0.5;
  211.     for (y = 0; y < 3*STEPY; y++, phi = nphi) {
  212.         nphi = phi + STEPPHI;
  213.         if (nphi < 0.0) {
  214.             continue;
  215.         } else if (phi >= PI) {
  216.             break;
  217.         } else if (phi < 0.0) {
  218.             phi = 0;
  219.         } else if (nphi >= PI) {
  220.             nphi = PI;
  221.         }
  222.         py = y / STEPY;
  223.         theta = - (PI/4);
  224.  
  225.         point[0][0] =  RADIUS * sin(phi) * cos(theta);
  226.         point[0][1] = -RADIUS * sin(phi) * sin(theta);
  227.         point[0][2] =  RADIUS * cos(phi);
  228.         point[1][0] =  RADIUS * sin(nphi) * cos(theta);
  229.         point[1][1] = -RADIUS * sin(nphi) * sin(theta);
  230.         point[1][2] =  RADIUS * cos(nphi);
  231.         point[2][2] = point[1][2];
  232.         point[3][2] = point[0][2];
  233.  
  234.         pol.coe[0] = - point[0][0];
  235.         pol.coe[1] = - point[0][1];
  236.         pol.coe[2] = - point[0][2];
  237.         v_unit(pol.coe, pol.coe);
  238.         pol.coe[3] = point[0][0] + point[0][1] + point[0][2];
  239.  
  240.         for (x = 0; x < 4*STEPX; x++) {
  241.             px = x / STEPX;
  242.             theta += STEPTHETA;
  243.             point[3][0] =  RADIUS * sin(phi) * cos(theta);
  244.             point[3][1] = -RADIUS * sin(phi) * sin(theta);
  245.             point[2][0] =  RADIUS * sin(nphi) * cos(theta);
  246.             point[2][1] = -RADIUS * sin(nphi) * sin(theta);
  247.  
  248.             uv[0][0] = uv[1][0] = (double)((x%STEPX)  )/(double)STEPX;
  249.             uv[2][0] = uv[3][0] = (double)((x%STEPX)+1)/(double)STEPX;
  250.             uv[0][1] = uv[3][1] = (double)((y%STEPY)  )/(double)STEPY;
  251.             uv[1][1] = uv[2][1] = (double)((y%STEPY)+1)/(double)STEPY;
  252.  
  253.             if (BgMake == 12) {
  254.                 pol.atr = BgMakeAtr[px + 4 * py];
  255.             } else if (BgMake == 6) {
  256.                 pol.atr = BgMakeAtr[(px % 2) + 2 * py];
  257.             } else if (BgMake == 4) {
  258.                 pol.atr = BgMakeAtr[px];
  259.                 if (py == 0) {
  260.                     uv[0][1] = uv[1][1] = uv[2][1] = uv[3][1] = 0.0;
  261.                 } else if (py == 2) {
  262.                     uv[0][1] = uv[1][1] = uv[2][1] = uv[3][1] = 1.0;
  263.                 }
  264.             } else if (BgMake == 2) {
  265.                 pol.atr = BgMakeAtr[px % 2];
  266.                 if (py == 0) {
  267.                     uv[0][1] = uv[1][1] = uv[2][1] = uv[3][1] = 0.0;
  268.                 } else if (py == 2) {
  269.                     uv[0][1] = uv[1][1] = uv[2][1] = uv[3][1] = 1.0;
  270.                 }
  271.             } else if (BgMake == 1) {
  272.                 pol.atr = BgMakeAtr[0];
  273.                 uv[0][0] = uv[1][0] = (double)(x  )/(double)(STEPX*4);
  274.                 uv[2][0] = uv[3][0] = (double)(x+1)/(double)(STEPX*4);
  275.                 uv[0][1] = uv[3][1] = (double)(y  )/(double)(STEPY*3);
  276.                 uv[1][1] = uv[2][1] = (double)(y+1)/(double)(STEPY*3);
  277.             }
  278.  
  279.             conv_poly( &pol, frame );
  280.             point[1][0] = point[2][0];
  281.             point[1][1] = point[2][1];
  282.             point[1][2] = point[2][2];
  283.             point[0][0] = point[3][0];
  284.             point[0][1] = point[3][1];
  285.             point[0][2] = point[3][2];
  286.         }
  287. /*        phi += STEPPHI;*/
  288.     }
  289. /*    inbg = FALSE;*/
  290. }
  291. #endif
  292.  
  293.  
  294. /*        ポリゴンの視点変換        */
  295. static    void    conv_poly( poly, frame )
  296. Poly    *poly ;
  297. Frame    *frame ;
  298. {
  299.     int        i, n, ch ;
  300.     static    AtrTable    atrbuf ;
  301.     n = poly->pointnum ;
  302.  
  303.     /*    ワークサイズのチェック&更新  */
  304.     if ( n > bufsize )
  305.     {
  306.         if ( bufsize > 0 )
  307.         {
  308.             tempfree( convbuf );
  309.             tempfree( clipbuf );
  310.             if ( ShadingModel == GOURAUD_SHADE )
  311.             {
  312.                 tempfree( atrconvbuf );
  313.                 tempfree( atrclipbuf );
  314.             }
  315.         }
  316.         bufsize = n ;
  317.         convbuf = (Point*)tempalloc( bufsize * 2 * sizeof( Point ) );
  318.         clipbuf = (Point*)tempalloc( bufsize * 2 * sizeof( Point ) );
  319.         if ( ShadingModel == GOURAUD_SHADE )
  320.         {
  321.             atrconvbuf = tempalloc( bufsize * 2 * sizeof( AtrTable ) );
  322.             atrclipbuf = tempalloc( bufsize * 2 * sizeof( AtrTable ) );
  323.         }
  324.         else
  325.             atrconvbuf = & atrbuf ;
  326.     }
  327.  
  328.  
  329.     /*    座標変換  */
  330.     vec_mult_mat( convbuf, (Point*)pointer(poly->point), conv, n, 1 );
  331.  
  332.     /*    クリッピングチェック    */
  333.     ch = clipcheck( convbuf, n ) ;
  334.     if ( ch == 0 )
  335.         return ;
  336.  
  337.     /*    光度計算 */
  338. #ifdef BACKFACE
  339.     if (GetAtrTable( atrconvbuf, frame, poly, world, worldit ) == FALSE) {
  340.         return;
  341.     }
  342. #else
  343.     GetAtrTable( atrconvbuf, frame, poly, world, worldit );
  344. #endif
  345.     /*    クリッピング    */
  346.     if ( ch == 1 )
  347.     {
  348.         n = screenclip( convbuf, atrconvbuf, n );
  349.         if ( n == 0 )
  350.             return ;
  351.     }
  352. #if 0
  353.     else if (inbg) {
  354.         /*    透視変換    */
  355.         for( i = 0 ; i < n ; ++i )
  356.         {
  357.             convbuf[i][0] /= convbuf[i][2] ;
  358.             convbuf[i][1] /= convbuf[i][2] ;
  359.             convbuf[i][2] = FrontClip;
  360.         }
  361. #endif
  362.     else
  363.     {
  364.         /*    透視変換    */
  365.         for( i = 0 ; i < n ; ++i )
  366.         {
  367.             convbuf[i][0] /= convbuf[i][2] ;
  368.             convbuf[i][1] /= convbuf[i][2] ;
  369.             convbuf[i][2] = FrontClip * MAXLONGF / convbuf[i][2] ;
  370.         }
  371.     }
  372.  
  373.     /*    エッジリストに登録    */
  374.     SetEdgeList( convbuf, atrconvbuf, n, poly->atr );
  375.  
  376.     polynum++ ;
  377. }
  378.  
  379. /*
  380.     クリッピングのチェック
  381.     戻り値    0    すべてビューポート外
  382.             1    クリッピングの必要あり
  383.             2    すべてビューポート内
  384. */
  385. static    int        clipcheck( buf, n )
  386. Point    *buf ;
  387. int        n ;
  388. {
  389.     int        i, flag, isin, isout ;
  390.     Float    x, y ;
  391.  
  392.     isin = 31 ;
  393.     isout = 0 ;
  394.     for( i = 0 ; i < n ; ++i )
  395.     {
  396. #if 0
  397.         x = buf[i][0] / buf[i][2] ;
  398.         y = buf[i][1] / buf[i][2] ;
  399.         flag = 0 ;
  400.         if ( FrontClip <= buf[i][2] )
  401.             flag += 16 ;
  402.         else
  403.         {
  404.             x = - x ;
  405.             y = - y ;
  406.         }
  407.         if ( 0.0 <= x )
  408.             flag += 1 ;
  409.         if ( x < fxpixel )
  410.             flag += 2 ;
  411.         if ( 0.0 <= y )
  412.             flag += 4 ;
  413.         if ( y < fypixel )
  414.             flag += 8 ;
  415.         isin &= flag ;
  416.         isout |= flag ;
  417. #endif
  418.         if (buf[i][2] == 0.0) {
  419.             x = 0;
  420.             y = 0;
  421.         } else {
  422.             x = buf[i][0] / buf[i][2] ;
  423.             y = buf[i][1] / buf[i][2] ;
  424.         }
  425.         flag = 0 ;
  426.         if ( FrontClip <= buf[i][2] )
  427.             flag += 16 ;
  428.         else
  429.         {
  430.             x = - x ;
  431.             y = - y ;
  432.         }
  433.         if ( 0.0 <= x )
  434.             flag += 1 ;
  435.         if ( x < fxpixel )
  436.             flag += 2 ;
  437.         if ( 0.0 <= y )
  438.             flag += 4 ;
  439.         if ( y < fypixel )
  440.             flag += 8 ;
  441.         isin &= flag ;
  442.         isout |= flag ;
  443. #if 0
  444.         if ( FrontClip > buf[i][2] ) {
  445.             flag = 0;
  446.         } else {
  447.             x = buf[i][0] / buf[i][2] ;
  448.             y = buf[i][1] / buf[i][2] ;
  449.             flag = 16 ;
  450.             if ( 0.0 <= x )
  451.                 flag += 1 ;
  452.             if ( x < fxpixel )
  453.                 flag += 2 ;
  454.             if ( 0.0 <= y )
  455.                 flag += 4 ;
  456.             if ( y < fypixel )
  457.                 flag += 8 ;
  458.         }
  459.         isin &= flag ;
  460.         isout |= flag ;
  461. #endif
  462.     }
  463.  
  464.     if ( isout != 31 )
  465.         return( 0 );
  466.     if ( isin == 31 )
  467.         return( 2 );
  468.     return( 1 );
  469. }
  470.  
  471. /*
  472.     スクリーンクリッピング
  473.     戻り値    クリッピング後の頂点数
  474. */
  475. static    int        screenclip( buf, atrbuf, n )
  476. Point        *buf ;
  477. AtrTable    *atrbuf ;
  478. int            n ;
  479. {
  480.     int        i ;
  481.     int        isin, isout, flags ;
  482.  
  483.     /*    前面クリッピング  */
  484.     isin = 1 ;
  485.     isout = 0 ;
  486.     for( i = 0 ; i < n ; ++i )
  487.     {
  488.         flags = ( buf[i][2] > FrontClip ) ;
  489.         isin &= flags ;
  490.         isout |= flags ;
  491.     }
  492.     if ( isout == 0 )    /*    すべてビューポート外  */
  493.         return( 0 );
  494.     if ( isin != 1 )    /*    すべてビューポート内ではない */
  495.     {
  496.         n = clip( buf, atrbuf, n, 2, FrontClip, TRUE );
  497.     }
  498.  
  499.     /*    透視変換    */
  500.     for( i = 0 ; i < n ; ++i )
  501.     {
  502.         buf[i][0] /= buf[i][2] ;
  503.         buf[i][1] /= buf[i][2] ;
  504.         buf[i][2] = FrontClip * MAXLONGF / buf[i][2] ;
  505.     }
  506.  
  507.     /*    スクリーンクリッピング    */
  508.     isin = 0x0f ;
  509.     isout = 0 ;
  510.     for( i = 0 ; i < n ; ++i )
  511.     {
  512.         flags = 0 ;
  513.         if ( buf[i][0] >= 0.0 )
  514.             flags += 1 ;
  515.         if ( buf[i][0] < fxpixel )
  516.             flags += 2 ;
  517.         if ( buf[i][1] >= 0.0 )
  518.             flags += 4 ;
  519.         if ( buf[i][1] < fypixel )
  520.             flags += 8 ;
  521.         isin &= flags ;
  522.         isout |= flags ;
  523.     }
  524.  
  525.     if ( isout != 0x0f )    /*    すべてスクリーン外    */
  526.         return( 0 );
  527.     if ( isin != 0x0f )        /*    すべてスクリーンの中にあるわけではない */
  528.     {
  529.         /*    クリッピングの必要あり */
  530.         if ( ( isin & 1 ) == 0 )    /*    左にはずれている  */
  531.         {
  532.             n = clip( buf, atrbuf, n, 0, 0.0, TRUE );
  533.             if ( n == 0 )
  534.                 return( 0 ) ;
  535.         }
  536.         if ( ( isin & 2 ) == 0 )    /*    右にはずれている  */
  537.         {
  538.             n = clip( buf, atrbuf, n, 0, fxpixel, FALSE );
  539.             if ( n == 0 )
  540.                 return( 0 ) ;
  541.         }
  542.         if ( ( isin & 4 ) == 0 )    /*    上にはずれている  */
  543.         {
  544.             n = clip( buf, atrbuf, n, 1, 0.0, TRUE );
  545.             if ( n == 0 )
  546.                 return( 0 ) ;
  547.         }
  548.         if ( ( isin & 8 ) == 0 )    /*    下にはずれている  */
  549.         {
  550.             n = clip( buf, atrbuf, n, 1, fypixel, FALSE );
  551.             if ( n == 0 )
  552.                 return( 0 ) ;
  553.         }
  554.     }
  555.     return( n );
  556. }
  557.  
  558. /*
  559.     クリッピング
  560.         ワーク領域 clipbuf, scclipbuf を使用
  561.     戻り値    クリッピング後の頂点の数
  562.         すべてビューポート内にない場合は0
  563.     引数
  564.     n    頂点の数
  565.     (*inview)( point )
  566.         1:point がビューポート内にある。
  567.         0:point がビューポート内にない。
  568.     (*lineclip)( point, point1, point2 )
  569.         point1 と point2 を結んだ線分とビューポートの境界線との交点を
  570.         求める
  571. */
  572. static    int        clip( Point *buf, AtrTable *atrbuf, int n, int axis, Float border, int sw )
  573. {
  574.     int        i, j, flag, f ;
  575.     int        last ;        /*    ひとつ前の配列要素        */
  576.     int        lastflag ;    /*    ひとつ前の頂点の状態    */
  577.  
  578.     if ( axis == 2 )
  579.         f = FALSE ;
  580.     else
  581.         f = TRUE ;
  582.  
  583.     /*    クリッピング */
  584.     j = 0 ;                    /*    clipbuf のカウンタ    */
  585.     last = n - 1 ;
  586.     if ( sw )
  587.         lastflag = ( buf[last][axis] > border );
  588.     else
  589.         lastflag = ( border > buf[last][axis] );
  590.     for( i = 0 ; i < n ; ++i )
  591.     {
  592.         if ( sw )
  593.             flag = ( buf[i][axis] > border );
  594.         else
  595.             flag = ( border > buf[i][axis] );
  596.         if ( flag )
  597.         {
  598.             if ( lastflag ) /*    中にいたまま */
  599.             {
  600.                 v_copy( clipbuf[j], buf[i] ) ;
  601.                 if ( ShadingModel == GOURAUD_SHADE )
  602.                     atrclipbuf[j] = atrbuf[i] ;
  603.                 j++ ;
  604.             }
  605.             else
  606.             {
  607.                 /*    外から中に    */
  608.                 lineclip( j++, buf, atrbuf, i, last, axis, border );
  609.  
  610.                 v_copy( clipbuf[j], buf[i] );
  611.                 if ( ShadingModel == GOURAUD_SHADE )
  612.                     atrclipbuf[j] = atrbuf[i] ;
  613.                 j++ ;
  614.             }
  615.         }
  616.         else
  617.         {
  618.             if ( lastflag )
  619.             {
  620.                 /*    中から外に    */
  621.                 lineclip( j++, buf, atrbuf, i, last, axis, border );
  622.             }
  623.             /*    外にいたままのときはなにもしない  */
  624.         }
  625.         last = i ;
  626.         lastflag = flag ;
  627.     }
  628.  
  629.     memcpy( (char *)buf, (char *)clipbuf, j * sizeof( Point ) );
  630.     if ( ShadingModel == GOURAUD_SHADE )
  631.         memcpy( (char*)atrbuf, (char*)atrclipbuf, j * sizeof( AtrTable ) );
  632.  
  633.     return( j );
  634. }
  635.  
  636. /*    線分のクリッピング    */
  637. static    void    lineclip( int n, Point *buf, AtrTable *atrbuf, int cur, int last, int axis, Float border )
  638. {
  639.     int            i ;
  640.     Float        t ;
  641.     AtrTable    *a1, *a2, *ap ;
  642.  
  643.     t = ( border - buf[last][axis] ) / ( buf[cur][axis] - buf[last][axis] ) ;
  644.     clipbuf[n][0] = ( buf[cur][0] - buf[last][0] ) * t + buf[last][0] ;
  645.     clipbuf[n][1] = ( buf[cur][1] - buf[last][1] ) * t + buf[last][1] ;
  646.     clipbuf[n][2] = ( buf[cur][2] - buf[last][2] ) * t + buf[last][2] ;
  647.  
  648.     if ( ShadingModel == GOURAUD_SHADE )
  649.     {
  650.         a1 = atrbuf + last ;
  651.         a2 = atrbuf + cur ;
  652.         ap = atrclipbuf + n ;
  653.  
  654.         /*    線形補間    */
  655.         for( i = 0 ; i < 3 ; ++i )
  656.         {
  657.             ap->shade.curcolor[i]
  658.                     = (long)(
  659.                             (Float)( a2->shade.curcolor[i] -
  660.                                       a1->shade.curcolor[i] ) * t
  661.                             )
  662.                     + a1->shade.curcolor[i] ;
  663. #ifdef SPEC
  664.             ap->shade.curspecular[i]
  665.                     = (long)(
  666.                             (Float)( a2->shade.curspecular[i] -
  667.                                       a1->shade.curspecular[i] ) * t
  668.                             )
  669.                     + a1->shade.curspecular[i] ;
  670.             ap->shade.depthcolor[i] = a1->shade.depthcolor[i];
  671. #endif
  672.         }
  673. #ifdef REFMAP
  674.         if (RefMap) {
  675.             double len = 0.0;
  676.             for (i = 0; i < 3; ++i) {
  677.                 ap->shade.refcolor[i] = a1->shade.refcolor[i];
  678.                 ap->shade.currefdir[i]
  679.                      = (long)((Float)(a2->shade.currefdir[i] - a1->shade.currefdir[i]) * t)
  680.                      + a1->shade.currefdir[i];
  681.             }
  682. #if 0
  683.                 len += (Float)ap->shade.currefdir[i] * (Float)ap->shade.currefdir[i];
  684.             if (len >= 1.0) {
  685.                 for (i = 0; i < 3; ++i) {
  686.                     ap->shade.currefdir[i] = (Float)(ap->shade.currefdir[i]) / len * SHADE_POINT;
  687.                 }
  688.             }
  689. #endif
  690.         }
  691. #endif
  692. #ifdef SPEC
  693.         ap->shade.depthrate
  694.                 = (long)((Float)(a2->shade.depthrate - a1->shade.depthrate)*t)
  695.                 + a1->shade.depthrate;
  696.  
  697. #endif
  698.         if (axis != 2) {
  699.             t = t * buf[cur][2] /
  700.                     (buf[last][2] + (buf[cur][2]-buf[last][2])*t);
  701.         }
  702.         for( i = 0 ; i < 2 ; ++i )
  703.         {
  704.             ap->map.curuv[i]
  705.                     = (long)(
  706.                             (Float)( a2->map.curuv[i] -
  707.                                       a1->map.curuv[i] ) * t
  708.                             )
  709.                     + a1->map.curuv[i] ;
  710.         }
  711.         ap->map.map = a1->map.map ;
  712.     }
  713. }
  714.