132 lines
2.7 KiB
C
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;
|
|
}
|
|
}
|
|
}
|
|
}
|