396 lines
8.1 KiB
C
396 lines
8.1 KiB
C
|
|
// temporary structs for loading
|
|
struct s_tmpvx
|
|
{
|
|
long x;
|
|
long y;
|
|
long z;
|
|
int power; // for center
|
|
};
|
|
struct s_tmpnr
|
|
{
|
|
long x;
|
|
long y;
|
|
long z;
|
|
};
|
|
struct s_tmpgnr // gouraud normal
|
|
{
|
|
long x;
|
|
long y;
|
|
long z;
|
|
int power;
|
|
};
|
|
struct s_tmpfc
|
|
{
|
|
int v[3]; // vertex number
|
|
char vv[3]; // vertex (edge) visible
|
|
char used;
|
|
char material;
|
|
};
|
|
|
|
// buffers for reading objects from asc
|
|
char oname[64];
|
|
int vxleft,fcleft;
|
|
int vxmap[MAXVX];
|
|
struct s_tmpvx vxdata[MAXVX];
|
|
struct s_tmpnr nrdata[MAXNR];
|
|
struct s_tmpgnr gvxdata[MAXVX];
|
|
struct s_tmpfc fcdata[MAXFC];
|
|
struct s_tmpvx *vx=vxdata;
|
|
struct s_tmpnr *nr=nrdata;
|
|
struct s_tmpfc *fc=fcdata;
|
|
struct s_tmpgnr *gvx=gvxdata;
|
|
int vxnum,fcnum,nrnum,nrnum1;
|
|
int vxcount,fccount; // original in 3DS
|
|
|
|
int facedata[16384],facedatalen; // len=words
|
|
int faceoff[MAXFC],facenum;
|
|
|
|
#include "opt.c"
|
|
|
|
int addvx(long x,long y,long z)
|
|
{
|
|
int i;
|
|
for(i=0;i<vxnum;i++)
|
|
{
|
|
if(vx[i].x==x && vx[i].y==y && vx[i].z==z)
|
|
{
|
|
vx[i].power++;
|
|
return(i);
|
|
}
|
|
}
|
|
vx[vxnum].power=1;
|
|
gvx[vxnum].power=0;
|
|
vx[vxnum].x=x;
|
|
vx[vxnum].y=y;
|
|
vx[vxnum].z=z;
|
|
return(vxnum++);
|
|
}
|
|
|
|
int addnr(long x,long y,long z)
|
|
{
|
|
int i;
|
|
for(i=0;i<nrnum;i++)
|
|
{
|
|
if(nr[i].x==x && nr[i].y==y && nr[i].z==z)
|
|
{
|
|
return(i);
|
|
}
|
|
}
|
|
nr[nrnum].x=x;
|
|
nr[nrnum].y=y;
|
|
nr[nrnum].z=z;
|
|
return(nrnum++);
|
|
}
|
|
|
|
void resetscene(void)
|
|
{
|
|
struct s_cobject *co1;
|
|
int i,a;
|
|
co1=co;
|
|
for(i=0;i<conum;i++)
|
|
{
|
|
co1->last_on=0;
|
|
co1->last_x=0;
|
|
co1->last_y=0;
|
|
co1->last_z=0;
|
|
for(a=0;a<9;a++) co1->last_m[a]=0;
|
|
co1++;
|
|
}
|
|
}
|
|
|
|
int duplicate(struct s_cobject *co0)
|
|
{
|
|
int a;
|
|
struct s_cobject *co1;
|
|
co1=co+conum;
|
|
co1->index=co0->index;
|
|
strcpy(co1->name,co0->name);
|
|
co1->last_on=0;
|
|
co1->last_x=0;
|
|
co1->last_y=0;
|
|
co1->last_z=0;
|
|
for(a=0;a<9;a++) co1->last_m[a]=0;
|
|
co1->lastused=-1;
|
|
co1->duplicate=1;
|
|
co1->original=co0-co;
|
|
co1->size=co0->size;
|
|
strcpy(co1->fname,co0->fname);
|
|
co1->o=getmem(sizeof(object));
|
|
memcpy(co1->o,co0->o,sizeof(object));
|
|
// new object needs new matrices
|
|
co1->o->r=getmem(sizeof(rmatrix));
|
|
co1->o->r0=getmem(sizeof(rmatrix));
|
|
memset(co1->o->r,0,sizeof(rmatrix));
|
|
memset(co1->o->r0,0,sizeof(rmatrix));
|
|
return(conum++);
|
|
}
|
|
|
|
struct s_cobject *create(void)
|
|
{
|
|
int a;
|
|
object *o;
|
|
|
|
co[conum].o=o=getmem(sizeof(object));
|
|
memcpy(co[conum].name,oname,17);
|
|
co[conum].name[17]=0;
|
|
co[conum].index=conum;
|
|
co[conum].last_on=0;
|
|
co[conum].last_x=0;
|
|
co[conum].last_y=0;
|
|
co[conum].last_z=0;
|
|
for(a=0;a<9;a++) co[conum].last_m[a]=0;
|
|
o->flags=F_DEFAULT;
|
|
o->r=getmem(sizeof(rmatrix));
|
|
o->r0=getmem(sizeof(rmatrix));
|
|
calc_setrmatrix_ident(o->r0);
|
|
o->r0->x=o->r0->y=o->r0->z=0;
|
|
o->pd=getmem(facedatalen*2);
|
|
o->pdlen=facedatalen*2;
|
|
o->plnum=1;
|
|
for(a=0;a<SORTDIRS+1;a++)
|
|
{
|
|
o->pl[a]=getmem((3+facenum)*2);
|
|
}
|
|
o->nnum=nrnum;
|
|
o->nnum1=nrnum1;
|
|
o->vnum=vxnum;
|
|
o->v0=getmem(vxnum*sizeof(vlist));
|
|
o->n0=getmem(nrnum*sizeof(nlist));
|
|
o->v=getmem(vxnum*sizeof(vlist));
|
|
o->n=getmem(nrnum*sizeof(nlist));
|
|
o->pv=getmem(vxnum*sizeof(pvlist));
|
|
o->vf=0;
|
|
// copy vertices etc to just allocated object
|
|
for(a=0;a<vxnum;a++)
|
|
{
|
|
o->v0[a].x=vx[a].x;
|
|
o->v0[a].y=vx[a].y;
|
|
o->v0[a].z=vx[a].z;
|
|
o->v0[a].normal=vx[a].power; // power=normal
|
|
o->v0[a].RESERVED=0xfc;
|
|
}
|
|
for(a=0;a<nrnum;a++)
|
|
{
|
|
o->n0[a].x=(int)nr[a].x;
|
|
o->n0[a].y=(int)nr[a].y;
|
|
o->n0[a].z=(int)nr[a].z;
|
|
o->n0[a].RESERVED=0xfc;
|
|
}
|
|
memcpy(o->pd,facedata,facedatalen*2);
|
|
memcpy(o->pl[0]+2,faceoff,2*facenum);
|
|
o->pl[0][0]=facenum+3; // words in list
|
|
o->pl[0][1]=0; // closest=center in list 0 (set later)
|
|
o->pl[0][facenum+2]=0; // end
|
|
return(co+(conum++));
|
|
}
|
|
|
|
int calccenter(void)
|
|
{
|
|
long x,y,z,p;
|
|
int a;
|
|
for(x=y=z=0,a=1;a<vxnum;a++)
|
|
{
|
|
p=vx[a].power;
|
|
x+=vx[a].x*p; y+=vx[a].y*p; z+=vx[a].z*p;
|
|
}
|
|
if(vxnum>1)
|
|
{
|
|
x/=vxnum-1; y/=vxnum-1; z/=vxnum-1;
|
|
}
|
|
print("Centerxyz: %li,%li,%li\n",x,y,z);
|
|
return(addvx(x,y,z));
|
|
}
|
|
|
|
void unify(long *x,long *y,long *z)
|
|
{
|
|
double d;
|
|
d=sqrt((double)*x*(double)*x+(double)*y*(double)*y+(double)*z*(double)*z);
|
|
if(!d) return;
|
|
d=1/d;
|
|
*x=(long)(NORMALSIZE*(double)*x*d);
|
|
*y=(long)(NORMALSIZE*(double)*y*d);
|
|
*z=(long)(NORMALSIZE*(double)*z*d);
|
|
}
|
|
|
|
void objectdone(void)
|
|
{
|
|
long x,y,z;
|
|
long cx,cy,cz;
|
|
int svx[SORTDIRS+1];
|
|
int a,center;
|
|
struct s_cobject *co;
|
|
if(vxleft || fcleft) error("Not all vertices (%i missing) or faces (%i missing) found!",vxleft,fcleft);
|
|
optimize(); // combines triangles to larger faces and creates polydata
|
|
center=calccenter(); // calculate center
|
|
cx=vx[center].x;
|
|
cy=vx[center].y;
|
|
cz=vx[center].z;
|
|
for(a=0;a<SORTDIRS;a++) // calculate box for Z sort
|
|
{
|
|
sortdir(a,&x,&y,&z);
|
|
svx[a]=addvx(x+cx,y+cy,z+cz);
|
|
}
|
|
nrnum1=nrnum;
|
|
// add gouraud normals
|
|
for(a=0;a<vxnum;a++) if(gvx[a].power)
|
|
{
|
|
x=gvx[a].x/gvx[a].power;
|
|
y=gvx[a].y/gvx[a].power;
|
|
z=gvx[a].z/gvx[a].power;
|
|
unify(&x,&y,&z);
|
|
vx[a].power=addnr(x,y,z);
|
|
}
|
|
else vx[a].power=-1;
|
|
// all vertices & normals should be in tmp structs now!
|
|
co=create(); // allocate memory for object and copy data to it
|
|
co->duplicate=0;
|
|
co->original=conum-1;
|
|
co->lastused=-1;
|
|
co->o->pl[0][1]=center; // sortlist0's closest vertex should be center
|
|
for(a=0;a<SORTDIRS;a++) co->o->pl[a+1][1]=svx[a];
|
|
print(" Faces: %i => %i\n",fccount,facenum);
|
|
print(" Normals: %i => %i (%i)\n",fccount,nrnum1,nrnum);
|
|
print("Vertices: %i => %i\n",vxcount,vxnum);
|
|
co->f1=fccount; co->f2=facenum;
|
|
co->n1=fccount; co->n2=nrnum1; co->ng=nrnum;
|
|
co->v1=vxcount; co->v2=vxnum;
|
|
*oname=0;
|
|
}
|
|
|
|
void readasc(void)
|
|
{
|
|
char tmp[256];
|
|
int a,b,i1,i2,i3;
|
|
int i1v,i2v,i3v;
|
|
long x,y,z;
|
|
float f,fx,fy,fz;
|
|
char *p,*p0,*t;
|
|
print("\n");
|
|
print(">>>>>>>>>>>>>>>> ASC file <<<<<<<<<<<<<<<<\n");
|
|
print("\n");
|
|
while(!feof(in))
|
|
{
|
|
p0=p=getline();
|
|
if(emptyline(p)) continue;
|
|
// process line
|
|
t=getfirsttoken(&p);
|
|
IFT("Named")
|
|
{
|
|
if(*oname)
|
|
{
|
|
objectdone();
|
|
print("}\n");
|
|
print("\n");
|
|
}
|
|
gettoken(&p); // 'object:'
|
|
t=gettoken(&p);
|
|
strcpy(tmp,t);
|
|
do
|
|
{
|
|
p0=p=getline();
|
|
}
|
|
while(emptyline(p));
|
|
IFS(p,"Tri-mesh")
|
|
{
|
|
print("TRIMESH %s\n",tmp);
|
|
strcpy(oname,tmp);
|
|
p=p0;
|
|
getseek(&p,"Vertices:");
|
|
i1=getint(&p);
|
|
p=p0;
|
|
getseek(&p,"Faces:");
|
|
i2=getint(&p);
|
|
print("vertices:%i faces:%i\n",i1,i2);
|
|
print("{\n");
|
|
//
|
|
vxnum=0;
|
|
nrnum=0;
|
|
fcnum=0;
|
|
vxcount=vxleft=i1;
|
|
fccount=fcleft=i2;
|
|
//
|
|
}
|
|
else
|
|
{
|
|
print("SKIPPING OBJECT %s (%s)\n",tmp,p);
|
|
}
|
|
continue;
|
|
}
|
|
if(!*oname) continue; // no object being processed!
|
|
IFT("Vertex")
|
|
{
|
|
t=gettoken(&p);
|
|
IFT("list:") continue;
|
|
i1=atoi(t);
|
|
//if(i1!=vxnum) error("Vertex indices out of order");
|
|
getxxyyzz(&p,&x,&y,&z);
|
|
vxmap[i1]=addvx(x,y,z);
|
|
print("vertex %i (%li,%li,%li)\n",i1,x,y,z);
|
|
vxleft--;
|
|
}
|
|
else IFT("Smoothing:")
|
|
{
|
|
// skip smoothing groups for now
|
|
}
|
|
else IFT("Material:")
|
|
{
|
|
t=p0+10;
|
|
for(a=0;a<strlen(t);a++) if(t[a]=='\"')
|
|
{
|
|
t[a]=0;
|
|
break;
|
|
}
|
|
b=strlen(t);
|
|
for(a=0;a<matnum;a++)
|
|
{
|
|
if(!memcmp(t,mat[a].name,b))
|
|
{
|
|
fc[fcnum-1].material=a;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else IFT("Face")
|
|
{
|
|
t=gettoken(&p);
|
|
IFT("list:") continue;
|
|
a=atoi(t);
|
|
if(a!=fcnum) error("Face indices out of order");
|
|
t=gettoken(&p);
|
|
i1=atoi(t+2);
|
|
t=gettoken(&p);
|
|
i2=atoi(t+2);
|
|
t=gettoken(&p);
|
|
i3=atoi(t+2);
|
|
t=gettoken(&p);
|
|
i1v=t[3]-'0';
|
|
t=gettoken(&p);
|
|
i2v=t[3]-'0';
|
|
t=gettoken(&p);
|
|
i3v=t[3]-'0';
|
|
fc[fcnum].v[0]=vxmap[i1];
|
|
fc[fcnum].v[1]=vxmap[i2];
|
|
fc[fcnum].v[2]=vxmap[i3];
|
|
fc[fcnum].vv[0]=(char)i1v;
|
|
fc[fcnum].vv[1]=(char)i2v;
|
|
fc[fcnum].vv[2]=(char)i3v;
|
|
fc[fcnum].used=0;
|
|
fc[fcnum].material=0;
|
|
print("face %i (%c%i,%c%i,%c%i)\n",a,
|
|
i1v?'+':'-',i1,
|
|
i2v?'+':'-',i2,
|
|
i3v?'+':'-',i3);
|
|
fcnum++;
|
|
fcleft--;
|
|
}
|
|
else print("Unknown: %s\n",t);
|
|
if(debug) print(" (%s)\n",p0);
|
|
}
|
|
if(*oname)
|
|
{
|
|
objectdone();
|
|
print("}\n");
|
|
print("\n");
|
|
}
|
|
}
|