www.pudn.com > 3DEDITOR.rar > OBJECT.CPP
#include "stdafx.h"
#include "3DEditor.h"
#include "impexp3ds.h"
#include "import3ds_pm.h"
extern char str[256],docpath[256];
int backface_culling;
#define SMALL_TX 0.001
void scene::reset()
{
if (piclib)
{
while(--npiclib>=0)
piclib[npiclib].FreePicture();
delete piclib;
}
if (matlib)
delete matlib;
if (obj0)
delete obj0;
if (camlib)
delete camlib;
if (lightlib)
delete lightlib;
if (oc) delete oc;
oc=0;
nlights=0;
lightlib=0;
camlib=0;
piclib=0;
matlib=0;
obj0=0;
ncamlib=0;
nmatlib=0;
nobj=0;
npiclib=0;
}
void scene::ComputeBBoxes()
{
bbox1.Vec(BIG,BIG,BIG);
bbox2.Vec(-BIG,-BIG,-BIG);
object *o=obj0;
while( o )
{
o->compute_bbox();
if (o->bbox2.x>bbox2.x)
bbox2.x=o->bbox2.x;
if (o->bbox2.y>bbox2.y)
bbox2.y=o->bbox2.y;
if (o->bbox2.z>bbox2.z)
bbox2.z=o->bbox2.z;
if (o->bbox1.xbbox1.x;
if (o->bbox1.ybbox1.y;
if (o->bbox1.zbbox1.z;
o=(object *)o->next;
}
bboxC=(bbox1+bbox2)/2.0;
bboxdiag=(bbox2-bbox1).Length();
}
int scene::find_image(char *name)
{
char *c=strrchr(name,'.');
if (c==0)
return -1;
if (stricmp(c+1,"tga") && stricmp(c+1,"jpg") && stricmp(c+1,"bmp") && stricmp(c+1,"wlm"))
return -1;
int n=0;
for( n=0;n=0)
{
strcpy(str,&mappaths[p*256]);
strcat(str,"\\");
}
else
*/
if (docpath[0]==0)
str[0]=0;
else
{
strcpy(str,docpath);
strcat(str,"\\");
}
strcat(str,name);
if (!stricmp(c+1,"tga"))
if (piclib[npiclib].LoadTGA(str))
{
strcpy(piclib[npiclib].name,name);
return npiclib++;
}
else ;
else
if (!stricmp(c+1,"jpg"))
if (piclib[npiclib].LoadJPG(str))
{
strcpy(piclib[npiclib].name,name);
return npiclib++;
}
else ;
else
if (piclib[npiclib].LoadBMP(str))
{
strcpy(piclib[npiclib].name,name);
return npiclib++;
}
else ;
// }
if (npiclib==0)
{
delete piclib;
npiclib=0;
piclib=0;
}
else
{
picture *temp=new picture[npiclib];
memcpy(temp,piclib,sizeof(picture)*npiclib);
delete piclib;
piclib=temp;
}
return -1;
}
void scene::load_images()
{
int n=0;
char *name;
char erro[512]="";
for( n=0;nnv*3];
unsigned short *faces=new unsigned short[o->nf*3];
unsigned short *mat=new unsigned short[nmatlib*2+o->nf];
int lmat=0, i, j, k, nvert=0, nfaces=0;
float *textcoord;
if(o->textcoord)
textcoord=new float[o->nv*2];
else
textcoord=0;
for( i=0;inf;j++ )
if(o->ft[j])
{
if(o->ft[j]->material==i)
mat[lmat+2+mat[lmat+1]++]=k;
k++;
}
if(mat[lmat+1])
lmat+=2+mat[lmat+1];
}
for( i=0;inv;i++ )
if (o->vt[i])
{
vert[3*nvert]=(float)o->vt[i]->pos.x;
vert[3*nvert+1]=(float)o->vt[i]->pos.y;
vert[3*nvert+2]=(float)o->vt[i]->pos.z;
if(o->textcoord)
{
textcoord[2*nvert]=o->vt[i]->tx[0];
textcoord[2*nvert+1]=o->vt[i]->tx[1];
}
o->vt[i]->flag=nvert++;
}
for( i=0;inf;i++ )
if (o->ft[i])
{
faces[nfaces*3]=o->ft[i]->lv[0]->flag;
faces[nfaces*3+1]=o->ft[i]->lv[1]->flag;
faces[nfaces*3+2]=o->ft[i]->lv[2]->flag;
nfaces++;
}
exp3ds.WriteNamedObject(o->name, vert, textcoord, nvert, faces, nfaces, mat, lmat, matlib,0);
delete vert;
delete textcoord;
delete faces;
delete mat;
o=o->next;
}
exp3ds.close(camlib, ncamlib, lightlib, nlights);
return 1;
}
return 0;
}
int scene::import(char *file,CListCtrl *lb)
{
char *c=strrchr(file,'.');
if (!c)
return 0;
if (!stricmp(c+1,"3ds"))
{
import3ds_pm ipm(this,lb,file);
return 1;
}
else return 0;
}
void object::reset()
{
if (vt)
{
int i;
for( i=0;ilv[1]->pos - ft[f]->lv[0]->pos;
n2=ft[f]->lv[2]->pos - ft[f]->lv[0]->pos;
ft[f]->normal.Cross(n1,n2);
ft[f]->normal.Normalize();
}
}
for( v=0;vnormal.Null();
vt[v]->flag=0;
}
for( f=0;flv[v]->normal+=ft[f]->normal;
ft[f]->lv[v]->flag++;
}
}
for( v=0;vflag)
{
vt[v]->normal/=(float)vt[v]->flag;
vt[v]->normal.Normalize();
}
}
}
int object::find_face_edge(int f,int i,int& g,int& j)
{
int a,b;
vtlist *v1=ft[f]->lv[i],*v2=ft[f]->lv[(i+1)%3];
for( a=f+1;alv[b]==v1 && ft[a]->lv[(b+1)%3]==v2) ||
(ft[a]->lv[b]==v2 && ft[a]->lv[(b+1)%3]==v1) )
{
if (ft[a]->lf[b])
continue;
g=a;
j=b;
return 1;
}
return 0;
}
void object::build_edge_tree()
{
int f,i,g,j;
for( f=0;flf[0]=0;
ft[f]->lf[1]=0;
ft[f]->lf[2]=0;
}
for( f=0;flf[i]==0)
if (find_face_edge(f,i,g,j))
{
ft[f]->lf[i]=ft[g];
ft[g]->lf[j]=ft[f];
}
}
}
int operator ==(ftlist &f1, ftlist &f2)
{
int i, j;
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
if (f1.lv[i]==f2.lv[j])
break;
if (j==3)
return 0;
}
return 1;
}
void object::DelFace(ftlist **f)
{
int k;
for(k=0;k<3;k++)
{
facelist *tmp=(*f)->lv[k]->faces;
if (((ftlist *)(tmp->face))==*f)
{
(*f)->lv[k]->faces=tmp->next;
tmp->next=0;
delete tmp;
}
else
{
facelist *tmp2=tmp->next;
while(tmp2)
{
if (((ftlist *)(tmp2->face)) == *f)
{
tmp->next=tmp2->next;
tmp2->next=0;
delete tmp2;
break;
}
tmp=tmp2;
tmp2=tmp2->next;
}
}
}
delete *f;
*f=0;
}
void object::DelDupVert()
{
int i, j;
for( i=0;ipos==vt[j]->pos)
if ( 0|| (fabs(vt[i]->tx[0]-vt[j]->tx[0])tx[1]-vt[j]->tx[1])lv[0]==ft[j]->lv[1] ||
ft[j]->lv[0]==ft[j]->lv[2] ||
ft[j]->lv[1]==ft[j]->lv[2])
DelFace(&ft[j]);
}
}
void object::fix_node_normal(ftlist *node)
{
unsigned short i,j;
node->flag=0;
for( i=0;i<3;i++ )
{
if (node->lf[i])
if (node->lf[i]->flag)
{
ftlist *node2=node->lf[i];
for( j=0;j<3;j++ )
if (node2->lf[j]==node)
break;
if (node->lv[i]==node2->lv[j])
{
void *t1;
t1=node2->lv[j];
node2->lv[j]=node2->lv[(j+1)%3];
node2->lv[(j+1)%3]=(vtlist *)t1;
t1=node2->lf[(j+1)%3];
node2->lf[(j+1)%3]=node2->lf[(j+2)%3];
node2->lf[(j+2)%3]=(ftlist *)t1;
}
fix_node_normal(node2);
}
}
}
void object::fix_normals()
{
int i;
for( i=0;iflag=1;
for( i=0;igroup=e;
node->flag=0;
elem[e].nf++;
for( i=0;i<3;i++ )
if (node->lv[i]->flag)
{
elem[e].nv++;
node->lv[i]->flag=0;
}
for( i=0;i<3;i++ )
if (node->lf[i])
if (node->lf[i]->flag)
count_node(node->lf[i],e);
}
void object::count_elements()
{
int i;
nelem=0;
for( i=0;iflag=1;
for( i=0;iflag=1;
while(1)
{
for( i=0;iflag==1)
break;
if (i==nf)
break;
else
{
if (nelem==0)
elem=new element;
else
{
element *tmp=new element[nelem+1];
memcpy(tmp,elem,sizeof(element)*nelem);
delete elem;
elem=tmp;
}
elem[nelem].nf=0;
elem[nelem].nv=0;
elem[nelem].elem=i;
count_node(ft[i],nelem);
nelem++;
}
}
}
void object::Explode()
{
vtlist **vt_temp;
vt_temp=new vtlist *[nf*3];
int f, i;
for( f=0;ffaces)
{
delete vt[f]->faces;
vt[f]->faces=0;
}
for( f=0;flv[i], sizeof(vtlist));
ft[f]->lv[i]=vt_temp[f*3+i];
}
else vt_temp[f*3]=vt_temp[f*3+1]=vt_temp[f*3+2]=0;
}
for( f=0;flf[i]=0;
for( f=0;ffaces=new facelist;
vt[f]->faces->face=ft[f/3];
}
}
void object::Implode()
{
int f, i, k, j;
vtlist *v1,*v2;
for(f=0;fflag=f;
for( f=0;flf[i]==0)
{
v1=ft[f]->lv[i];
v2=ft[f]->lv[(i+1)%3];
for(k=f+1;klf[j]==0)
{
// if (implode_dif_material==0)
if (ft[f]->material!=ft[k]->material)
break;
if((ft[k]->lv[j]->pos==v1->pos && ft[k]->lv[(j+1)%3]->pos==v2->pos)&&
(fabs(VecDot(ft[f]->normal,ft[k]->normal))>smoothang) )
{
// if (implode_dif_material==0)
if (fabs(v1->tx[0]-ft[k]->lv[j]->tx[0])>SMALL_TX ||
fabs(v1->tx[1]-ft[k]->lv[j]->tx[1])>SMALL_TX ||
fabs(v2->tx[0]-ft[k]->lv[(j+1)%3]->tx[0])>SMALL_TX ||
fabs(v2->tx[1]-ft[k]->lv[(j+1)%3]->tx[1])>SMALL_TX)
break;
change_index(v1->flag, ft[k]->lv[j]->flag);
change_index(v2->flag, ft[k]->lv[(j+1)%3]->flag);
ft[f]->lf[i]=ft[k];
ft[k]->lf[j]=ft[f];
break;
}
else
if((ft[k]->lv[j]->pos==v2->pos && ft[k]->lv[(j+1)%3]->pos==v1->pos)&&
(fabs(VecDot(ft[f]->normal,ft[k]->normal))>smoothang))
{
// if (implode_dif_material==0)
if (fabs(v1->tx[0]-ft[k]->lv[(j+1)%3]->tx[0])>SMALL_TX ||
fabs(v1->tx[1]-ft[k]->lv[(j+1)%3]->tx[1])>SMALL_TX ||
fabs(v2->tx[0]-ft[k]->lv[j]->tx[0])>SMALL_TX ||
fabs(v2->tx[1]-ft[k]->lv[j]->tx[1])>SMALL_TX)
break;
change_index(v1->flag, ft[k]->lv[(j+1)%3]->flag);
change_index(v2->flag, ft[k]->lv[j]->flag);
ft[f]->lf[i]=ft[k];
ft[k]->lf[j]=ft[f];
break;
}
}
if(j!=3)
break;
}
}
}
}
void object::CompactHoles()
{
int i,j;
nrf=nf;
nrv=nv;
for( i=0;ifaces;
while(tmp)
{
for(k=0;k<3;k++)
if(((ftlist *)(tmp->face))->lv[k]==vt[j])
break;
((ftlist *)(tmp->face))->lv[k]=vt[i];
tmp=tmp->next;
}
if(vt[i]->faces)
{
tmp=vt[i]->faces;
if(tmp->next)
do tmp=tmp->next;
while(tmp->next);
tmp->next=vt[j]->faces;
}
else vt[i]->faces=vt[j]->faces;
vt[j]->faces=0;
delete vt[j];
vt[j]=0;
}
float object::FindNextEdge(int group,int& f1,int& i1,int &f2,int& i2)
{
float dm=(float)1e20,d,dp;
int i,j;
int f,g;
vtlist *v1,*v2;
int a, tf1, tf2, tg1, tg2;
char *chk=new char[nf];
memset(chk,7,nf);
for( f=0;fgroup==group)
for( i=0;i<3;i++ )
if (chk[f]&(1<lf[i])
{
g=ft[f]->lf[i]->flag;
for( j=0;j<3;j++ )
if (ft[g]->lf[j]==ft[f])
break;
chk[g]&=(1<lv[i];
v2=ft[f]->lv[(i+1)%3];
d=(v1->pos - v2->pos).Length();
dp=(float)fabs(VecDot(v1->normal,v2->normal));
d/=dp;
if (desta_na_borda())
continue;
if (v2->esta_na_borda())
continue;
for( a=0;a<3;a++ )
if( ft[f]->lf[(i+1)%3]->lf[a]==ft[f] )
break;
tf1=(a+2)%3;
for( a=0;a<3;a++ )
if( ft[f]->lf[(i+2)%3]->lf[a]==ft[f] )
break;
tf2=(a+2)%3;
if(ft[f]->lf[(i+1)%3]->lv[tf1]==ft[f]->lf[(i+2)%3]->lv[tf2])
continue;
for( a=0;a<3;a++ )
if( ft[g]->lf[(j+1)%3]->lf[a]==ft[g] )
break;
tg1=(a+2)%3;
for( a=0;a<3;a++ )
if( ft[g]->lf[(j+2)%3]->lf[a]==ft[g] )
break;
tg2=(a+2)%3;
if(ft[g]->lf[(j+1)%3]->lv[tg1]==ft[g]->lf[(j+2)%3]->lv[tg2])
continue;
if(ft[f]->lf[(i+1)%3]->lv[tf1]==ft[g]->lf[(j+1)%3]->lv[tg1])
continue;
if(ft[f]->lf[(i+2)%3]->lv[tf2]==ft[g]->lf[(j+2)%3]->lv[tg2])
continue;
facelist *a1,*a2;
ftlist *b1,*b2;
int c1,c2;
a1=v1->faces;
while(a1)
{
b1=(ftlist *)a1->face;
if (b1==ft[f] || b1==ft[g] ||
b1==ft[f]->lf[(i+2)%3] ||
b1==ft[g]->lf[(j+1)%3])
{
a1=a1->next;
continue;
}
for( c1=0;c1<3;c1++ )
if (b1->lv[c1]==v1)
break;
a2=v2->faces;
while(a2)
{
b2=(ftlist *)a2->face;
if (b2==ft[f] || b2==ft[g] ||
b2==ft[f]->lf[(i+1)%3] ||
b2==ft[g]->lf[(j+2)%3])
{
a2=a2->next;
continue;
}
for( c2=0;c2<3;c2++ )
if (b2->lv[c2]==v2)
break;
if (b1->lv[(c1+1)%3]==b2->lv[(c2+1)%3] ||
b1->lv[(c1+1)%3]==b2->lv[(c2+2)%3] ||
b1->lv[(c1+2)%3]==b2->lv[(c2+1)%3] ||
b1->lv[(c1+2)%3]==b2->lv[(c2+2)%3])
break;
a2=a2->next;
}
if (a2!=0)
break;
a1=a1->next;
}
if (a1!=0)
continue;
dm=d;
f1=f;
f2=g;
i1=i;
i2=j;
}
}
delete chk;
if (dm<1e19)
return dm;
else return 0.0;
}
void object::CompressEdge(float weight,int f1,int i1, int f2,int i2)
{
int v1=ft[f1]->lv[i1]->flag,
v2=ft[f1]->lv[(i1+1)%3]->flag;
float t;
ctlist *c=new ctlist;
c->weight=weight;
c->nfv=vt[v2]->num_faces();
ASSERT(c->nfv>2);
c->nfv-=2;
vector v=(vt[v1]->pos+vt[v2]->pos)/2.0;
c->d=v-vt[v1]->pos;
c->vert1=v1;
c->vert2=v2;
c->vert3=ft[f1]->lv[(i1+2)%3]->flag;
c->vert4=ft[f2]->lv[(i2+2)%3]->flag;
c->face1=f1;
c->face2=f2;
c->face3=ft[f1]->lf[(i1+1)%3]->flag;
c->face4=ft[f1]->lf[(i1+2)%3]->flag;
c->face5=ft[f2]->lf[(i2+1)%3]->flag;
c->face6=ft[f2]->lf[(i2+2)%3]->flag;
c->i1=i1;
c->i2=i2;
c->mat1=ft[f1]->material;
c->mat2=ft[f2]->material;
vt[v1]->pos=v;
if(textcoord)
{
t = (vt[v1]->tx[0] + vt[v2]->tx[0])/(float)2.0;
c->dtx[0] = t - vt[v1]->tx[0];
vt[v1]->tx[0]=t;
t = (vt[v1]->tx[1] + vt[v2]->tx[1])/(float)2.0;
c->dtx[1] = t - vt[v1]->tx[1];
vt[v1]->tx[1]=t;
}
element *e=&elem[ft[f1]->group];
if (e->coef)
e->coef->prev=c;
c->next=e->coef;
c->prev=0;
e->coef=c;
ftlist *ff1,*ff2;
int ii1,ii2;
ff1=ft[f1]->lf[(i1+1)%3];
ff2=ft[f1]->lf[(i1+2)%3];
for( ii1=0;ii1<3;ii1++ )
if (ff1->lf[ii1]==ft[f1])
break;
for( ii2=0;ii2<3;ii2++ )
if (ff2->lf[ii2]==ft[f1])
break;
ff1->lf[ii1]=ff2;
ff2->lf[ii2]=ff1;
ff1=ft[f2]->lf[(i2+1)%3];
ff2=ft[f2]->lf[(i2+2)%3];
for( ii1=0;ii1<3;ii1++ )
if (ff1->lf[ii1]==ft[f2])
break;
for( ii2=0;ii2<3;ii2++ )
if (ff2->lf[ii2]==ft[f2])
break;
ff1->lf[ii1]=ff2;
ff2->lf[ii2]=ff1;
DelFace(&ft[f1]);
DelFace(&ft[f2]);
facelist *tmp;
if (c->nfv>0)
{
c->fv=new int[c->nfv];
tmp=vt[v2]->faces;
ii1=0;
while( tmp )
{
c->fv[ii1++]=((ftlist *)(tmp->face))->flag;
tmp=tmp->next;
}
}
change_index(v1,v2);
rebuild_normals(v1);
nrf--;
nrf--;
nrv--;
ncoef++;
e->nrf--;
e->nrf--;
e->nrv--;
e->ncoef++;
}
void object::rebuild_normals(int v1)
{
facelist *fl,*tmp;
ftlist *f;
vtlist *v;
vector n1,n2;
int n,j;
vt[v1]->normal.Null();
fl=vt[v1]->faces;
n=0;
while( fl )
{
f=(ftlist *)(fl->face);
n1=f->lv[1]->pos - f->lv[0]->pos;
n2=f->lv[2]->pos - f->lv[0]->pos;
f->normal.Cross(n1,n2);
f->normal.Normalize();
vt[v1]->normal+=f->normal;
n++;
fl=fl->next;
}
vt[v1]->normal/=(float)n;
fl=vt[v1]->faces;
while( fl )
{
f=(ftlist *)(fl->face);
for( j=0;j<3;j++ )
if (f->lv[j]->flag!=v1)
{
v=f->lv[j];
n=0;
v->normal.Null();
tmp=v->faces;
while( tmp )
{
v->normal+=((ftlist *)(tmp->face))->normal;
n++;
tmp=tmp->next;
}
v->normal/=(float)n;
}
fl=fl->next;
}
}
void object::Compress()
{
int f1,f2,i1,i2;
for( f1=0;f1flag=f1;
for( f1=0;f1flag=f1;
ncoef=0;
cur_ncoef=-1;
int e;
float d;
for( e=0;eweight;
else if (elem[e].cur_coef->next)
d=elem[e].cur_coef->next->weight;
if (d>dm)
{
dm=d;
em=e;
}
}
if (em>=0)
return AddCoef(em);
else return 0;
}
int scene::AddCoef()
{
float d,dm=0;
object *o=obj0,*om=0;
int e,em;
while(o)
{
for( e=0;enelem;e++ )
{
d=0;
if (o->elem[e].ncoef)
if (o->elem[e].cur_coef==0)
d=o->elem[e].coef->weight;
else if (o->elem[e].cur_coef->next)
d=o->elem[e].cur_coef->next->weight;
if (d>dm)
{
dm=d;
om=o;
em=e;
}
}
o=o->next;
}
if (om!=0)
return om->AddCoef(em);
else return 0;
}
int object::DelCoef()
{
int e,em=-1;
float dm=(float)1e19;
for( e=0;eweightweight;
em=e;
}
if (em>=0)
return DelCoef(em);
else return 0;
}
int scene::DelCoef()
{
float dm=(float)1e19;
object *o=obj0,*om=0;
int e,em;
while(o)
{
for( e=0;enelem;e++ )
if (o->elem[e].ncoef)
if (o->elem[e].cur_coef!=0)
if (o->elem[e].cur_coef->weightelem[e].cur_coef->weight;
om=o;
em=e;
}
o=o->next;
}
if (om!=0)
return om->DelCoef(em);
else return 0;
}
int object::AddCoef(int e)
{
if (elem[e].cur_coef==0)
if ((elem[e].cur_coef=elem[e].coef)==0)
return 0;
else ;
else
{
if (elem[e].cur_coef->next==0)
return 0;
elem[e].cur_coef=elem[e].cur_coef->next;
}
elem[e].cur_ncoef++;
cur_ncoef++;
ctlist *cur_coef=elem[e].cur_coef;
vtlist *vert=new vtlist;
vert->pos=vt[cur_coef->vert1]->pos+cur_coef->d;
vt[cur_coef->vert1]->pos-=cur_coef->d;
if(textcoord)
{
vert->tx[0]=vt[cur_coef->vert1]->tx[0]+cur_coef->dtx[0];
vert->tx[1]=vt[cur_coef->vert1]->tx[1]+cur_coef->dtx[1];
vt[cur_coef->vert1]->tx[0]-=cur_coef->dtx[0];
vt[cur_coef->vert1]->tx[1]-=cur_coef->dtx[1];
}
ftlist *f1=new ftlist,*f2=new ftlist;
f1->material=cur_coef->mat1;
f2->material=cur_coef->mat2;
f1->flag=cur_coef->face1;
f2->flag=cur_coef->face2;
vert->flag=cur_coef->vert2;
ft[cur_coef->face1]=f1;
ft[cur_coef->face2]=f2;
vt[cur_coef->vert2]=vert;
f1->lv[cur_coef->i1]=vt[cur_coef->vert1];
f1->lv[(cur_coef->i1+1)%3]=vt[cur_coef->vert2];
f1->lv[(cur_coef->i1+2)%3]=vt[cur_coef->vert3];
f2->lv[cur_coef->i2]=vt[cur_coef->vert2];
f2->lv[(cur_coef->i2+1)%3]=vt[cur_coef->vert1];
f2->lv[(cur_coef->i2+2)%3]=vt[cur_coef->vert4];
f1->lf[cur_coef->i1]=f2;
f1->lf[(cur_coef->i1+1)%3]=ft[cur_coef->face3];
f1->lf[(cur_coef->i1+2)%3]=ft[cur_coef->face4];
f1->group=ft[cur_coef->face3]->group;
f2->lf[cur_coef->i2]=f1;
f2->lf[(cur_coef->i2+1)%3]=ft[cur_coef->face5];
f2->lf[(cur_coef->i2+2)%3]=ft[cur_coef->face6];
f2->group=f1->group;
int i,j;
f1=ft[cur_coef->face3];
f2=ft[cur_coef->face4];
for( j=0;j<3;j++ )
if (f1->lf[j]==f2)
break;
f1->lf[j]=ft[cur_coef->face1];
for( j=0;j<3;j++ )
if (f2->lf[j]==f1)
break;
f2->lf[j]=ft[cur_coef->face1];
f1=ft[cur_coef->face5];
f2=ft[cur_coef->face6];
for( j=0;j<3;j++ )
if (f1->lf[j]==f2)
break;
f1->lf[j]=ft[cur_coef->face2];
for( j=0;j<3;j++ )
if (f2->lf[j]==f1)
break;
f2->lf[j]=ft[cur_coef->face2];
facelist *tmp,*tmp2;
for( i=0;infv;i++ )
{
for( j=0;j<3;j++ )
if (ft[cur_coef->fv[i]]->lv[j]==vt[cur_coef->vert1])
break;
ft[cur_coef->fv[i]]->lv[j]=vt[cur_coef->vert2];
if (vt[cur_coef->vert1]->faces->face==ft[cur_coef->fv[i]])
{
tmp=vt[cur_coef->vert1]->faces;
vt[cur_coef->vert1]->faces=tmp->next;
tmp->next=vt[cur_coef->vert2]->faces;
vt[cur_coef->vert2]->faces=tmp;
}
else
{
tmp=vt[cur_coef->vert1]->faces;
while(tmp->next->face!=ft[cur_coef->fv[i]])
tmp=tmp->next;
tmp2=tmp->next;
tmp->next=tmp->next->next;
tmp2->next=vt[cur_coef->vert2]->faces;
vt[cur_coef->vert2]->faces=tmp2;
}
}
tmp=new facelist;
tmp->face=ft[cur_coef->face1];
tmp->next=vt[cur_coef->vert3]->faces;
vt[cur_coef->vert3]->faces=tmp;
tmp=new facelist;
tmp->face=ft[cur_coef->face2];
tmp->next=vt[cur_coef->vert4]->faces;
vt[cur_coef->vert4]->faces=tmp;
tmp=new facelist;
tmp->face=ft[cur_coef->face1];
tmp->next=vt[cur_coef->vert1]->faces;
vt[cur_coef->vert1]->faces=tmp;
tmp=new facelist;
tmp->face=ft[cur_coef->face1];
tmp->next=vt[cur_coef->vert2]->faces;
vt[cur_coef->vert2]->faces=tmp;
tmp=new facelist;
tmp->face=ft[cur_coef->face2];
tmp->next=vt[cur_coef->vert1]->faces;
vt[cur_coef->vert1]->faces=tmp;
tmp=new facelist;
tmp->face=ft[cur_coef->face2];
tmp->next=vt[cur_coef->vert2]->faces;
vt[cur_coef->vert2]->faces=tmp;
rebuild_normals(cur_coef->vert1);
rebuild_normals(cur_coef->vert2);
nrf++;
nrf++;
nrv++;
elem[e].nrf++;
elem[e].nrf++;
elem[e].nrv++;
return 1;
}
int object::DelCoef(int e)
{
if(elem[e].cur_coef==0)
return 0;
ctlist *cur_coef=elem[e].cur_coef;
float t;
vector v=(vt[cur_coef->vert1]->pos+vt[cur_coef->vert2]->pos)/2.0;
vt[cur_coef->vert1]->pos=v;
if(textcoord)
{
t = (vt[cur_coef->vert1]->tx[0] + vt[cur_coef->vert2]->tx[0])/(float)2.0;
vt[cur_coef->vert1]->tx[0]=t;
t = (vt[cur_coef->vert1]->tx[1] + vt[cur_coef->vert2]->tx[1])/(float)2.0;
vt[cur_coef->vert1]->tx[1]=t;
}
ftlist *ff1,*ff2;
int ii1,ii2;
ff1=ft[cur_coef->face1]->lf[(cur_coef->i1+1)%3];
ff2=ft[cur_coef->face1]->lf[(cur_coef->i1+2)%3];
for( ii1=0;ii1<3;ii1++ )
if (ff1->lf[ii1]==ft[cur_coef->face1])
break;
for( ii2=0;ii2<3;ii2++ )
if (ff2->lf[ii2]==ft[cur_coef->face1])
break;
ff1->lf[ii1]=ff2;
ff2->lf[ii2]=ff1;
ff1=ft[cur_coef->face2]->lf[(cur_coef->i2+1)%3];
ff2=ft[cur_coef->face2]->lf[(cur_coef->i2+2)%3];
for( ii1=0;ii1<3;ii1++ )
if (ff1->lf[ii1]==ft[cur_coef->face2])
break;
for( ii2=0;ii2<3;ii2++ )
if (ff2->lf[ii2]==ft[cur_coef->face2])
break;
ff1->lf[ii1]=ff2;
ff2->lf[ii2]=ff1;
if (cur_coef->face1==elem[ft[cur_coef->face1]->group].elem ||
cur_coef->face2==elem[ft[cur_coef->face1]->group].elem)
elem[ft[cur_coef->face1]->group].elem=cur_coef->face3;
DelFace(&ft[cur_coef->face1]);
DelFace(&ft[cur_coef->face2]);
change_index(cur_coef->vert1,cur_coef->vert2);
rebuild_normals(cur_coef->vert1);
nrf--;
nrf--;
nrv--;
elem[e].nrf--;
elem[e].nrf--;
elem[e].nrv--;
elem[e].cur_coef=elem[e].cur_coef->prev;
elem[e].cur_ncoef--;
cur_ncoef--;
return 1;
}
int vtlist::num_faces()
{
int rslt=0;
facelist *t=faces;
while(t)
{
t=t->next;
rslt++;
}
return rslt;
}
bool vtlist::esta_na_borda()
{
facelist *t=faces;
ftlist *t2;
int i;
while(t)
{
t2=(ftlist *)t->face;
for(i=0;i<3;i++)
if(t2->lv[i]==this || t2->lv[(i+1)%3]==this)
if(t2->lf[i]==NULL)
return true;
t=t->next;
}
return false;
}
void object::ApagaVertNaAresta()
{
int v, v1, v2, l1, l2, l3;
ftlist *f1, *f2, *f3;
for(v=0;vflag=v;
for(v=0;vflag=v;
for( v=0;vnum_faces()==2)
{
f1=(ftlist *)(vt[v]->faces->face);
f2=(ftlist *)(vt[v]->faces->next->face);
for(l1=0;l1<3;l1++)
if(f1->lf[l1]==f2)
break;
for(l2=0;l2<3;l2++)
if(f1==f2->lf[l2])
break;
if(l1!=3)
{
v1=f1->lv[(l1+2)%3]->flag;
v2=f2->lv[(l2+2)%3]->flag;
if(EstaNaAresta(&vt[v]->pos.x, &vt[v1]->pos.x, &vt[v2]->pos.x))
{
f3=f2->lf[(l2+1)%3];
if(f3==NULL)
f3=f2->lf[(l2+2)%3];
if(f3)
{
for(l3=0;l3<3;l3++)
if(f3->lf[l3]==f2)
break;
f3->lf[l3]=f1;
f1->lf[l1]=f3;
}
else
f1->lf[l1]=NULL;
change_index(v2, v);
DelFace(&ft[f2->flag]);
juntaface(f1, v1, v2);
}
}
}
}
}
void object::juntaface(ftlist *f, int v1, int v2)
{
facelist *t1, *t2;
ftlist *t;
int i, j;
for(i=0;i<3;i++)
if(( f->lv[i]==vt[v1] && f->lv[(i+1)%3]==vt[v2] ) ||
( f->lv[i]==vt[v2] && f->lv[(i+1)%3]==vt[v1] ))
break;
t1=f->lv[i]->faces;
while(t1)
{
t2=f->lv[(i+1)%3]->faces;
while(t2)
{
t=(ftlist *)t2->face;
if(t2->face==t1->face && t2->face!=f)
{
f->lf[i]=(ftlist *)t2->face;
for(j=0;j<3;j++)
if(( t->lv[j]==f->lv[(i+1)%3] && t->lv[(j+1)%3]==f->lv[i] ) ||
( t->lv[j]==f->lv[i] && t->lv[(j+1)%3]==f->lv[(i+1)%3] ) )
break;
t->lf[j]=f;
return;
}
t2=t2->next;
}
t1=t1->next;
}
}
bool object::EstaNaAresta(float *a, float *a1, float *a2)
{
int j;
float t, p;
for(j=0;j<3;j++)
if(fabs(a1[j]-a2[j])>0.001)
break;
t=(a[j]-a1[j])/(a2[j]-a1[j]);
p=(a2[(j+1)%3]-a1[(j+1)%3])*t+a1[(j+1)%3];
if(fabs(a[(j+1)%3]-p)>0.001)
return false;
p=(a2[(j+2)%3]-a1[(j+2)%3])*t+a1[(j+2)%3];
if(fabs(a[(j+2)%3]-p)>0.001)
return false;
return true;
}
void object::compute_bbox()
{
bbox1.Vec(BIG,BIG,BIG);
bbox2.Vec(-BIG,-BIG,-BIG);
int v;
for( v=0;vpos.x>bbox2.x)
bbox2.x=vt[v]->pos.x;
if (vt[v]->pos.y>bbox2.y)
bbox2.y=vt[v]->pos.y;
if (vt[v]->pos.z>bbox2.z)
bbox2.z=vt[v]->pos.z;
if (vt[v]->pos.xpos.x;
if (vt[v]->pos.ypos.y;
if (vt[v]->pos.zpos.z;
}
}
void object::Serialize(ChunkFile & ar, bool IsStoring)
{
int i, j;
char flag;
unsigned short s,ss;
if (IsStoring)
{
for( i=0;iflag=i;
ar.Write(&vt[i]->pos,sizeof(vector));
if(textcoord)
ar.Write(vt[i]->tx,sizeof(float)*2);
}
else
{
flag=0;
ar.Write(&flag,sizeof(char));
}
ar.Write(&nf, sizeof(int));
ar.Write(&nrf, sizeof(int));
for(i=0;iflag=i;
for(i=0;i65535)
{
flag=1;
ar.Write(&flag,sizeof(char));
for(j=0;j<3;j++)
{
ar.Write(&ft[i]->lv[j]->flag, sizeof(int));
if (ft[i]->lf[j])
flag=ft[i]->lf[j]->flag+1;
else flag=0;
ar.Write(&flag, sizeof(int));
}
ar.Write(&ft[i]->group, sizeof(unsigned short));
ar.Write(&ft[i]->material,sizeof(unsigned short));
}
else
{
flag=2;
ar.Write(&flag,sizeof(char));
for(j=0;j<3;j++)
{
s=ft[i]->lv[j]->flag;
ar.Write(&s, sizeof(unsigned short));
if (ft[i]->lf[j])
s=ft[i]->lf[j]->flag+1;
else s=0;
ar.Write(&s, sizeof(unsigned short));
}
ar.Write(&ft[i]->group, sizeof(unsigned short));
ar.Write(&ft[i]->material,sizeof(unsigned short));
}
else
{
flag=0;
ar.Write(&flag,sizeof(char));
}
ar.Write(&nelem, sizeof(int));
for( j=0;jflag=i;
ar.Read(&vt[i]->pos,sizeof(vector));
if(textcoord)
ar.Read(vt[i]->tx,sizeof(float)*2);
}
else vt[i]=0;
}
ar.Read(&nf, sizeof(int));
ar.Read(&nrf, sizeof(int));
if(nf)
ft=new ftlist *[nf];
for(i=0;iflag=i;
for(j=0;j<3;j++)
{
ar.Read(&k, sizeof(int));
ft[i]->lv[j]=vt[k];
ar.Read(&l, sizeof(int));
ft[i]->lf[j]=(ftlist *)l;
facelist *f=new facelist;
f->face=ft[i];
f->next=vt[k]->faces;
vt[k]->faces=f;
}
ar.Read(&ft[i]->group,sizeof(unsigned short));
ar.Read(&ft[i]->material,sizeof(unsigned short));
}
else if (flag==2)
{
ft[i]=new ftlist;
ft[i]->flag=i;
for(j=0;j<3;j++)
{
ar.Read(&s, sizeof(unsigned short));
ft[i]->lv[j]=vt[s];
ar.Read(&ss, sizeof(unsigned short));
ft[i]->lf[j]=(ftlist *)ss;
facelist *f=new facelist;
f->face=ft[i];
f->next=vt[s]->faces;
vt[s]->faces=f;
}
ar.Read(&ft[i]->group,sizeof(unsigned short));
ar.Read(&ft[i]->material,sizeof(unsigned short));
}
else ft[i]=0;
}
ar.Read(&nelem, sizeof(int));
if (nelem)
elem=new element[nelem];
for( j=0;jlf[j])
ft[i]->lf[j]=ft[(int)(ft[i]->lf[j])-1];
compute_normals();
ncoef=0;
cur_ncoef=-1;
}
}
void object::invert_node_normal(ftlist *node)
{
node->flag=0;
void *tmp;
tmp=node->lv[0];
node->lv[0]=node->lv[1];
node->lv[1]=(vtlist *)tmp;
tmp=node->lf[1];
node->lf[1]=node->lf[2];
node->lf[2]=(ftlist *)tmp;
}
void object::invert_normal(ftlist *node)
{
int i,e=node->group,last_pos;
last_pos=elem[e].cur_ncoef;
while( AddCoef(e) );
ctlist *cur_coef=elem[e].cur_coef;
for( i=0;iflag=1;
invert_node_normal(node);
fix_node_normal(node);
compute_normals();
ncoef-=elem[e].ncoef;
cur_ncoef-=elem[e].ncoef;
elem[e].coef=0;
elem[e].ncoef=0;
for( i=0;iflag=i;
for( i=0;iflag=i;
int i1,i2;
while( cur_coef )
{
for( i1=0;i1<3;i1++ )
if (ft[cur_coef->face1]->lf[i1]==ft[cur_coef->face2])
break;
for( i2=0;i2<3;i2++ )
if (ft[cur_coef->face2]->lf[i2]==ft[cur_coef->face1])
break;
CompressEdge(cur_coef->weight,cur_coef->face1,i1,cur_coef->face2,i2);
if (cur_coef->prev==0)
{
delete cur_coef;
break;
}
cur_coef=cur_coef->prev;
}
elem[e].cur_ncoef=-1;
elem[e].cur_coef=0;
while( elem[e].cur_ncoeflf[i])
{
ftlist *f2=ft[f]->lf[i];
for( j=0;j<3;j++ )
if (f2->lf[j]==ft[f])
break;
ASSERT(j<3);
ASSERT( (f2->lv[(j+1)%3]==ft[f]->lv[i] && f2->lv[j]==ft[f]->lv[(i+1)%3]) ||
(f2->lv[j]==ft[f]->lv[i] && f2->lv[(j+1)%3]==ft[f]->lv[(i+1)%3]) );
}
}
}
for( v=0;vfaces;
while( t )
{
ftlist *face=(ftlist *)t->face;
for( j=0;j<3;j++ )
if (face->lv[j]==vt[v])
break;
ASSERT(j<3);
t=t->next;
}
}
}
void object::check_edges()
{
int f, i, k, j, l;
vtlist *v1,*v2;
for( f=0;flv[i];
v2=ft[f]->lv[(i+1)%3];
for(k=0;klv[(j+1)%3] && v2==ft[k]->lv[j])
|| (v2==ft[k]->lv[(j+1)%3] && v1==ft[k]->lv[j]))
{
l++;
ASSERT(l<3);
}
}
}
void scene::calc_uv(float &u, float &v, struct mapping *map)
{
u+=-map->u_offset-0.5f;
v+=map->v_offset+0.5f;
if(map->rotation!=0.0f)
{
float ua=u, va=v;
float s=(float)SinD(-map->rotation), c=(float)CosD(-map->rotation);
u=ua*c-va*s;
v=ua*s+va*c;
}
u=u*map->u_scale+0.5f;
v=v*map->v_scale-0.5f;
}
void ftlist::get_normal(vector *n)
{
*n=normal;
}
int VECBIGGER(float x,float y,float z)
{
if (x>y)
if (x>z)
return 0;
else return 2;
else if (y>z)
return 1;
else return 2;
}
void WHOISMINMED(float x, float y, float z, int& min,int& med)
{
if (x>y)
if (x>z)
{
min=1;
med=2;
}
else
{
min=0;
med=1;
}
else if (y>z)
{
min=0;
med=2;
}
else
{
min=0;
med=1;
}
}
int EvenCrossings(int Sides,float *gu,float *gv)
{
static int i, j,crossings;
crossings=0;
for(i=0; i=0)) || ((gv[j]<-SMALL) && (gv[i]>=0.0)))
if((gu[i]>=0.0) && (gu[j]>=0.0))
++crossings;
else
if((gu[i]>=0.0) || (gu[j]>=0.0))
if((gu[i]-gv[i]*(gu[j]-gu[i])/(gv[j]-gv[i]))>SMALL)
++crossings;
}
if((crossings%2)==0)
return 0;
else
return 1;
}
void ftlist::get_center(vector *c)
{
*c=(lv[0]->pos+lv[1]->pos+lv[2]->pos)/3;
}
void ftlist::get_bbox(boundbox *b)
{
b->min.Vec((float)1e20,(float)1e20,(float)1e20);
b->max.Vec((float)-1e20,(float)-1e20,(float)-1e20);
int i;
for( i=0;i<3;i++ )
{
if (lv[i]->pos.xmin.x)
b->min.x=lv[i]->pos.x;
if (lv[i]->pos.ymin.y)
b->min.y=lv[i]->pos.y;
if (lv[i]->pos.zmin.z)
b->min.z=lv[i]->pos.z;
if (lv[i]->pos.x>b->max.x)
b->max.x=lv[i]->pos.x;
if (lv[i]->pos.y>b->max.y)
b->max.y=lv[i]->pos.y;
if (lv[i]->pos.z>b->max.z)
b->max.z=lv[i]->pos.z;
}
}
void ftlist::compute_nuv(int tx,vector& IntPoint,vector& N,float& tx_u, float& tx_v)
{
static int min,med,a,intn;
float i[5],v[3][2],c[3][5],m[3][2],n[3];
WHOISMINMED((float)fabs(normal.x),(float)fabs(normal.y),(float)fabs(normal.z),min,med);
for( a=0;a<3;a++ )
{
v[a][0]=*((&lv[a]->pos.x)+min);
v[a][1]=*((&lv[a]->pos.x)+med);
c[a][0]=lv[a]->normal.x;
c[a][1]=lv[a]->normal.y;
c[a][2]=lv[a]->normal.z;
intn=3;
if (tx)
{
c[a][intn++]=lv[a]->tx[0];
c[a][intn++]=lv[a]->tx[1];
}
}
m[0][0]=(*((&IntPoint.x)+min))-v[0][0];
m[0][1]=(*((&IntPoint.x)+med))-v[0][1];
m[1][0]=v[2][0]-v[0][0];
m[1][1]=v[2][1]-v[0][1];
m[2][0]=v[1][0]-v[0][0];
m[2][1]=v[1][1]-v[0][1];
n[0]=m[1][0]*m[2][1]-m[1][1]*m[2][0];
n[1]=m[0][0]*m[2][1]-m[0][1]*m[2][0];
n[2]=m[0][0]*m[1][1]-m[0][1]*m[1][0];
for( a=0;a0)
return 0;
d=-VecDot(normal,lv[0]->pos);
if (x1<-SMALL||x1>SMALL)
{
dist=-(VecDot(normal,ro)+d)/x1;
ip=ro+rd*dist;
return is_inside(ip);
}
else return 0;
}
int ftlist::is_inside(vector& ip)
{
static int a,z;
static float gu[3],gv[3];
z=VECBIGGER((float)fabs(normal.x),(float)fabs(normal.y),(float)fabs(normal.z));
for( a=0;a<3;a++ )
switch( z )
{
case 0:
gv[a]= lv[a]->pos.y - ip.y;
gu[a]= lv[a]->pos.z - ip.z;
break;
case 1:
gv[a]= lv[a]->pos.x - ip.x;
gu[a]= lv[a]->pos.z - ip.z;
break;
case 2:
gu[a]= lv[a]->pos.x - ip.x;
gv[a]= lv[a]->pos.y - ip.y;
break;
}
return EvenCrossings(3,gu,gv);
}
void ftlist::compute_dudv(vector& ip,float u,float v,vector &dU, vector &dV)
{
float uv[3][2],a,b;
vector du,dv;
vector d0=lv[0]->pos-ip;
du=lv[1]->pos-lv[0]->pos;
dv=lv[2]->pos-lv[0]->pos;
uv[1][0]=lv[1]->tx[0] - lv[0]->tx[0];
uv[1][1]=lv[1]->tx[1] - lv[0]->tx[1];
uv[2][0]=lv[2]->tx[0] - lv[0]->tx[0];
uv[2][1]=lv[2]->tx[1] - lv[0]->tx[1];
float delta=uv[1][0]*uv[2][1]-uv[2][0]*uv[1][1];
uv[0][0]=u-lv[0]->tx[0]+(float)0.01;
uv[0][1]=v-lv[0]->tx[1];
a=(uv[0][0]*uv[2][1]-uv[2][0]*uv[0][1])/delta;
b=(uv[1][0]*uv[0][1]-uv[0][0]*uv[1][1])/delta;
dU=(a*du + b*dv)+d0;
dU.Normalize();
uv[0][0]=u-lv[0]->tx[0];
uv[0][1]=v-lv[0]->tx[1]+(float)0.01;
a=(uv[0][0]*uv[2][1]-uv[2][0]*uv[0][1])/delta;
b=(uv[1][0]*uv[0][1]-uv[0][0]*uv[1][1])/delta;
dV=(a*du + b*dv)+d0;
dV.Normalize();
}
void scene::SelectMaterial(material *mat,int texture)
{
glColor3ub(255,255,255);
glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,mat->ambient);
glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,mat->diffuse);
float f[4];
f[0]=mat->specular[0]*mat->shininess_strength;
f[1]=mat->specular[1]*mat->shininess_strength;
f[2]=mat->specular[2]*mat->shininess_strength;
f[3]=mat->specular[3];
glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,f);
glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS,mat->shininess*100);
f[0]=mat->diffuse[0]*mat->self_illum;
f[1]=mat->diffuse[1]*mat->self_illum;
f[2]=mat->diffuse[2]*mat->self_illum;
glMaterialfv(GL_FRONT_AND_BACK,GL_EMISSION,f);
if (texture && mat->map_texture1.piclibindx>=0 && piclib)
{
picture *p=&piclib[mat->map_texture1.piclibindx];
if (p && p->icon)
{
if (p->bytespixel==3)
glTexImage2D(GL_TEXTURE_2D,0,3,p->iconsx,p->iconsy,0,GL_RGB,GL_UNSIGNED_BYTE,p->icon);
else glTexImage2D(GL_TEXTURE_2D,0,1,p->iconsx,p->iconsy,0,GL_LUMINANCE,GL_UNSIGNED_BYTE,p->icon);
glEnable(GL_TEXTURE_2D);
return;
}
}
glTexImage2D(GL_TEXTURE_2D,0,3,0,0,0,GL_RGB,GL_UNSIGNED_BYTE,0);
glDisable(GL_TEXTURE_2D);
}