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 >
Wrap
C/C++ Source or Header
|
1996-04-25
|
11KB
|
490 lines
/*
* 表示
*
* Copyright Koabayashi 1993.9.11
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <assert.h>
#define VIEW_LOCAL
#include "matrix.h"
#include "poly.h"
#include "view.h"
#include "input.h"
#define RAD (3.14159265/180.0)
#define CACHE_SIZE 1024
#define CACHE_SET 4
int ViewMode ;
ViewWindow WinXY, WinYZ, WinZX, WinPers ;
int VisibleVector ; /* 法線ベクトル表示モード */
int VisiblePolyVector ; /* 面法線表示モード */
int VisibleVertex ; /* 頂点表示モード */
int InvisibleDraw ; /* Invisibleを描画するか */
int DrawFrontOnlyFlag ; /* 表のみを描画するか */
int Cx, Cy, Cz ; /* 中心位置 */
int ZoomPlus, ZoomMinus ; /* ズーム値 */
int WinMove ; /* ウインドウ移動量 */
int GridDisplay ; /* 表示グリッド */
int GridCursor ; /* カーソル移動グリッド */
int PersMat[5][3] ; /* 透視図用行列 */
Matrix PersMatInv; /* カーソル逆算用行列 */
int ConvFlag ; /* 変換許可 */
int ConvMat[5][3] ; /* 変換用行列 */
int ConvInv[5][3] ; /* 変換用逆行列 */
int Mx, My, Mz, Mstat ; /* 3D マウスカーソル */
int PersMx, PersMy, PersMstat ; /* 2D マウスカーソル */
#if 0
int xyoffx, xyoffy ; /* オフセット */
int yzoffy, yzoffz ;
int zxoffx, zxoffz ;
#endif
int PersOffsetX, PersOffsetY, PersScaleX, PersAngleCount;
static struct {
short x, y, z ;
short flag ;
int scr[2] ;
}
VertexCache[CACHE_SIZE][CACHE_SET] ;
static int DiscardSet;
static int CacheHit, CacheMiss ;
static int CacheHitSet[CACHE_SET];
static int DispH, DispV ; /* ディスプレイサイズ */
static void SetClip( int, int );
static void SetOffset( void );
static void CacheInit( void );
/* 初期設定 */
void ViewInit( h, v )
int h, v ;
{
Matrix mat ;
ViewMode = VIEW_ALL ;
PersAngleCount = 90;
SetClip( h, v );
VisibleVector = 0 ;
VisiblePolyVector = 0;
InvisibleDraw = TRUE;
DrawFrontOnlyFlag = FALSE;
VisibleVertex = 0;
ViewSetCenter( 0, 0, 0 );
ViewSetZoom( 0, 0 );
MatUnit( mat );
MatToInt( PersMat, mat );
MatUnit( PersMatInv );
ConvFlag = FALSE ;
MatToInt( ConvMat, mat );
GridCursor = 1 ;
GridDisplay = 1 ;
Mx = My = Mz = 0 ;
PersMx = PersMy = 0 ;
Mstat = OFF ;
PersMstat = PERS_CURSOR_OFF ;
CacheInit();
#if 0
ConvFlag = TRUE ;
MatRot( mat, AxisX, 45.0 );
MatToInt( ConvMat, mat );
MatInv( mat );
MatToInt( ConvInv, mat );
#endif
}
/* サイズ設定 */
static void SetClip( h, v )
int h, v ; /* 表示ウインドウサイズ */
{
DispH = h ;
DispV = v ;
v -= MENU_WIDTH + STATUS_WIDTH ;
switch( ViewMode )
{
case VIEW_ALL:
WinXY.h = WinZX.h = h / 2 ;
WinXY.v = WinZX.v = v / 2 ;
WinYZ.h = WinPers.h = (h+1) / 2 ;
WinYZ.v = WinPers.v = (v+1) / 2 ;
WinXY.x = 0 ;
WinXY.y = MENU_WIDTH ;
WinYZ.x = h / 2 ;
WinYZ.y = v / 2 + MENU_WIDTH ;
WinZX.x = 0 ;
WinZX.y = v / 2 + MENU_WIDTH ;
WinPers.x = h / 2 ;
WinPers.y = MENU_WIDTH ;
break ;
case VIEW_XY:
WinXY.x = 0 ;
WinXY.y = MENU_WIDTH ;
WinXY.h = h ;
WinXY.v = v ;
break ;
case VIEW_YZ:
WinYZ.x = 0 ;
WinYZ.y = MENU_WIDTH ;
WinYZ.h = h ;
WinYZ.v = v ;
break ;
case VIEW_ZX:
WinZX.x = 0 ;
WinZX.y = MENU_WIDTH ;
WinZX.h = h ;
WinZX.v = v ;
case VIEW_PERS:
WinPers.x = 0 ;
WinPers.y = MENU_WIDTH ;
WinPers.h = h ;
WinPers.v = v ;
break ;
}
SetOffset();
}
/* 表示設定 */
void ViewSetWindow( mode )
int mode ;
{
ViewMode = mode ;
SetClip( DispH, DispV );
CacheInit();
}
/* ディスプレイサイズ設定 */
void ViewSetDisplay( h, v )
int h, v ;
{
SetClip( h, v );
CacheInit();
}
/* 中心値の設定 */
void ViewSetCenter( cx, cy, cz )
int cx, cy, cz ;
{
Cx = cx ;
Cy = cy ;
Cz = cz ;
}
/* ズーム値の設定 */
void ViewSetZoom( zoom, move )
int zoom ;
int move ;
{
if ( zoom > 0 )
{
ZoomPlus = zoom ;
ZoomMinus = 1 ;
}
else if ( zoom < 0 )
{
ZoomPlus = 1 ;
ZoomMinus = - zoom ;
}
else
{
ZoomPlus = 1 ;
ZoomMinus = 1 ;
}
if ( move == 0 )
WinMove = 10 * ZoomMinus / ZoomPlus ;
else
WinMove = move ;
}
/* 透視図の設定 */
void ViewSetPers( mat )
Matrix mat ;
{
MatToInt( PersMat, mat );
MatCopy(PersMatInv, mat);
MatInv(PersMatInv);
CacheInit();
}
/* グリッドの設定 */
void ViewSetGrid( gdisp, gcur )
int gdisp, gcur ;
{
GridDisplay = gdisp ;
GridCursor = gcur ;
}
/* 3面図の変換設定 */
void ViewSetConv( mat )
Matrix mat ;
{
int i, j ;
Matrix inv ;
ConvFlag = FALSE ;
for( i = 0 ; i < 3 ; i++ )
{
for( j = 0 ; j < 3 ; j++ )
{
if ( i == j )
{
if( mat[i][j] != (float)1.0 )
ConvFlag = TRUE ;
}
else
{
if( mat[i][j] != (float)0.0 )
ConvFlag = TRUE ;
}
}
}
if ( mat[3][0] != (float)0.0 || mat[3][1] != (float)0.0 || mat[3][1] != (float)0.0 )
ConvFlag = TRUE ;
MatCopy( inv, mat );
MatInv( inv );
MatToInt( ConvMat, mat );
MatToInt( ConvInv, inv );
}
int PersAngle(int angle)
{
int a = PersAngleCount;
PersOffsetX = WinPers.x + WinPers.h / 2 ;
PersOffsetY = WinPers.y + WinPers.v / 2 ;
if (angle > 0 && angle < 180 && angle != PersAngleCount) {
CacheInit();
PersAngleCount = angle;
}
PersScaleX = (int)((double)(WinPers.h / 2) / tan(3.14159265358979/180.0*(double)(PersAngleCount/2)));
return a;
}
static void SetOffset()
{
WinXY.offx = WinXY.x + WinXY.h / 2 ;
WinXY.offy = WinXY.y + WinXY.v / 2 ;
WinYZ.offx = WinYZ.x + WinYZ.h / 2 ;
WinYZ.offy = WinYZ.y + WinYZ.v / 2 ;
WinZX.offx = WinZX.x + WinZX.h / 2 ;
WinZX.offy = WinZX.y + WinZX.v / 2 ;
WinPers.offx = 0 ;
WinPers.offy = 0 ;
PersAngle(0);
}
/* スクリーン座標に変換 */
void ToScreen( pos, ver )
int pos[3] ;
Vertex *ver ;
{
int i ;
if ( ConvFlag )
{
for( i = 0 ; i < 3 ; i++ )
{
pos[i] = (((int)ver->x * ConvMat[0][i]
+ (int)ver->y * ConvMat[1][i]
+ (int)ver->z * ConvMat[2][i] ) >> 16)
+ ConvMat[3][i];
}
pos[0] = ( pos[0] - Cx ) * ZoomPlus / ZoomMinus ;
pos[1] = ( pos[1] - Cy ) * ZoomPlus / ZoomMinus ;
pos[2] = ( pos[2] - Cz ) * ZoomPlus / ZoomMinus ;
}
else
{
pos[0] = ( ver->x - Cx ) * ZoomPlus / ZoomMinus ;
pos[1] = ( ver->y - Cy ) * ZoomPlus / ZoomMinus ;
pos[2] = ( ver->z - Cz ) * ZoomPlus / ZoomMinus ;
}
}
/* 裏表判定 */
int ScreenFront(short *vec)
{
int x;
x = (int)vec[0] * PersMat[0][0]
+ (int)vec[1] * PersMat[1][0]
+ (int)vec[2] * PersMat[2][0];
return x < 0;
}
/* 透視変換 */
int ToScreenPers( scr, local )
int *scr ;
Vertex *local ;
{
int i, j ;
int w[3] ;
int tag ;
#if 0
tag = ( ( local->x * 2 + local->x +
local->y * 8 - local->y +
+ local->z ) >> 1 ) & ( CACHE_SIZE - 1 );
#endif
tag = ( ( (int)local->x * 8 + (int)local->x * 4 + (int)local->x +
(int)local->y * 8 + (int)local->y * 4 - (int)local->y +
(int)local->z * 16 + (int)local->z ) >> 1 ) & ( CACHE_SIZE - 1 );
for (j = 0; j < CACHE_SET; ++j) {
if ( VertexCache[tag][j].flag >= 0 &&
*(int*)&VertexCache[tag][j] == *(int*)local &&
VertexCache[tag][j].z == local->z )
{
scr[0] = VertexCache[tag][j].scr[0] ;
scr[1] = VertexCache[tag][j].scr[1] ;
CacheHit ++ ;
CacheHitSet[j]++;
return VertexCache[tag][j].flag ;
}
}
CacheMiss ++ ;
for (j = 0; j < CACHE_SET; j++) {
if ( VertexCache[tag][j].flag < 0) {
break;
}
}
if (j == CACHE_SET) {
j = DiscardSet;
if (++DiscardSet == CACHE_SET) {
DiscardSet = 0;
}
}
*(int*)&VertexCache[tag][j] = *(int*)local ;
VertexCache[tag][j].z = local->z ;
#if 0
//
for( i = 0 ; i < 3 ; i++ )
{
w[i] = (int)local->x * PersMat[0][i]
+ (int)local->y * PersMat[1][i]
+ (int)local->z * PersMat[2][i]
+ PersMat[3][i];
}
//
w[0] = ((int)local->x * PersMat[0][0] + (int)local->y * PersMat[1][0]
+ (int)local->z * PersMat[2][0] + PersMat[3][0]) >> 16;
w[1] = ((int)local->x * PersMat[0][1] + (int)local->y * PersMat[1][1]
+ (int)local->z * PersMat[2][1] + PersMat[3][1]) >> 16;
w[2] = ((int)local->x * PersMat[0][2] + (int)local->y * PersMat[1][2]
+ (int)local->z * PersMat[2][2] + PersMat[3][2]) >> 16;
//
w[0] = (((int)local->x * PersMat[0][0]
+ (int)local->y * PersMat[1][0]
+ (int)local->z * PersMat[2][0]) >> 16) + PersMat[3][0];
w[1] = (((int)local->x * PersMat[0][1]
+ (int)local->y * PersMat[1][1]
+ (int)local->z * PersMat[2][1]) >> 16) + PersMat[3][1];
w[2] = (((int)local->x * PersMat[0][2]
+ (int)local->y * PersMat[1][2]
+ (int)local->z * PersMat[2][2]) >> 16) + PersMat[3][2];
#else
for( i = 0 ; i < 3 ; i++ )
{
int x, a, b;
a = b = 0;
x = (int)local->x * PersMat[0][i]; a += x >> 16; b += x & 65535;
x = (int)local->y * PersMat[1][i]; a += x >> 16; b += x & 65535;
x = (int)local->z * PersMat[2][i]; a += x >> 16; b += x & 65535;
a += PersMat[3][i] + (b >> 16);
w[i] = a;
}
#endif
if ( w[0] > 0 )
{
#if 0
scr[0] = - w[1] / ( w[0] / ( WinPers.h / 2 ) ) + WinPers.x + WinPers.h / 2 ;
scr[1] = - w[2] / ( w[0] / ( WinPers.h / 2 ) ) + WinPers.y + WinPers.v / 2 ;
#endif
scr[0] = - PersScaleX * w[1] / w[0] + PersOffsetX;
scr[1] = - PersScaleX * w[2] / w[0] + PersOffsetY;
VertexCache[tag][j].scr[0] = scr[0] ;
VertexCache[tag][j].scr[1] = scr[1] ;
VertexCache[tag][j].flag = TRUE ;
return TRUE ;
}
else
{
VertexCache[tag][j].flag = FALSE ;
return FALSE ;
}
}
static void CacheInit()
{
int i, j ;
#if 0
printf("Hit=%5d, Miss=%5d, Ratio = %5.2lf%% : ", CacheHit, CacheMiss, (double)CacheHit / (double)(CacheHit + CacheMiss + 1));
for (j = 0; j < CACHE_SET; j++ )
printf("Hit[%d]=%5d, ", j, CacheHitSet[j]);
printf("\n");
#endif
CacheHit = 0 ;
CacheMiss = 0 ;
DiscardSet = 0;
for( i = 0 ; i < CACHE_SIZE ; i++ )
for (j = 0; j < CACHE_SET; j++ )
VertexCache[i][j].flag = -1 ;
for (j = 0; j < CACHE_SET; j++ )
CacheHitSet[j] = 0;
}
/* 行列の整数化 */
void MatToInt( m, mm )
int m[5][3] ;
Matrix mm ;
{
int i, j ;
#if 1
for( i = 0 ; i < 3 ; i++ )
{
for( j = 0 ; j < 3 ; j++ )
m[i][j] = (int)( mm[i][j] * 65536.0 );
}
for( j = 0 ; j < 3 ; j++ ) {
m[3][j] = (int)( mm[3][j] );
m[4][j] = (int)( (mm[3][j]-(double)m[3][j]) * 65536.0 );
}
#else
#if 0
for( i = 0 ; i < 3 ; i++ )
{
for( j = 0 ; j < 3 ; j++ )
m[i][j] = (int)( mm[i][j] * 65536.0 );
}
for( j = 0 ; j < 3 ; j++ )
m[3][j] = (int)( mm[3][j] );
#else
for( i = 0 ; i < 4 ; i++ )
{
for( j = 0 ; j < 3 ; j++ )
m[i][j] = (int)( mm[i][j] * 65536.0 );
}
#endif
#endif
}