Created
January 18, 2024 15:48
-
-
Save gnilk/91d68816127237efadf439e32f57943a to your computer and use it in GitHub Desktop.
ETS - VoxelPoly
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// PVoxelPoly.cpp: implementation of the PVoxelPoly class. | |
// | |
// gnilk, 2024-01-18, | |
// this is dump of the VoxelPolygon part in Enlight the Surreal by Noice from 2000 | |
// note: this won't compile, it is more for completness of the algorithm used | |
// | |
// | |
////////////////////////////////////////////////////////////////////// | |
#include "PVoxelPoly.h" | |
#include "../kfx/kfx.h" | |
////////////////////////////////////////////////////////////////////// | |
// Construction/Destruction | |
////////////////////////////////////////////////////////////////////// | |
#include "goa/goa.h" | |
#include <math.h> | |
static GOA_RGBA col_BLACK = {0,0,0,0}; | |
#if !defined(M_PI) | |
#define M_PI 3.1415926535897932384 | |
#endif | |
typedef struct | |
{ | |
float val[8]; | |
} SCAN; | |
static SCAN *screen_start,*screen_end; | |
static int slice_len=32; | |
static int fade_off=0; | |
static int e_fade = 0; | |
static float e_fade_t = 0; | |
static float fade_ypos=-240; | |
static float fade_y_t=0; | |
static float slice_scale = 32.0f; | |
static float xv=0,yv=0,zv=0,secs = 0; | |
static float pack1[10],pack2[10],pack3[10],pack4[10]; | |
static GOA_VECTOR cube_dst[8]; | |
static GOA_VECTOR cube_src[]= | |
{ | |
-32,-32,32, 32,-32,32, 32,32,32, -32,32,32, | |
-32,-32,-32, 32,-32,-32, 32,32,-32, -32,32,-32 | |
}; | |
typedef struct | |
{ | |
int yofs; | |
int xofs; | |
GOA_RGBA col; | |
int zval; | |
} SPIXEL; | |
static SPIXEL *parray; | |
static int num_parray; | |
static int ceil2 (int a) | |
{ | |
a+=0xffff; | |
return (a >> 16); | |
} | |
static void calc_subpixel (float *dst, float s, float *src, int num) | |
{ | |
int i; | |
for (i=0;i<num;i++) | |
dst[i] += (ceil2(s * (1 << 16)) - s) * src[i]; | |
} | |
static void m_outline(SCAN *uptab, SCAN *downtab, float *pa1, float *pa2, int n,int min_h,int max_h) | |
{ | |
int i,j; | |
float *a1=pa1; | |
float *a2=pa2; | |
float add_val[8],start[8]; | |
SCAN *tab=downtab; | |
float deltay; | |
if (a1[1]==a2[1]) return; | |
if (a1[1]>a2[1]) | |
{ | |
float *tmp; | |
tmp = a1; | |
a1 = a2; | |
a2 = tmp; | |
tab=uptab; | |
} | |
deltay=a2[1] - a1[1]; | |
if ((int)deltay == 0) return; | |
for (i=j=0;i<n;i++) | |
{ | |
if (i!=1) | |
{ | |
add_val[j] = (a2[i] - a1[i]) / deltay; | |
start[j]=a1[i]; | |
j++; | |
} | |
} | |
calc_subpixel (start,a1[1],add_val,n-1); | |
for (i=a1[1]; i<=a2[1]; i++) | |
{ | |
for (j=0;j<n-1;j++) | |
{ | |
if ((i>min_h) && (i<max_h)) | |
tab[i].val[j]=start[j]; | |
start[j] += add_val[j]; | |
} | |
} | |
} | |
static void tscanline (GOA_PIXMAP *dest, GOA_PIXMAP *texture, GOA_PIXMAP *hmap, int y, float *pa1, float *pa2,int n) | |
{ | |
float deltax,add_val[8],start[8]; | |
float *a1=pa1,*a2=pa2; | |
int i,j,tx,ty,tofs,yofs; | |
yofs = y*dest->width; | |
if (pa1[0] == pa2[0]) return; | |
if (pa1[0] > pa2[0]) | |
{ | |
a1 = pa2; | |
a2 = pa1; | |
} | |
deltax=a2[0] - a1[0]; | |
if ((int)deltax == 0) return; | |
if (deltax > 16) | |
{ | |
for (i=j=0;i<n;i++) | |
{ | |
if (i!=0) | |
{ | |
add_val[j] = (a2[i] - a1[i]) / deltax; | |
start[j]=a1[i]; | |
j++; | |
} | |
} | |
calc_subpixel (start,a1[1],add_val,n-1); | |
for (i=a1[0];i<=a2[0];i++) | |
{ | |
if ((i>0)) | |
{ | |
tx = start[1]; | |
ty = start[2]; | |
ty *= 256; | |
tofs = (tx&0xff)+(ty&0xff00); | |
parray[num_parray].yofs = yofs; | |
parray[num_parray].xofs = i; | |
parray[num_parray].col = texture->image[tofs]; | |
parray[num_parray].col.a = hmap->image[tofs].r; | |
parray[num_parray].zval = (int)start[0]; | |
num_parray++; | |
} | |
for (j=0;j<n-1;j++) | |
start[j]+=add_val[j]; | |
} | |
} else | |
{ | |
float xp,xa; | |
deltax = 16; | |
for (i=j=0;i<n;i++) | |
{ | |
if (i!=0) | |
{ | |
add_val[j] = (a2[i] - a1[i]) / deltax; | |
start[j]=a1[i]; | |
j++; | |
} | |
} | |
calc_subpixel (start,a1[1],add_val,n-1); | |
xp = a1[0]; | |
xa = (a2[0] - a1[0])/16.0; | |
for (i=0;i<=16;i++) | |
{ | |
if ((i>0)) | |
{ | |
tx = start[1]; | |
ty = start[2]; | |
ty *= 256; | |
tofs = (tx&0xff)+(ty&0xff00); | |
parray[num_parray].yofs = yofs; | |
parray[num_parray].xofs = xp; | |
parray[num_parray].col = texture->image[tofs]; | |
parray[num_parray].col.a = hmap->image[tofs].r; | |
parray[num_parray].zval = (int)start[0]; | |
num_parray++; | |
} | |
xp += xa; | |
for (j=0;j<n-1;j++) | |
start[j]+=add_val[j]; | |
} | |
} | |
} | |
#ifndef min | |
#define min(a,b) ((a)<(b)?(a):(b)) | |
#endif | |
#ifndef max | |
#define max(a,b) ((a)>(b)?(a):(b)) | |
#endif | |
static void drawquad_hmap (GOA_PIXMAP *dest, GOA_PIXMAP *texture, GOA_PIXMAP *hmap, float *a1, float *a2, float *a3, float *a4,int hval) | |
{ | |
float p1[8],p2[8],p3[8],p4[8]; | |
int y_start,y_end,i; | |
y_start = min (a1[1],a2[1]); | |
y_start = min (y_start,a3[1]); | |
y_start = min (y_start,a4[1]); | |
y_end = max (a1[1],a2[1]); | |
y_end = max (y_end,a3[1]); | |
y_end = max (y_end,a4[1]); | |
if (y_end < 0) return; | |
if (y_start > dest->height) return; | |
m_outline (screen_start,screen_end,a1,a2,5,0,dest->height); | |
m_outline (screen_start,screen_end,a2,a3,5,0,dest->height); | |
m_outline (screen_start,screen_end,a3,a4,5,0,dest->height); | |
m_outline (screen_start,screen_end,a4,a1,5,0,dest->height); | |
if (y_start<0) | |
y_start = 0; | |
if (y_end > dest->height) y_end = dest->height; | |
num_parray = 0; | |
for (i=y_start;i<y_end;i++) | |
tscanline (dest,texture,hmap,i,screen_start[i].val,screen_end[i].val,4); | |
} | |
static int draw_parray (GOA_PIXMAP *dest, GOA_PIXMAP *texture, GOA_PIXMAP *hmap,int h,int ox,int oy,int oya,int oxa, int za) | |
{ | |
int i,sofs,sofs2,xo,yo,twh,num; | |
int *zbuffer = dest->zbuffer; | |
GOA_RGBA *dst = dest->image; | |
num = 0; | |
twh=dest->height * dest->width; | |
for (i=0;i<num_parray;i++) | |
{ | |
xo = parray[i].xofs + ox; | |
yo = oy+parray[i].yofs; | |
sofs = xo+yo; | |
if (zbuffer[sofs] > (parray[i].zval + za)) | |
{ | |
if (parray[i].col.a > h) | |
{ | |
zbuffer[sofs] = parray[i].zval+za; | |
sofs2 =oya+parray[i].yofs + oxa+parray[i].xofs; | |
dst[sofs] = parray[i].col; | |
dst[sofs2] = parray[i].col; | |
parray[num] = parray[i]; | |
num++; | |
} | |
} else | |
{ | |
parray[num] = parray[i]; | |
num++; | |
} | |
} | |
return num_parray; | |
} | |
void voxpoly_drawquad (GOA_PIXMAP *dest, GOA_PIXMAP *texture, GOA_PIXMAP *hmap, float *a1, float *a2, float *a3, float *a4,GOA_VECTOR *normal) | |
{ | |
GOA_VECTOR vadd[4]; | |
int i; | |
int xa,ya,za; | |
int xp,yp,zp,oxp,oyp; | |
xp = yp = zp = oxp = oyp = 0; | |
xa = (int)((65536.0f * slice_scale * normal->x/(float)slice_len)); | |
ya = (int)((65536.0f * slice_scale * normal->y/(float)slice_len)); | |
za = (int)((65536.0f * slice_scale * normal->z/(float)slice_len)); | |
num_parray = 0; | |
drawquad_hmap (dest,texture,hmap,a1,a2,a3,a4,0); | |
if (num_parray > 0) | |
{ | |
for (i=0;i<slice_len;i++) | |
{ | |
if ((num_parray = draw_parray (dest,texture,hmap,i*(256/slice_len),xp>>16,(yp>>16)*dest->width,oxp>>16,(oyp>>16)*dest->width,zp>>16))==0) return; | |
oxp = xp + 0.5*xa; | |
oyp = yp + 0.5*ya; | |
xp += xa; | |
yp += ya; | |
zp += za; | |
} | |
} | |
} | |
static void voxpoly_setscale (float scale) | |
{ | |
slice_scale = scale; | |
} | |
static void voxpoly_setslice (int slice) | |
{ | |
slice_len = slice; | |
} | |
static int voxpoly_init (int width,int height) | |
{ | |
if ((parray = (SPIXEL *)gmalloc (sizeof (SPIXEL) * (width * height)))==NULL) return 0; | |
if ((screen_start = (SCAN *)gmalloc (sizeof (SCAN) * height))==NULL) return 0; | |
if ((screen_end = (SCAN *)gmalloc (sizeof (SCAN) * height))==NULL) return 0; | |
return 1; | |
} | |
static void draw_face (GOA_PIXMAP *dest,GOA_PIXMAP *texture, GOA_PIXMAP *hmap, int a, int b, int c, int d) | |
{ | |
GOA_VECTOR normal,v1,v2; | |
gmemcpy4 (pack1,&cube_dst[a],3); | |
gmemcpy4 (pack2,&cube_dst[b],3); | |
gmemcpy4 (pack3,&cube_dst[c],3); | |
gmemcpy4 (pack4,&cube_dst[d],3); | |
pack1[3] = pack1[4] = 0; | |
pack2[3] = 255; | |
pack2[4] = 0; | |
pack3[3] = 255; | |
pack3[4] = 255; | |
pack4[3] = 0; | |
pack4[4] = 255; | |
goa_vector_cross (&normal,goa_vector_sub (&v2,&cube_dst[c],&cube_dst[a]),goa_vector_sub (&v1,&cube_dst[b],&cube_dst[a])); | |
goa_vector_normalize (&normal,&normal); | |
if (normal.z > 0) voxpoly_drawquad (dest,texture,hmap, pack1,pack2,pack3,pack4,&normal); | |
else voxpoly_drawquad (dest,texture,hmap, pack1,pack2,pack3,pack4,&normal); | |
} | |
PVoxelPoly::PVoxelPoly() | |
{ | |
} | |
PVoxelPoly::~PVoxelPoly() | |
{ | |
} | |
int PVoxelPoly::CreateFX (char *fn,char *path) | |
{ | |
frustum = NULL; | |
tmap = jpeg_load2pixmap ("data/vpoly/tmap2.jpg"); | |
int i; | |
for (i=0;i<tmap->width*tmap->height;i++) | |
{ | |
int tmp; | |
tmp = tmap->image[i].g; | |
tmap->image[i].g = tmap->image[i].b; | |
tmap->image[i].b = tmp; | |
} | |
hmap = jpeg_load2pixmap ("data/vpoly/hmap.jpg"); | |
star = jpeg_load2pixmap ("data/spider/star1.jpg"); | |
bgpic2 = (GOA_PIXMAP *)fn; | |
renpic = goa_pixmap_create (240,240,GOA_PIXMAPCREATE_CLEAR | GOA_PIXMAPCREATE_ZBUFFER); | |
bgpic = jpeg_load2pixmap ("data/vpoly/bgpic.jpg"); | |
voxpoly_init (renpic->width,renpic->height); | |
return 1; | |
} | |
static void mpixmap_copy (GOA_PIXMAP *dst,int x, int y, GOA_PIXMAP *src) | |
{ | |
int xl,yl,ysadd,ydadd,ys; | |
GOA_RGBA *sptr,*dptr; | |
ysadd = src->width*4; | |
ydadd = dst->width*4; | |
xl = src->width; | |
yl = src->height; | |
ys = 0; | |
if (y<0) | |
{ | |
yl+=y; | |
ys=-y; | |
y=0; | |
}else | |
{ | |
if ((y+src->height) > dst->height) | |
yl -= (y+src->height) - dst->height; | |
} | |
if (yl<1) return; | |
sptr = &src->image[ys*src->width]; | |
dptr = &dst->image[x+y*dst->width]; | |
__asm | |
{ | |
mov esi,sptr | |
mov edi,dptr | |
mov edx,yl | |
ylp: | |
push esi | |
push edi | |
mov ecx,xl | |
xlp: | |
cmp [esi],0 | |
je ncopy | |
mov eax,[esi] | |
mov [edi],eax | |
ncopy: | |
add edi,4 | |
add esi,4 | |
dec ecx | |
jne xlp | |
pop edi | |
pop esi | |
add edi,ydadd | |
add esi,ysadd | |
dec edx | |
jne ylp | |
} | |
} | |
static float fade_away_intens = 0; | |
GOA_PIXMAP *PVoxelPoly::Render (GOA_PIXMAP *dst, int flags) | |
{ | |
GOA_MATRIX rm; | |
GOA_VECTOR vadd={160,120,0}; | |
float c_scale = 1.0; | |
int i; | |
if (frustum==NULL) | |
{ | |
frustum = goa_frustum_create (renpic,renpic->width,renpic->height,400,GOA_FRUSTUMCREATE_NONE); | |
} | |
goa_pixmap_copy (dst,0,0,bgpic,0,0,dst->width,dst->height,GOA_PIXMAPCOPY_IMAGE); | |
goa_pixmap_clear (renpic,0,0,renpic->width,renpic->height,col_BLACK,GOA_PIXMAP_ZMAX, GOA_PIXMAPCLEAR_ZBUFFER|GOA_PIXMAPCLEAR_IMAGE); | |
goa_matrix_fromangles(&rm,xv,yv,zv); | |
goa_matrix_multivectormul (cube_dst,cube_src,8,&rm); | |
c_scale = 1.3+0.3*sin (dsys->time_total); | |
for (i=0;i<8;i++) | |
{ | |
goa_vector_mul (&cube_dst[i],c_scale,&cube_dst[i]); | |
goa_frustum_project (frustum,&cube_dst[i],&cube_dst[i]); | |
} | |
voxpoly_setscale (24+16*sin(0.8*dsys->time_total)); | |
voxpoly_setslice ((24+16*sin(0.8*dsys->time_total)) / 2.0f); | |
draw_face (renpic,tmap,hmap,0,1,2,3); | |
draw_face (renpic,tmap,hmap,7,6,5,4); | |
draw_face (renpic,tmap,hmap,1,5,6,2); | |
draw_face (renpic,tmap,hmap,3,7,4,0); | |
draw_face (renpic,tmap,hmap,0,4,5,1); | |
draw_face (renpic,tmap,hmap,2,6,7,3); | |
kfx_pixmap_3x3blur(renpic,0,0,renpic,0,0,renpic->width,renpic->height,1.0); | |
// kfx_pixmap_addsi(dst,320,160,renpic,2,2,1); | |
// kfx_pixmap_add(dst,320,160,renpic); | |
fade_ypos = -200 + 280 * sin (fade_y_t); | |
mpixmap_copy (dst,(320-renpic->width/2)+64*cos (dsys->time_total),fade_ypos,renpic); | |
if (!fade_off) | |
{ | |
fade_y_t += dsys->time_delta; | |
if (fade_y_t>M_PI/2.0) fade_y_t = M_PI/2.0; | |
} else | |
{ | |
pfxpix_crossfade(dst, 0,0,dst, 0,0,bgpic2,0,0,fade_away_intens,640,320); | |
fade_away_intens += dsys->time_delta; | |
if (fade_away_intens > 1) fade_away_intens=1; | |
fade_y_t += dsys->time_delta; | |
if (fade_y_t>M_PI) fade_y_t = M_PI; | |
} | |
if (e_fade) | |
{ | |
float sc; | |
sc = 0.5+0.5*sin (e_fade_t); | |
kfx_pixmap_addsi(dst,284,142,star,sc,sc,sc); | |
kfx_pixmap_addsi(dst,204,174,star,sc,sc,sc); | |
e_fade_t += 1.2 * dsys->time_delta; | |
if (e_fade_t > 2.0 * M_PI) e_fade = 0; | |
} | |
xv += dsys->time_delta; | |
yv += dsys->time_delta*0.76; | |
zv += -dsys->time_delta*1.2; | |
return dst; | |
} | |
void PVoxelPoly::Signal (int sig,int numval, float *values) | |
{ | |
switch (sig) | |
{ | |
case 1 : | |
e_fade = 1; | |
e_fade_t = 0; | |
break; | |
case 2 : | |
fade_off = 1; | |
break; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment