271 lines
5.3 KiB
Text
271 lines
5.3 KiB
Text
// object sorting
|
|
|
|
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);
|
|
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=-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;
|
|
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 *ip,*pp;
|
|
long d1=0,d2=0,dc=0,d,d1a,d2a;
|
|
int d1c=0,d2c=0;
|
|
int a,c;
|
|
|
|
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
|
|
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)/10000.0);
|
|
|
|
if(debcount<100)
|
|
{
|
|
fprintf(fdeb,"%id:%li\n",c,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;
|
|
if(d1a>d2a)
|
|
{
|
|
if(d1>0 && dc>0) return(1);
|
|
return(-1);
|
|
}
|
|
else
|
|
{
|
|
if(d2>0 && dc>0) return(1);
|
|
return(-1);
|
|
}
|
|
}
|
|
|
|
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;
|
|
int d,a,c,b,n,onum;
|
|
int changed;
|
|
int *ip,*pp;
|
|
osd=256;
|
|
for(d=0;d<8;d++)
|
|
{
|
|
sortdir(d,&osx,&osy,&osz);
|
|
osetup(o,1);
|
|
}
|
|
for(d=0;d<8;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)
|
|
{
|
|
osp[onum].o=*ip++;
|
|
pp=(int *)(osp[onum].o+(char *)o->pd);
|
|
c=*pp++; // sides
|
|
c&=0xff;
|
|
pp++; // skip color
|
|
n=*pp++; // skip normal
|
|
z=0; z2=0x7fffffff;
|
|
while(c--)
|
|
{
|
|
a=*pp++;
|
|
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;
|
|
}
|
|
osp[onum].a=pa=o->n[n].x;
|
|
osp[onum].b=pb=o->n[n].y;
|
|
osp[onum].c=pc=o->n[n].z;
|
|
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;
|
|
/*
|
|
if(debcount<100)
|
|
{
|
|
fprintf(fdeb,"%id:%li\n",c,td);
|
|
debcount++;
|
|
}
|
|
*/
|
|
}
|
|
|
|
onum++;
|
|
}
|
|
qsort(osp,onum,sizeof(osp[0]),qcmp);
|
|
//resort by planes
|
|
#if 1
|
|
for(j=0;j<onum;j++) osp[j].swapped=0;
|
|
for(i=0;i<onum;i++)
|
|
{
|
|
changed=0;
|
|
for(j=i+1;j<onum;j++)
|
|
{
|
|
a=planecompare(osp+i,osp+j,o);
|
|
// -1=j farther than i (swap)
|
|
// 0==indetermined
|
|
// 1==i farther than j (ok)
|
|
// 2==i farther than j.. (next)
|
|
if(a==2) break;
|
|
else if(a==-1)
|
|
{
|
|
if(osp[j].swapped) continue; // no double swap
|
|
changed=1;
|
|
memcpy(&osptmp,osp+j,sizeof(osptmp));
|
|
memcpy(osp+j,osp+i,sizeof(osptmp));
|
|
memcpy(osp+i,&osptmp,sizeof(osptmp));
|
|
osp[j].swapped=1;
|
|
j=-1;
|
|
}
|
|
}
|
|
if(changed) i--;
|
|
else for(j=i+1;j<onum;j++) osp[j].swapped=0;
|
|
}
|
|
#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==13) skipw=1;
|
|
}
|
|
o->flags=fbak;
|
|
}
|
|
}
|