mirror of
https://github.com/KranX/Vangers.git
synced 2025-12-01 07:25:28 +07:00
281 lines
7.5 KiB
C++
281 lines
7.5 KiB
C++
#include "../src/global.h"
|
|
|
|
#include "../src/common.h"
|
|
|
|
#include "../src/3d/3d_math.h"
|
|
|
|
#include "../src/terra/vmap.h"
|
|
#include "impass.h"
|
|
#include "../src/terra/world.h"
|
|
#include "../src/terra/render.h"
|
|
|
|
/* ----------------------------- EXTERN SECTION ---------------------------- */
|
|
/* --------------------------- PROTOTYPE SECTION --------------------------- */
|
|
/* --------------------------- DEFINITION SECTION -------------------------- */
|
|
const int PEAK_SIZE = 9;
|
|
static uchar PeakData[PEAK_SIZE*PEAK_SIZE] = {
|
|
10, 20, 50, 80, 80, 80, 50, 20, 10,
|
|
20, 50, 80,100,100,100, 80, 50, 20,
|
|
20, 50,100,200,200,200,100, 50, 20,
|
|
20, 50,200,200,255,200,200, 50, 20,
|
|
20, 50,200,255,255,255,200, 50, 20,
|
|
20, 50,200,200,255,200,200, 50, 20,
|
|
20, 50,100,200,200,200,100, 50, 20,
|
|
20, 50, 80,100,100,100, 80, 50, 20,
|
|
10, 20, 50, 80, 80, 80, 50, 20, 10
|
|
};
|
|
|
|
ImpassType* ImpPattern[IMP_MAX];
|
|
#ifdef _SURMAP_
|
|
int curImpIndex;
|
|
const char* ImpItem[IMP_MAX] = {
|
|
"SPHERE",
|
|
"POLYGON",
|
|
"PEAK"
|
|
};
|
|
#endif
|
|
|
|
void ImpassPrepare(void)
|
|
{
|
|
#ifdef _SURMAP_
|
|
XStream ff(0);
|
|
if(!ff.open("impass.dat",XS_IN)){
|
|
(ImpPattern[IMP_SPHERE] = new ImpSphere(100,100)) -> init();
|
|
(ImpPattern[IMP_POLYGON] = new ImpPolygon(100,100)) -> init();
|
|
(ImpPattern[IMP_PEAK] = new ImpPeak(PEAK_SIZE,PEAK_SIZE)) -> init();
|
|
}
|
|
else {
|
|
ImpPattern[IMP_SPHERE] = new ImpSphere(100,100);
|
|
ImpPattern[IMP_POLYGON] = new ImpPolygon(100,100);
|
|
ImpPattern[IMP_PEAK] = new ImpPeak(PEAK_SIZE,PEAK_SIZE);
|
|
ff > curImpIndex;
|
|
ImpPattern[IMP_SPHERE] -> read(ff);
|
|
ImpPattern[IMP_POLYGON] -> read(ff);
|
|
ImpPattern[IMP_PEAK] -> read(ff);
|
|
ImpPattern[IMP_SPHERE] -> init();
|
|
ImpPattern[IMP_POLYGON] -> init();
|
|
ImpPattern[IMP_PEAK] -> init();
|
|
ff.close();
|
|
}
|
|
#else
|
|
(ImpPattern[IMP_SPHERE] = new ImpSphere(10,10,0,0,0,100,5)) -> init();
|
|
// (ImpPattern[IMP_POLYGON] = new ImpPolygon(50,50,0,0,0,100,100)) -> init();
|
|
// (ImpPattern[IMP_PEAK] = new ImpPeak(PEAK_SIZE,PEAK_SIZE,0,0,0,100,100)) -> init();
|
|
#endif
|
|
}
|
|
|
|
void ImpassSave(void)
|
|
{
|
|
#ifdef _SURMAP_
|
|
XStream ff("impass.dat",XS_OUT);
|
|
ff < curImpIndex;
|
|
ImpPattern[IMP_SPHERE] -> write(ff);
|
|
ImpPattern[IMP_POLYGON] -> write(ff);
|
|
ImpPattern[IMP_PEAK] -> write(ff);
|
|
ff.close();
|
|
#endif
|
|
}
|
|
|
|
ImpassType::ImpassType(int _sx,int _sy,int _force,int _mode,int _level,int _rad,int _h,int _n,int _phase,int _inverse,int _plain,int _noiseLevel,int _noiseAmp)
|
|
{
|
|
map = NULL;
|
|
sx = _sx; sy = _sy;
|
|
level = _level;
|
|
mode = _mode;
|
|
force = _force;
|
|
radInt = _rad;
|
|
rad = (double)_rad/100.;
|
|
h = _h;
|
|
n = _n;
|
|
phase = _phase;
|
|
inverse = _inverse;
|
|
plain = _plain;
|
|
noiseLevel = _noiseLevel;
|
|
noiseAmp = _noiseAmp;
|
|
}
|
|
|
|
void ImpassType::init(void)
|
|
{
|
|
map = NULL;
|
|
change(sx,sy,force,mode,level,radInt,h,n,phase,inverse,plain,noiseLevel,noiseAmp);
|
|
}
|
|
|
|
void ImpassType::read(XStream& ff)
|
|
{
|
|
ff > sx > sy > level > force > mode > radInt > h > n > phase > inverse > plain > noiseLevel > noiseAmp;
|
|
}
|
|
|
|
void ImpassType::write(XStream& ff)
|
|
{
|
|
ff < sx < sy < level < force < mode < radInt < h < n < phase < inverse < plain < noiseLevel < noiseAmp;
|
|
}
|
|
|
|
void ImpassType::change(int _sx,int _sy,int _force,int _mode,int _level,int _rad,int _h,int _n,int _phase,int _inverse,int _plain,int _noiseLevel,int _noiseAmp)
|
|
{
|
|
if(!_sx) _sx = 16; if(!_sy) _sy = 16;
|
|
sx = _sx; sy = _sy;
|
|
size = sx*sy;
|
|
level = _level;
|
|
mode = _mode;
|
|
force = _force;
|
|
|
|
radInt = _rad;
|
|
rad = (double)_rad/100.;
|
|
h = _h;
|
|
n = _n;
|
|
phase = _phase;
|
|
inverse = _inverse;
|
|
plain = _plain;
|
|
noiseLevel = _noiseLevel;
|
|
noiseAmp = _noiseAmp;
|
|
|
|
if(map) delete map;
|
|
map = new short[size];
|
|
|
|
register int i;
|
|
short* p = map;
|
|
for(i = 0;i < size;i++,p++) *p = level;
|
|
|
|
build();
|
|
ImpassSave();
|
|
}
|
|
|
|
#ifdef _SURMAP_
|
|
void ImpassType::put(int x,int y)
|
|
{
|
|
x -= sx/2;
|
|
y -= sy/2;
|
|
|
|
register int i,j;
|
|
int xx,yy,v,vv = 0;
|
|
short* p = map;
|
|
uchar** lt = vMap -> lineT;
|
|
|
|
vMap -> increase(y,y + sy - 1);
|
|
|
|
for(j = 0;j < sy;j++)
|
|
for(i = 0;i < sx;i++,p++)
|
|
if(force || *p != level){
|
|
xx = XCYCL(x + i);
|
|
yy = YCYCL(y + j);
|
|
if(lt[yy]){
|
|
v = *(lt[yy] + xx);
|
|
switch(mode){
|
|
case 0:
|
|
vv = *p;
|
|
break;
|
|
case 1:
|
|
vv = MAX(v,*p);
|
|
if(vv != *p) continue;
|
|
break;
|
|
case 2:
|
|
vv = MIN(v,*p);
|
|
if(vv != *p) continue;
|
|
break;
|
|
case 3:
|
|
vv = v + *p >> 1;
|
|
break;
|
|
case 4:
|
|
vv = v + *p;
|
|
break;
|
|
}
|
|
if(noiseLevel && noiseAmp)
|
|
if((int)realRND(100) < noiseLevel) vv += noiseAmp - realRND((noiseAmp << 1) + 1);
|
|
pixSet(xx,yy,vv - v);
|
|
}
|
|
}
|
|
regRender(x,y,x + sx,y + sy);
|
|
}
|
|
#endif
|
|
|
|
static double plane(double x,double y, double x0,double y0,double z0,double x1,double y1,double z1,double x2,double y2,double z2)
|
|
{
|
|
double a = (y1 - y0)*(z2 - z0) - (z1 - z0)*(y2 - y0);
|
|
double b = (x1 - x0)*(z2 - z0) - (z1 - z0)*(x2 - x0);
|
|
double c = (x1 - x0)*(y2 - y0) - (y1 - y0)*(x2 - x0);
|
|
|
|
return ((y - y0)*b - (x - x0)*a)/c + z0;
|
|
}
|
|
|
|
static double minim(double* d,int n)
|
|
{
|
|
double m = 1000.0;
|
|
for(int i = 0;i < n;i++)
|
|
if(d[i] >= 0 && d[i] < m) m = d[i];
|
|
return m;
|
|
}
|
|
|
|
ImpSphere::ImpSphere(int _sx,int _sy,int _force,int _mode,int _level,int _rad,int _h,int _n,int _phase,int _inverse,int _plain,int _noiseLevel,int _noiseAmp)
|
|
: ImpassType(_sx,_sy,_force,_mode,_level,_rad,_h,_n,_phase,_inverse,_plain,_noiseLevel,_noiseAmp)
|
|
{ }
|
|
|
|
void ImpSphere::build(void)
|
|
{
|
|
double dx = 2.0/(double)sx;
|
|
double dy = 2.0/(double)sy;
|
|
double xx,yy,zz;
|
|
double r2 = rad*rad;
|
|
|
|
register int x,y;
|
|
short* p = map;
|
|
for(yy = -1.0,y = 0;y < sy;yy += dy,y++)
|
|
for(xx = -1.0,x = 0;x < sx;xx += dx,x++,p++){
|
|
zz = r2 - (xx*xx + yy*yy);
|
|
if(zz > 0.0){
|
|
*p = (short)(sqrt(zz)*h);
|
|
if(inverse) *p = -*p;
|
|
if(plain) *p = level;
|
|
else *p += level;
|
|
}
|
|
}
|
|
}
|
|
|
|
ImpPolygon::ImpPolygon(int _sx,int _sy,int _force,int _mode,int _level,int _rad,int _h,int _n,int _phase,int _inverse,int _plain,int _noiseLevel,int _noiseAmp)
|
|
: ImpassType(_sx,_sy,_force,_mode,_level,_rad,_h,_n,_phase,_inverse,_plain,_noiseLevel,_noiseAmp)
|
|
{ }
|
|
|
|
void ImpPolygon::build(void)
|
|
{
|
|
double dx = 2.0/(double)sx;
|
|
double dy = 2.0/(double)sy;
|
|
double xx,yy,zz;
|
|
double* zzz = new double[n];
|
|
double phs = (double)phase/1000.;
|
|
double angle = 2.*M_PI/(double)n;
|
|
double ang;
|
|
|
|
register int x,y,i;
|
|
short* p = map;
|
|
for(yy = 1.0,y = 0;y < sy;yy -= dy,y++)
|
|
for(xx = -1.0,x = 0;x < sx;xx += dx,x++,p++){
|
|
// zzz[0] = plane(xx,yy, -rad,rad,0.0, rad,rad,0.0, 0.0,0.0,(double)h/256.);
|
|
// zzz[1] = plane(xx,yy, -rad,-rad,0.0, rad,-rad,0.0, 0.0,0.0,(double)h/256.);
|
|
// zzz[2] = plane(xx,yy, -rad,rad,0.0, -rad,-rad,0.0, 0.0,0.0,(double)h/256.);
|
|
// zzz[3] = plane(xx,yy, rad,rad,0.0, rad,-rad,0.0, 0.0,0.0,(double)h/256.);
|
|
|
|
for(ang = phs,i = 0;i < n;i++,ang += angle){
|
|
zzz[i] = plane(xx,yy,rad*sin(ang),rad*cos(ang),0.0, rad*sin(ang + angle),rad*cos(ang + angle),0.0, 0.0,0.0,(double)h/256.);
|
|
if(zzz[i] < 0.0) zzz[i] = 0.0;
|
|
}
|
|
|
|
zz = minim(zzz,n);
|
|
if(zz > 0){
|
|
*p = (short)(zz*h);
|
|
if(inverse) *p = -*p;
|
|
if(plain) *p = level;
|
|
else *p += level;
|
|
}
|
|
}
|
|
delete[] zzz;
|
|
}
|
|
|
|
ImpPeak::ImpPeak(int _sx,int _sy,int _force,int _mode,int _level,int _rad,int _h,int _n,int _phase,int _inverse,int _plain,int _noiseLevel,int _noiseAmp)
|
|
: ImpassType(_sx,_sy,_force,_mode,_level,_rad,_h)
|
|
{ }
|
|
|
|
void ImpPeak::build(void)
|
|
{
|
|
for(int i = 0;i < sx*sy;i++) map[i] = PeakData[i];
|
|
}
|
|
|