home *** CD-ROM | disk | FTP | other *** search
/ DOS/V Power Report 1997 March / VPR9703A.ISO / VPR_DATA / DOGA / SOURCES / POLYEDIT.LZH / MODEL / VIEW1.C < prev    next >
C/C++ Source or Header  |  1996-04-25  |  11KB  |  490 lines

  1. /*
  2.  *        表示
  3.  *
  4.  *        Copyright    Koabayashi    1993.9.11
  5.  */
  6.  
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <math.h>
  11. #include <assert.h>
  12.  
  13. #define    VIEW_LOCAL
  14.  
  15. #include "matrix.h"
  16. #include "poly.h"
  17. #include "view.h"
  18. #include "input.h"
  19.  
  20. #define    RAD                (3.14159265/180.0)
  21. #define    CACHE_SIZE        1024
  22. #define CACHE_SET        4
  23.  
  24. int            ViewMode ;
  25. ViewWindow    WinXY, WinYZ, WinZX, WinPers ;
  26. int            VisibleVector ;                /*    法線ベクトル表示モード    */
  27. int            VisiblePolyVector ;            /*     面法線表示モード        */
  28. int            VisibleVertex ;                /*    頂点表示モード            */
  29. int            InvisibleDraw ;                /*     Invisibleを描画するか    */
  30. int            DrawFrontOnlyFlag ;            /*  表のみを描画するか        */
  31. int            Cx, Cy, Cz ;                /*    中心位置                */
  32. int            ZoomPlus, ZoomMinus ;        /*    ズーム値                */
  33. int            WinMove ;                    /*    ウインドウ移動量        */
  34. int            GridDisplay ;                /*    表示グリッド            */
  35. int            GridCursor ;                /*    カーソル移動グリッド    */
  36. int            PersMat[5][3] ;                /*    透視図用行列            */
  37. Matrix        PersMatInv;                    /*    カーソル逆算用行列        */
  38. int            ConvFlag ;                    /*    変換許可                */
  39. int            ConvMat[5][3] ;                /*    変換用行列                */
  40. int            ConvInv[5][3] ;                /*    変換用逆行列            */
  41. int            Mx, My, Mz, Mstat ;            /*    3D マウスカーソル        */
  42. int            PersMx, PersMy, PersMstat ;    /*    2D マウスカーソル        */
  43.  
  44. #if    0
  45. int            xyoffx, xyoffy ;        /*    オフセット                */
  46. int            yzoffy, yzoffz ;
  47. int            zxoffx, zxoffz ;
  48. #endif
  49. int        PersOffsetX, PersOffsetY, PersScaleX, PersAngleCount;
  50.  
  51. static    struct    {
  52.     short    x, y, z ;
  53.     short    flag ;
  54.     int        scr[2] ;
  55. }
  56.     VertexCache[CACHE_SIZE][CACHE_SET] ;
  57. static    int        DiscardSet;
  58. static    int        CacheHit, CacheMiss ;
  59. static    int        CacheHitSet[CACHE_SET];
  60.  
  61.  
  62. static    int        DispH, DispV ;                /*    ディスプレイサイズ        */
  63.  
  64. static    void    SetClip( int, int );
  65. static    void    SetOffset( void );
  66. static    void    CacheInit( void );
  67.  
  68.  
  69. /*    初期設定    */
  70. void    ViewInit( h, v )
  71. int        h, v ;
  72. {
  73.     Matrix    mat ;
  74.  
  75.     ViewMode = VIEW_ALL ;
  76.     PersAngleCount = 90;
  77.     SetClip( h, v );
  78.     VisibleVector = 0 ;
  79.     VisiblePolyVector = 0;
  80.     InvisibleDraw = TRUE;
  81.     DrawFrontOnlyFlag = FALSE;
  82.  
  83.     VisibleVertex = 0;
  84.     ViewSetCenter( 0, 0, 0 );
  85.     ViewSetZoom( 0, 0 );
  86.  
  87.     MatUnit( mat );
  88.     MatToInt( PersMat, mat );
  89.     MatUnit( PersMatInv );
  90.     ConvFlag = FALSE ;
  91.     MatToInt( ConvMat, mat );
  92.     GridCursor = 1 ;
  93.     GridDisplay = 1 ;
  94.     Mx = My = Mz = 0 ;
  95.     PersMx = PersMy = 0 ;
  96.     Mstat = OFF ;
  97.     PersMstat = PERS_CURSOR_OFF ;
  98.     CacheInit();
  99.  
  100. #if    0
  101.     ConvFlag = TRUE ;
  102.     MatRot( mat, AxisX, 45.0 );
  103.     MatToInt( ConvMat, mat );
  104.     MatInv( mat );
  105.     MatToInt( ConvInv, mat );
  106. #endif
  107.  
  108. }
  109.  
  110. /*    サイズ設定    */
  111. static    void    SetClip( h, v )
  112. int        h, v ;        /*    表示ウインドウサイズ    */
  113. {
  114.     DispH = h ;
  115.     DispV = v ;
  116.  
  117.     v -= MENU_WIDTH + STATUS_WIDTH ;
  118.     switch( ViewMode )
  119.     {
  120.         case VIEW_ALL:
  121.             WinXY.h = WinZX.h = h / 2 ;
  122.             WinXY.v = WinZX.v = v / 2 ;
  123.             WinYZ.h = WinPers.h = (h+1) / 2 ;
  124.             WinYZ.v = WinPers.v = (v+1) / 2 ;
  125.             WinXY.x = 0 ;
  126.             WinXY.y = MENU_WIDTH ;
  127.             WinYZ.x = h / 2 ;
  128.             WinYZ.y = v / 2 + MENU_WIDTH ;
  129.             WinZX.x = 0 ;
  130.             WinZX.y = v / 2 + MENU_WIDTH ;
  131.             WinPers.x = h / 2 ;
  132.             WinPers.y = MENU_WIDTH ;
  133.             break ;
  134.         case VIEW_XY:
  135.             WinXY.x = 0 ;
  136.             WinXY.y = MENU_WIDTH ;
  137.             WinXY.h = h ;
  138.             WinXY.v = v ;
  139.             break ;
  140.         case VIEW_YZ:
  141.             WinYZ.x = 0 ;
  142.             WinYZ.y = MENU_WIDTH ;
  143.             WinYZ.h = h ;
  144.             WinYZ.v = v ;
  145.             break ;
  146.         case VIEW_ZX:
  147.             WinZX.x = 0 ;
  148.             WinZX.y = MENU_WIDTH ;
  149.             WinZX.h = h ;
  150.             WinZX.v = v ;
  151.         case VIEW_PERS:
  152.             WinPers.x = 0 ;
  153.             WinPers.y = MENU_WIDTH ;
  154.             WinPers.h = h ;
  155.             WinPers.v = v ;
  156.             break ;
  157.     }
  158.     SetOffset();
  159. }
  160.  
  161. /*    表示設定    */
  162. void    ViewSetWindow( mode )
  163. int        mode ;
  164. {
  165.     ViewMode = mode ;
  166.     SetClip( DispH, DispV );
  167.     CacheInit();
  168. }
  169.  
  170. /*    ディスプレイサイズ設定    */
  171. void    ViewSetDisplay( h, v )
  172. int        h, v ;
  173. {
  174.     SetClip( h, v );
  175.     CacheInit();
  176. }
  177.  
  178. /*    中心値の設定    */
  179. void    ViewSetCenter( cx, cy, cz )
  180. int        cx, cy, cz ;
  181. {
  182.     Cx = cx ;
  183.     Cy = cy ;
  184.     Cz = cz ;
  185. }
  186.  
  187. /*    ズーム値の設定    */
  188. void    ViewSetZoom( zoom, move )
  189. int        zoom ;
  190. int        move ;
  191. {
  192.     if ( zoom > 0 )
  193.     {
  194.         ZoomPlus = zoom ;
  195.         ZoomMinus = 1 ;
  196.     }
  197.     else if ( zoom < 0 )
  198.     {
  199.         ZoomPlus = 1 ;
  200.         ZoomMinus = - zoom ;
  201.     }
  202.     else
  203.     {
  204.         ZoomPlus = 1 ;
  205.         ZoomMinus = 1 ;
  206.     }
  207.     if ( move == 0 )
  208.         WinMove = 10 * ZoomMinus / ZoomPlus ;
  209.     else
  210.         WinMove = move ;
  211. }
  212.  
  213. /*    透視図の設定    */
  214. void    ViewSetPers( mat )
  215. Matrix    mat ;
  216. {
  217.     MatToInt( PersMat, mat );
  218.     MatCopy(PersMatInv, mat);
  219.     MatInv(PersMatInv);
  220.     CacheInit();
  221. }
  222.  
  223. /*    グリッドの設定    */
  224. void    ViewSetGrid( gdisp, gcur )
  225. int        gdisp, gcur ;
  226. {
  227.     GridDisplay = gdisp ;
  228.     GridCursor = gcur ;
  229. }
  230.  
  231. /*    3面図の変換設定    */
  232. void    ViewSetConv( mat )
  233. Matrix    mat ;
  234. {
  235.     int        i, j ;
  236.     Matrix    inv ;
  237.  
  238.     ConvFlag = FALSE ;
  239.     for( i = 0 ; i < 3 ; i++ )
  240.     {
  241.         for( j = 0 ; j < 3 ; j++ )
  242.         {
  243.             if ( i == j )
  244.             {
  245.                 if( mat[i][j] != (float)1.0 )
  246.                     ConvFlag = TRUE ;
  247.             }
  248.             else
  249.             {
  250.                 if( mat[i][j] != (float)0.0 )
  251.                     ConvFlag = TRUE ;
  252.             }
  253.         }
  254.     }
  255.     if ( mat[3][0] != (float)0.0 || mat[3][1] != (float)0.0 || mat[3][1] != (float)0.0 )
  256.         ConvFlag = TRUE ;
  257.     MatCopy( inv, mat );
  258.     MatInv( inv );
  259.     MatToInt( ConvMat, mat );
  260.     MatToInt( ConvInv, inv );
  261. }
  262.  
  263. int PersAngle(int angle)
  264. {
  265.     int a = PersAngleCount;
  266.     PersOffsetX = WinPers.x + WinPers.h / 2 ;
  267.     PersOffsetY = WinPers.y + WinPers.v / 2 ;
  268.     if (angle > 0 && angle < 180 && angle != PersAngleCount) {
  269.         CacheInit();
  270.         PersAngleCount = angle;
  271.     }
  272.     PersScaleX = (int)((double)(WinPers.h / 2) / tan(3.14159265358979/180.0*(double)(PersAngleCount/2)));
  273.     return a;
  274. }
  275.  
  276. static    void    SetOffset()
  277. {
  278.     WinXY.offx = WinXY.x + WinXY.h / 2 ;
  279.     WinXY.offy = WinXY.y + WinXY.v / 2 ;
  280.     WinYZ.offx = WinYZ.x + WinYZ.h / 2 ;
  281.     WinYZ.offy = WinYZ.y + WinYZ.v / 2 ;
  282.     WinZX.offx = WinZX.x + WinZX.h / 2 ;
  283.     WinZX.offy = WinZX.y + WinZX.v / 2 ;
  284.     WinPers.offx = 0 ;
  285.     WinPers.offy = 0 ;
  286.  
  287.     PersAngle(0);
  288. }
  289.  
  290.  
  291.  
  292. /*    スクリーン座標に変換    */
  293. void    ToScreen( pos, ver )
  294. int        pos[3] ;
  295. Vertex    *ver ;
  296. {
  297.     int        i ;
  298.  
  299.     if ( ConvFlag )
  300.     {
  301.         for( i = 0 ; i < 3 ; i++ )
  302.         {
  303.             pos[i] = (((int)ver->x * ConvMat[0][i]
  304.                      + (int)ver->y * ConvMat[1][i]
  305.                      + (int)ver->z * ConvMat[2][i] ) >> 16)
  306.                      +               ConvMat[3][i];
  307.         }
  308.         pos[0] = ( pos[0] - Cx ) * ZoomPlus / ZoomMinus ;
  309.         pos[1] = ( pos[1] - Cy ) * ZoomPlus / ZoomMinus ;
  310.         pos[2] = ( pos[2] - Cz ) * ZoomPlus / ZoomMinus ;
  311.     }
  312.     else
  313.     {
  314.         pos[0] = ( ver->x - Cx ) * ZoomPlus / ZoomMinus ;
  315.         pos[1] = ( ver->y - Cy ) * ZoomPlus / ZoomMinus ;
  316.         pos[2] = ( ver->z - Cz ) * ZoomPlus / ZoomMinus ;
  317.     }
  318. }
  319.  
  320. /*    裏表判定    */
  321. int        ScreenFront(short *vec)
  322. {
  323.     int x;
  324.     x = (int)vec[0] * PersMat[0][0]
  325.       + (int)vec[1] * PersMat[1][0]
  326.       + (int)vec[2] * PersMat[2][0];
  327.     return x < 0;
  328. }
  329.  
  330.  
  331. /*    透視変換    */
  332. int        ToScreenPers( scr, local )
  333. int        *scr ;
  334. Vertex    *local ;
  335. {
  336.     int        i, j ;
  337.     int        w[3] ;
  338.     int        tag ;
  339. #if 0
  340.     tag = ( ( local->x * 2 + local->x +
  341.               local->y * 8 - local->y +
  342.               + local->z ) >> 1 ) & ( CACHE_SIZE - 1 );
  343. #endif
  344.     tag = ( ( (int)local->x *  8 + (int)local->x * 4 + (int)local->x +
  345.               (int)local->y *  8 + (int)local->y * 4 - (int)local->y +
  346.               (int)local->z * 16 + (int)local->z ) >> 1 ) & ( CACHE_SIZE - 1 );
  347.  
  348.     for (j = 0; j < CACHE_SET; ++j) {
  349.         if ( VertexCache[tag][j].flag >= 0 &&
  350.              *(int*)&VertexCache[tag][j] == *(int*)local &&
  351.              VertexCache[tag][j].z == local->z )
  352.         {
  353.             scr[0] = VertexCache[tag][j].scr[0] ;
  354.             scr[1] = VertexCache[tag][j].scr[1] ;
  355.             CacheHit ++ ;
  356.             CacheHitSet[j]++;
  357.             return VertexCache[tag][j].flag ;
  358.         }
  359.     }
  360.     CacheMiss ++ ;
  361.     for (j = 0; j < CACHE_SET; j++) {
  362.         if ( VertexCache[tag][j].flag < 0) {
  363.             break;
  364.         }
  365.     }
  366.     if (j == CACHE_SET) {
  367.         j = DiscardSet;
  368.         if (++DiscardSet == CACHE_SET) {
  369.             DiscardSet = 0;
  370.         }
  371.     }
  372.     *(int*)&VertexCache[tag][j] = *(int*)local ;
  373.     VertexCache[tag][j].z = local->z ;
  374. #if 0
  375. //
  376.     for( i = 0 ; i < 3 ; i++ )
  377.     {
  378.         w[i] = (int)local->x * PersMat[0][i]
  379.              + (int)local->y * PersMat[1][i]
  380.              + (int)local->z * PersMat[2][i]
  381.              +                 PersMat[3][i];
  382.     }
  383.  
  384. //
  385.     w[0] = ((int)local->x * PersMat[0][0] + (int)local->y * PersMat[1][0]
  386.          +  (int)local->z * PersMat[2][0] + PersMat[3][0]) >> 16;
  387.     w[1] = ((int)local->x * PersMat[0][1] + (int)local->y * PersMat[1][1]
  388.          +  (int)local->z * PersMat[2][1] + PersMat[3][1]) >> 16;
  389.     w[2] = ((int)local->x * PersMat[0][2] + (int)local->y * PersMat[1][2]
  390.          +  (int)local->z * PersMat[2][2] + PersMat[3][2]) >> 16;
  391.  
  392. //
  393.     w[0] = (((int)local->x * PersMat[0][0]
  394.          +   (int)local->y * PersMat[1][0]
  395.          +   (int)local->z * PersMat[2][0]) >> 16) + PersMat[3][0];
  396.     w[1] = (((int)local->x * PersMat[0][1]
  397.          +   (int)local->y * PersMat[1][1]
  398.          +   (int)local->z * PersMat[2][1]) >> 16) + PersMat[3][1];
  399.     w[2] = (((int)local->x * PersMat[0][2]
  400.          +   (int)local->y * PersMat[1][2]
  401.          +   (int)local->z * PersMat[2][2]) >> 16) + PersMat[3][2];
  402. #else
  403.     for( i = 0 ; i < 3 ; i++ )
  404.     {
  405.         int x, a, b;
  406.         a = b = 0;
  407.         x = (int)local->x * PersMat[0][i]; a += x >> 16; b += x & 65535;
  408.         x = (int)local->y * PersMat[1][i]; a += x >> 16; b += x & 65535;
  409.         x = (int)local->z * PersMat[2][i]; a += x >> 16; b += x & 65535;
  410.         a += PersMat[3][i] + (b >> 16);
  411.         w[i] = a;
  412.     }
  413. #endif
  414.     if ( w[0] > 0 )
  415.     {
  416. #if 0
  417.         scr[0] = - w[1] / ( w[0] / ( WinPers.h / 2 ) ) + WinPers.x + WinPers.h / 2 ;
  418.         scr[1] = - w[2] / ( w[0] / ( WinPers.h / 2 ) ) + WinPers.y + WinPers.v / 2 ;
  419. #endif
  420.         scr[0] = - PersScaleX * w[1] / w[0] + PersOffsetX;
  421.         scr[1] = - PersScaleX * w[2] / w[0] + PersOffsetY;
  422.  
  423.         VertexCache[tag][j].scr[0] = scr[0] ;
  424.         VertexCache[tag][j].scr[1] = scr[1] ;
  425.         VertexCache[tag][j].flag = TRUE ;
  426.         return TRUE ;
  427.     }
  428.     else
  429.     {
  430.         VertexCache[tag][j].flag = FALSE ;
  431.         return FALSE ;
  432.     }
  433. }
  434.  
  435. static    void    CacheInit()
  436. {
  437.     int        i, j ;
  438. #if 0
  439. printf("Hit=%5d, Miss=%5d, Ratio = %5.2lf%% : ", CacheHit, CacheMiss, (double)CacheHit / (double)(CacheHit + CacheMiss + 1));
  440.     for (j = 0; j < CACHE_SET; j++ )
  441.         printf("Hit[%d]=%5d, ", j, CacheHitSet[j]);
  442. printf("\n");
  443. #endif
  444.     CacheHit = 0 ;
  445.     CacheMiss = 0 ;
  446.     DiscardSet = 0;
  447.     for( i = 0 ; i < CACHE_SIZE ; i++ )
  448.         for (j = 0; j < CACHE_SET; j++ )
  449.             VertexCache[i][j].flag = -1 ;
  450.     for (j = 0; j < CACHE_SET; j++ )
  451.         CacheHitSet[j] = 0;
  452. }
  453.  
  454. /*    行列の整数化    */
  455. void    MatToInt( m, mm )
  456. int        m[5][3] ;
  457. Matrix    mm ;
  458. {
  459.     int        i, j ;
  460. #if 1
  461.     for( i = 0 ; i < 3 ; i++ )
  462.     {
  463.         for( j = 0 ; j < 3 ; j++ )
  464.             m[i][j] = (int)( mm[i][j] * 65536.0 );
  465.     }
  466.     for( j = 0 ; j < 3 ; j++ ) {
  467.         m[3][j] = (int)( mm[3][j] );
  468.         m[4][j] = (int)( (mm[3][j]-(double)m[3][j]) * 65536.0 );
  469.     }
  470. #else
  471.  
  472. #if 0
  473.     for( i = 0 ; i < 3 ; i++ )
  474.     {
  475.         for( j = 0 ; j < 3 ; j++ )
  476.             m[i][j] = (int)( mm[i][j] * 65536.0 );
  477.     }
  478.     for( j = 0 ; j < 3 ; j++ )
  479.         m[3][j] = (int)( mm[3][j] );
  480. #else
  481.     for( i = 0 ; i < 4 ; i++ )
  482.     {
  483.         for( j = 0 ; j < 3 ; j++ )
  484.             m[i][j] = (int)( mm[i][j] * 65536.0 );
  485.     }
  486. #endif
  487. #endif
  488. }
  489.  
  490.