home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DOS/V Power Report 1997 March
/
VPR9703A.ISO
/
VPR_DATA
/
DOGA
/
SOURCES
/
POLYEDIT.LZH
/
MODEL
/
SHADE.C
< prev
next >
Wrap
C/C++ Source or Header
|
1996-06-28
|
8KB
|
360 lines
/*
* ポリゴンデータ管理ライブラリ
*
* Copyright T.Kobayashi 1994.8.7
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <assert.h>
#include "lib.h"
#include "alloc.h"
#include "buffer.h"
#include "poly.h"
typedef struct {
short flag, useflag ;
short x, y, z ;
short vx, vy, vz ;
}
HashStruct ;
HashStruct *HashTable = NULL;
int HashSize, HashBit ;
static void MakeHash( int );
static void HashAppend( Vertex*, int, int, int );
static int HashFunc( Vertex* );
static int HashEqual( Vertex*, HashStruct* );
static HashStruct *HashRead( Vertex* );
/*
static void Coefficent( int[3], Vertex*, int );
*/
/* セレクトされているポリゴンに法線ベクトルをつける */
void PolyShade( sw )
int sw ;
{
int i, coe[3] ;
float vx, vy, vz, r ;
float pvx, pvy, pvz ;
Polygon *poly ;
Vertex *ver ;
HashStruct *table ;
if ( Selects == 0 )
return ;
if (sw == SHADE_CREATE)
{
poly = PolyTop();
while( poly != NULL )
{
if ( poly->select == ON )
{
ver = poly->ver ;
poly->type |= POLY_SHADE ;
ObjData[poly->obj].edit = TRUE ;
Coefficent( coe, ver, poly->vers );
for( i = poly->vers ; i > 0 ; i-- )
{
ver->vx = coe[0];
ver->vy = coe[1];
ver->vz = coe[2];
ver ++ ;
}
}
poly = PolyNext( poly );
}
}
else if ( sw )
{
int vertexs = 0;
poly = PolyTop();
while( poly != NULL )
{
if ( poly->select == ON )
{
vertexs += poly->vers;
}
poly = PolyNext( poly );
}
MakeHash(vertexs);
poly = PolyTop();
while( poly != NULL )
{
if ( poly->select == ON )
{
ver = poly->ver ;
Coefficent( coe, ver, poly->vers );
for( i = poly->vers ; i > 0 ; i-- )
{
HashAppend( ver, coe[0], coe[1], coe[2] );
ver ++ ;
}
}
poly = PolyNext( poly );
}
poly = PolyTop();
while( poly != NULL )
{
if ( poly->select == ON )
{
ver = poly->ver ;
poly->type |= POLY_SHADE ;
ObjData[poly->obj].edit = TRUE ;
#if 1
Coefficent( coe, ver, poly->vers );
for( i = poly->vers ; i > 0 ; i-- )
{
table = HashRead( ver );
vx = (float)table->vx ;
vy = (float)table->vy ;
vz = (float)table->vz ;
if (vx * coe[0] + vy * coe[1] + vz * coe[2] < (float)0.0 )
{
vx = - vx ;
vy = - vy ;
vz = - vz ;
}
r = sqrt(vx * vx + vy * vy + vz * vz);
if (r > 0.0) r = 256.0 / r;
/* r = 256.0 / sqrt( vx * vx + vy * vy + vz * vz );*/
ver->vx = (int)( vx * r );
ver->vy = (int)( vy * r );
ver->vz = (int)( vz * r );
ver ++ ;
}
#else
for( i = 0 ; i < poly->vers ; i++ )
{
table = HashRead( ver );
vx = (float)table->vx ;
vy = (float)table->vy ;
vz = (float)table->vz ;
if ( i > 0 && pvx * vx + pvy * vy + pvz * vz < (float)0.0 )
{
if (table->useflag == FALSE) {
table->vx = -table->vx;
table->vy = -table->vy;
table->vz = -table->vz;
vx = - vx ;
vy = - vy ;
vz = - vz ;
} else {
int j;
for (j = 0; j < i; j++) {
poly->ver[j].vx = -poly->ver[j].vx;
poly->ver[j].vy = -poly->ver[j].vy;
poly->ver[j].vz = -poly->ver[j].vz;
}
}
}
table->useflag = TRUE;
r = sqrt(vx * vx + vy * vy + vz * vz);
if (r > 0.0) r = 256.0 / r;
/* r = 256.0 / sqrt( vx * vx + vy * vy + vz * vz );*/
ver->vx = (int)( vx * r );
ver->vy = (int)( vy * r );
ver->vz = (int)( vz * r );
pvx = vx ;
pvy = vy ;
pvz = vz ;
ver ++ ;
}
#endif
/* HashAppend( ver, coe[0], coe[1], coe[2] );*/
}
poly = PolyNext( poly );
}
MemoryFree(HashTable);
HashTable = NULL;
}
else
{
poly = PolyTop();
while( poly != NULL )
{
if ( poly->select == ON )
{
poly->type &= ( ~ POLY_SHADE );
ObjData[poly->obj].edit = TRUE ;
}
poly = PolyNext( poly );
}
}
}
/* ハッシュテーブルをつくる */
static void MakeHash(int vertexs)
{
int i;
HashSize = 1 ;
while( vertexs != 0 )
{
HashSize <<= 1 ;
vertexs >>= 1 ;
}
if (HashTable != NULL) {
MemoryFree(HashTable);
}
HashTable = MemoryAlloc( HashSize * sizeof( HashStruct ) );
for( i = 0 ; i < HashSize ; i++ ) {
HashTable[i].flag = FALSE ;
HashTable[i].useflag = FALSE ;
}
HashBit = HashSize - 1 ;
}
/* ハッシュテーブルに登録 */
static void HashAppend( ver, vx, vy, vz )
Vertex *ver ;
int vx, vy, vz ;
{
int i, n ;
i = 0 ;
n = HashFunc( ver ) & HashBit ;
while( HashEqual( ver, &HashTable[n] ) == FALSE )
{
n = ( n + 997 ) & HashBit ;
i++ ;
assert( i < HashSize );
}
if ( HashTable[n].flag )
{
if ( HashTable[n].vx * vx + HashTable[n].vy * vy + HashTable[n].vz * vz >= 0 )
{
HashTable[n].vx += (short)vx ;
HashTable[n].vy += (short)vy ;
HashTable[n].vz += (short)vz ;
}
else
{
HashTable[n].vx += - (short)vx ;
HashTable[n].vy += - (short)vy ;
HashTable[n].vz += - (short)vz ;
}
}
else
{
HashTable[n].flag = TRUE ;
HashTable[n].x = ver->x ;
HashTable[n].y = ver->y ;
HashTable[n].z = ver->z ;
HashTable[n].vx = (short)vx ;
HashTable[n].vy = (short)vy ;
HashTable[n].vz = (short)vz ;
}
}
/* ハッシュ関数 */
static int HashFunc( ver )
Vertex *ver ;
{
return ( ver->x % 181 ) + ( ver->y % 479 ) * 97 + ( ver->z % 571 ) * 997 ;
}
/* ハッシュテーブルのヒットのチェック */
static int HashEqual( ver, table )
Vertex *ver ;
HashStruct *table ;
{
if ( table->flag == FALSE )
return TRUE ;
else if ( ver->x == table->x && ver->y == table->y && ver->z == table->z )
return TRUE ;
else
return FALSE ;
}
/* ハッシュテーブルから読み出す */
static HashStruct *HashRead( ver )
Vertex *ver ;
{
int n ;
n = HashFunc( ver ) & HashBit ;
while( HashEqual( ver, &HashTable[n] ) == FALSE )
{
assert( HashTable[n].flag == TRUE );
n = ( n + 997 ) & HashBit ;
}
return &HashTable[n] ;
}
void Coefficent( coe, vers, n )
int coe[3] ;
Vertex *vers ;
int n ;
{
int i ;
float a, b, c, r ;
const Vertex *p1, *p2 ;
/* 係数の計算(規格化する) */
p1 = vers ;
p2 = vers + 1 ;
a = b = c = 0.0 ;
for( i = 0 ; i < n-1 ; ++i )
{
a += (float)( ( p1->y - p2->y ) * ( p1->z + p2->z ) );
b += (float)( ( p1->z - p2->z ) * ( p1->x + p2->x ) );
c += (float)( ( p1->x - p2->x ) * ( p1->y + p2->y ) );
p1 ++ ;
p2 ++ ;
}
p2 = vers ;
a += (float)( ( p1->y - p2->y ) * ( p1->z + p2->z ) );
b += (float)( ( p1->z - p2->z ) * ( p1->x + p2->x ) );
c += (float)( ( p1->x - p2->x ) * ( p1->y + p2->y ) );
r = (float)sqrt(a*a+b*b+c*c);
if (r > 0.0) r = (float)256.0/r;
/*
r = (float)256.0 / sqrt( a * a + b * b + c * c );
*/
coe[0] = (int)( a * r );
coe[1] = (int)( b * r );
coe[2] = (int)( c * r );
}
/* セレクトされているポリゴンの法線ベクトルを反転する */
void PolyShadeInv()
{
int i ;
Polygon *poly ;
Vertex *ver ;
poly = PolyTop();
while( poly != NULL )
{
if ( poly->select && ( poly->type & POLY_SHADE ) )
{
ver = poly->ver ;
for( i = 0 ; i < poly->vers ; i++ )
{
ver->vx = - ver->vx ;
ver->vy = - ver->vy ;
ver->vz = - ver->vz ;
ver++ ;
}
ObjData[poly->obj].edit = TRUE ;
}
poly = PolyNext( poly );
}
}