322 lines
7 KiB
C
322 lines
7 KiB
C
// object sorting
|
|
|
|
//#define SORTDIRS 6
|
|
#define SORTDIRS 8
|
|
|
|
long osx,osy,osz; // sorting eye
|
|
long aosx,aosy,aosz; // sorting eye
|
|
long bosx,bosy,bosz; // sorting eye
|
|
static long osd=0;
|
|
|
|
void osetup(object *o,int flag)
|
|
{ // sets up camera distance etc for good viewing
|
|
long cx,cy,cz;
|
|
long ox,oy,oz;
|
|
long d=osd;
|
|
int a,c;
|
|
vlist *v;
|
|
for(c=0;c<64;c++)
|
|
{
|
|
ox=osx*d/256L;
|
|
oy=osy*d/256L;
|
|
oz=osz*d/256L;
|
|
v=o->v0+o->pl[0][1];
|
|
cx=v->x;
|
|
cy=v->y;
|
|
cz=v->z;
|
|
calc_setrmatrix_camera(o->r,ox+cx,oy+cy,oz+cz,cx,cy,cz,0);
|
|
calc_nrotate(o->nnum1,o->n,o->n0,o->r);
|
|
calc_rotate(o->vnum,o->v,o->v0,o->r);
|
|
calc_project(o->vnum,o->pv,o->v);
|
|
if(!flag) break;
|
|
for(a=0;a<o->vnum;a++) if(o->pv[a].vf) break;
|
|
if(a==o->vnum) break;
|
|
d=d*4/3;
|
|
}
|
|
if(osd<d) osd=d;
|
|
}
|
|
|
|
void sortdir(int d,long *osx,long *osy,long *osz)
|
|
{
|
|
switch(d)
|
|
{
|
|
/*
|
|
case 0 : *osx=-256; *osy=0; *osz=0; break;
|
|
case 1 : *osy=-256; *osz=0; *osx=0; break;
|
|
case 2 : *osz=-256; *osx=30; *osy=30; break;
|
|
case 3 : *osx=256; *osy=0; *osz=0; break;
|
|
case 4 : *osy=256; *osz=0; *osx=0; break;
|
|
case 5 : *osz=256; *osx=30; *osy=30; break;
|
|
*/
|
|
case 0 : *osx=-256; *osy=-256; *osz=-256; break;
|
|
case 1 : *osx=256; *osy=-256; *osz=-256; break;
|
|
case 2 : *osx=256; *osy=256; *osz=-256; break;
|
|
case 3 : *osx=-256; *osy=256; *osz=-256; break;
|
|
case 4 : *osx=-256; *osy=-256; *osz=256; break;
|
|
case 5 : *osx=256; *osy=-256; *osz=256; break;
|
|
case 6 : *osx=256; *osy=256; *osz=256; break;
|
|
case 7 : *osx=-256; *osy=256; *osz=256; break;
|
|
case 8 : *osx=-366; *osy=0; *osz=0; break;
|
|
/*
|
|
case 0 : *osx=-256; *osy=-256; *osz=-256; break;
|
|
case 1 : *osx=256; *osy=-256; *osz=-256; break;
|
|
case 2 : *osx=256; *osy=256; *osz=-256; break;
|
|
case 3 : *osx=-256; *osy=256; *osz=-256; break;
|
|
case 4 : *osx=-256; *osy=-256; *osz=256; break;
|
|
case 5 : *osx=0; *osy=366; *osz=0; break;
|
|
case 6 : *osx=256; *osy=-256; *osz=256; break;
|
|
case 7 : *osx=0; *osy=-366; *osz=0; break;
|
|
case 8 : *osx=256; *osy=256; *osz=256; break;
|
|
case 9 : *osx=-366; *osy=0; *osz=0; break;
|
|
case 10 : *osx=-256; *osy=256; *osz=256; break;
|
|
case 11 : *osx=366; *osy=0; *osz=0; break;
|
|
case 12 : *osx=30; *osy=30; *osz=-366; break;
|
|
case 13 : *osx=30; *osy=30; *osz=366; break;
|
|
*/
|
|
default : *osx=*osy=*osz=0; break;
|
|
}
|
|
}
|
|
|
|
struct s_osp
|
|
{
|
|
long dis; // distance maximum
|
|
long dismin; // distance minimum
|
|
long a,b,c,d; // plane equation
|
|
int o; // offset
|
|
int swapped;
|
|
} osp[MAXFC];
|
|
struct s_osp osptmp;
|
|
|
|
int qcmp(struct s_osp *a,struct s_osp *b)
|
|
{
|
|
if(a->dis>b->dis) return(-1);
|
|
if(a->dis<b->dis) return(1);
|
|
return(0);
|
|
}
|
|
|
|
// -1=j farther than i (swap)
|
|
// 0==indetermined
|
|
// 1==i farther than j (ok)
|
|
// 2==i farther than j.. (next)}
|
|
int planecompare(struct s_osp *i,struct s_osp *j,object *o,int flag)
|
|
{
|
|
int *ip,*pp;
|
|
long d1=0,d2=0,dc=0,d,d1a,d2a,dd;
|
|
int d1c=0,d2c=0;
|
|
int a,c,r;
|
|
|
|
if(i->dismin>j->dis) return(2);
|
|
|
|
pp=(int *)(j->o+(char *)(o->pd));
|
|
c=*pp++; // sides
|
|
c&=0xff;
|
|
pp++; // skip color
|
|
pp++; // skip normal
|
|
//fprintf(fdeb,"compare i=f%i(%i) with j=f%i(%i)\n",i-osp,i->o,j-osp,j->o);
|
|
while(c--)
|
|
{
|
|
a=*pp++;
|
|
d=(long)(((double)o->v[a].x*(double)i->a+(double)o->v[a].y*(double)i->b+(double)o->v[a].z*(double)i->c+(double)i->d)/1000.0);
|
|
|
|
if(debcount<1000)
|
|
{
|
|
//fprintf(fdeb,"v%i:%li ",a,d);
|
|
debcount++;
|
|
}
|
|
|
|
if(d<0) { d1+=d; d1c++; }
|
|
else { d2+=d; d2c++; }
|
|
}
|
|
if(d1c) d1/=d1c;
|
|
if(d2c) d2/=d2c;
|
|
// camera at zero, so dc=i->d;
|
|
dc=i->d;
|
|
if(d1<0) d1a=-d1; else d1a=d1;
|
|
if(d2<0) d2a=-d2; else d2a=d2;
|
|
d=d1a-d2a; if(d<0) d=-d;
|
|
dd=(d1a+d2a)/8;
|
|
if(d<dd) return(0); // comaparator face cuts this one in middle
|
|
//fprintf(fdeb,"\ncamera at %li, d1=%li, d1c=%i, d2=%li, d2c=%i, d1a=%li d2a=%li\n",dc,d1,d1c,d2,d2c,d1a,d2a);
|
|
if(d1a>d2a)
|
|
{
|
|
if(d1>0 && dc>0) r=1;
|
|
else if(d1<0 && dc<0) r=1;
|
|
else r=-1;
|
|
}
|
|
else
|
|
{
|
|
if(d2>0 && dc>0) r=1;
|
|
else if(d2<0 && dc<0) r=1;
|
|
else r=-1;
|
|
}
|
|
if(flag)
|
|
{
|
|
a=planecompare(j,i,o,0);
|
|
if(a==r) r=0;
|
|
//fprintf(fdeb,"returns %i\n\n",r);
|
|
}
|
|
return(r);
|
|
}
|
|
|
|
void objectsort(object *o)
|
|
{
|
|
static int skipw=0;
|
|
long z,z1,z2;
|
|
long px,py,pz,pa,pb,pc,pd,td;
|
|
int fbak,i,j,k;
|
|
int d,a,c,b,n,onum;
|
|
int changed;
|
|
int *ip,*pp;
|
|
osd=256;
|
|
for(d=0;d<SORTDIRS;d++)
|
|
{
|
|
sortdir(d,&osx,&osy,&osz);
|
|
osetup(o,1);
|
|
}
|
|
for(d=0;d<SORTDIRS;d++)
|
|
{
|
|
aosx=osx;
|
|
aosy=osy;
|
|
aosz=osz;
|
|
sortdir(d,&osx,&osy,&osz);
|
|
bosx=osx;
|
|
bosy=osy;
|
|
bosz=osz;
|
|
if(d && !skipw)
|
|
{
|
|
for(a=0;a<=64;a+=2)
|
|
{
|
|
b=64-a;
|
|
osx=(aosx*(long)b+bosx*(long)a)>>6;
|
|
osy=(aosy*(long)b+bosy*(long)a)>>6;
|
|
osz=(aosz*(long)b+bosz*(long)a)>>6;
|
|
osetup(o,0);
|
|
fbak=o->flags;
|
|
o->flags&=~(F_GOURAUD);
|
|
vNext();
|
|
vis_drawobject(o);
|
|
o->flags=fbak;
|
|
}
|
|
}
|
|
osx=bosx;
|
|
osy=bosy;
|
|
osz=bosz;
|
|
osetup(o,0);
|
|
ip=o->pl[0]+2;
|
|
onum=0;
|
|
while(*ip)
|
|
{
|
|
a=osp[onum].o=*ip++;
|
|
pp=(int *)(osp[onum].o+(char *)o->pd);
|
|
c=*pp++; // sides
|
|
c&=0xff;
|
|
if(a!=68 && a!=56)
|
|
{
|
|
// *pp=-1;
|
|
}
|
|
pp++; // skip color
|
|
n=*pp++; // skip normal
|
|
z=0; z2=0x7fffffff;
|
|
//fprintf(fdeb,"face %i: ",osp[onum].o);
|
|
while(c--)
|
|
{
|
|
a=*pp++;
|
|
//fprintf(fdeb,"%i ",a);
|
|
if(c==1)
|
|
{
|
|
px=o->v[a].x;
|
|
py=o->v[a].y;
|
|
pz=o->v[a].z;
|
|
}
|
|
z1=o->v[a].z;
|
|
if(z1>z) z=z1;
|
|
if(z1<z2) z2=z1;
|
|
}
|
|
//fprintf(fdeb,"\n");
|
|
osp[onum].a=pa=o->n[n].x/4;
|
|
osp[onum].b=pb=o->n[n].y/4;
|
|
osp[onum].c=pc=o->n[n].z/4;
|
|
osp[onum].d=pd=-px*pa-py*pb-pz*pc;
|
|
osp[onum].dis=z;
|
|
osp[onum].dismin=z2;
|
|
|
|
pp=(int *)(osp[onum].o+(char *)o->pd);
|
|
c=*pp++; // sides
|
|
c&=0xff;
|
|
pp++; // skip color
|
|
pp++; // skip normal
|
|
while(c--)
|
|
{
|
|
a=*pp++;
|
|
td=o->v[a].x*pa+o->v[a].y*pb+o->v[a].z*pc+pd;
|
|
}
|
|
|
|
onum++;
|
|
}
|
|
qsort(osp,onum,sizeof(osp[0]),qcmp);
|
|
//resort by planes
|
|
#if 0
|
|
for(i=0;i<onum;i++)
|
|
{
|
|
for(k=i+1;k<onum;k++)
|
|
{
|
|
for(j=k;j<onum;j++)
|
|
{
|
|
for(a=0;a<8;a++)
|
|
{
|
|
//fprintf(fdeb,"%i%c ",osp[a].o,osp[a].swapped?'*':'.');
|
|
}
|
|
//fprintf(fdeb,"\n");
|
|
a=planecompare(osp+i,osp+j,o,1);
|
|
// -1=j farther than i (swap)
|
|
// 0==indetermined
|
|
// 1==i farther than j (ok)
|
|
// 2==i farther than j.. (next)
|
|
/*
|
|
if(a==2)
|
|
{
|
|
j=onum;
|
|
break;
|
|
}
|
|
else */
|
|
if(a==-1)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if(j==onum) break; //all faces after i were before it
|
|
memcpy(&osptmp,osp+k,sizeof(osptmp));
|
|
memcpy(osp+k,osp+i,sizeof(osptmp));
|
|
memcpy(osp+i,&osptmp,sizeof(osptmp));
|
|
}
|
|
}
|
|
#endif
|
|
o->plnum=d+2;
|
|
ip=o->pl[d+1];
|
|
*ip++=onum+3;
|
|
ip++; // skip center vertex id
|
|
for(a=0;a<onum;a++)
|
|
{
|
|
*ip++=osp[a].o;
|
|
}
|
|
*ip++=0;
|
|
|
|
fbak=o->flags;
|
|
o->flags&=~(F_GOURAUD);
|
|
vNext();
|
|
vis_drawobject(o);
|
|
if(!skipw)
|
|
{
|
|
vNext();
|
|
vis_drawobject(o);
|
|
vNext();
|
|
vis_drawobject(o);
|
|
vNext();
|
|
vis_drawobject(o);
|
|
a=getch();
|
|
if(a==27) break;
|
|
if(a==13) skipw=1;
|
|
}
|
|
o->flags=fbak;
|
|
}
|
|
}
|