SecondReality/VISU/C/OPT.C
2017-09-24 01:45:36 +02:00

132 lines
2.7 KiB
C

/* ASC optimization from:
char oname[64];
struct s_tmpvx *vx;
struct s_tmpfc *fc;
int vxnum,fcnum,vxleft,fcleft;
to:
int facedata[32767],facedatalen;
int faceoff[MAXFC],facenum;
*/
int currentface;
int connects[256],connectp;
int pvnum;
int pv[MAXFACE];
void padd(int v) // add vertex to pv
{
if(pvnum && pv[pvnum-1]==v) return;
pv[pvnum++]=v;
if(pvnum>=MAXFACE)
{
int a;
printf("FATAL ERROR: FACE OVERFLOW (SEE REPORT)");
print("FATAL: FACE %i OVERFLOWS (max %i sides) [",currentface,MAXFACE);
for(a=0;a<connectp;a++) print("%i ",connects[a]);
print("]");
exit(3);
}
}
void pexpand(struct s_tmpfc *f,int i,int cntn) // add face to pv
{
int k,l,v1,v2,cnt;
if(f->used) return;
f->used=1;
for(cnt=0;cnt<cntn;cnt++)
{
if(f->vv[i]) padd(f->v[i]);
else
{ // find the polygon on side and recurse
l=-1; // nothing found
v1=f->v[(i==2)?0:i+1];
v2=f->v[i];
for(k=0;k<fcnum;k++) if(!fc[k].used)
{
if(fc[k].v[0]==v1 && fc[k].v[1]==v2)
{
l=1; break;
}
if(fc[k].v[1]==v1 && fc[k].v[2]==v2)
{
l=2; break;
}
if(fc[k].v[2]==v1 && fc[k].v[0]==v2)
{
l=0; break;
}
}
if(l==-1)
{ // failed to find
padd(f->v[i]);
}
else
{
connects[connectp++]=k;
pexpand(fc+k,l,2);
}
}
i=(i==2)?0:i+1;
}
}
void optimize(void)
{
int nrm,i,j,flags,a;
facedatalen=facenum=0;
facedata[facedatalen++]=0; // 'null' face
for(j=0;j<vxnum;j++)
{
gvx[j].x=gvx[j].y=gvx[j].z=gvx[j].power=0;
}
for(i=0;i<fcnum;i++)
{
currentface=i;
connectp=0;
pvnum=0;
connects[connectp++]=i;
pexpand(fc+i,0,3);
if(pvnum)
{
long x=0,y=0,z=0;
// calc normal
{
struct s_tmpvx *v;
struct s_tmpvx *w;
int a,b;
double dl;
for(a=0;a<pvnum;a++)
{
v=vx+pv[a];
w=vx+pv[a?(a-1):(pvnum-1)];
x+=(v->y-w->y)*(v->z+w->z);
y+=(v->z-w->z)*(v->x+w->x);
z+=(v->x-w->x)*(v->y+w->y);
}
dl=sqrt((double)x*(double)x+(double)y*(double)y+(double)z*(double)z);
if(dl<-1 || dl>1)
{
x=-(long)((double)x*NORMALSIZE/dl);
y=-(long)((double)y*NORMALSIZE/dl);
z=-(long)((double)z*NORMALSIZE/dl);
}
nrm=addnr(x,y,z);
}
// write stuff
flags=mat[fc[i].material].flags;
faceoff[facenum++]=facedatalen*2; // char offset
facedata[facedatalen++]=pvnum|flags; // sides | flags
facedata[facedatalen++]=mat[fc[i].material].color; // color
facedata[facedatalen++]=nrm; // normal
for(j=0;j<pvnum;j++)
{
a=pv[j];
gvx[a].x+=x;
gvx[a].y+=y;
gvx[a].z+=z;
gvx[a].power++;
facedata[facedatalen++]=a;
}
}
}
}