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); 
}