⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 flybezier.cpp

📁 是3D游戏一书中所讲的游戏引擎fly3D 包括fly3D引擎的源码及应用此引擎开发出来的游戏实例 有fly3D引擎的教程,易于step by step跟学
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include "../Fly3D.h"

float bezier_curve::distance(float *p,float *p1,float *p2)
{
	// returns distance from point p to line defined by p1,p2

	float dot=0,len1=0,len2=0;
	int i;

	// alloc two vectors
	float *v1=new float [nd];
	float *v2=new float [nd];
	
	// compute length from (p1,p) and (p1,p2)
	for( i=0;i<nd;i++ )
	{
		v1[i]= p[i]-p1[i];
		v2[i]=p2[i]-p1[i];
		len1+=v1[i]*v1[i];
		len2+=v2[i]*v2[i];
	}
	len1=(float)sqrt(len1);
	len2=(float)sqrt(len2);
	
	// normalize 
	if (len1>0)
		for( i=0;i<nd;i++ )
			v1[i]/=len1;
	if (len2>0)
		for( i=0;i<nd;i++ )
			v2[i]/=len2;
	
	// compute dot product
	for( i=0;i<nd;i++ )
		dot+=v1[i]*v2[i];

	// free vectors
	delete v1; 
	delete v2;

	// return distance
	return (float)sqrt(len1*len1*(1.0f-dot*dot));
}

int bezier_curve::adaptative_subdiv(float maxerror,float *points,int maxpoints)
{
	if (maxpoints<2) return 0;

	int npoints,i,j;
	float tmp;

	// start points list with two points (the curve edges)
	points[0]=0.0f;
	points[1]=1.0f;
	npoints=2;

	// subdiv curve recursevily
	subdiv(0,1,&p[0],&p[nd*(np-1)],points,npoints,maxerror,maxpoints);

	// sort points
	for( i=1;i<npoints;i++ )
		for( j=i+1;j<npoints;j++ )
			if (points[j]<points[i])
			{
				tmp=points[i];
				points[i]=points[j];
				points[j]=tmp;
			}

	// sort number of points
	return npoints;
}

void bezier_curve::subdiv(float u1,float u2,float *p1,float *p2,float *points,int& npoints,float maxerror,int maxpoints)
{
	// if points list is not full
	if (npoints<maxpoints)
	{
	// alloc a new point
	float *p=new float[nd];
	
	// compute segment midpoint coordinate
	float u=(u1+u2)*0.5f;

	// evaluate curve at the segment midpoint
	evaluate(u,p);

	// if error is bigger then maxerror
	if (distance(p,p1,p2)>maxerror)
		{
		// add point to points list
		points[npoints++]=u;
		// subdiv each segment recursevily
		subdiv(u1,u,p1,p,points,npoints,maxerror,maxpoints);
		subdiv(u,u2,p,p2,points,npoints,maxerror,maxpoints);
		}
	
	// delete allocated point
	delete p;
	}
}

void bezier_curve::reset()
{
	if (p) 
		delete p;
	p=0;
	ns=0;
	np=0;
}

void bezier_curve::set_dim(int ndim)
{
	reset();
	nd=ndim;
}

void bezier_curve::add_point(float *f)
{
	// adds a new point to the curve
	// f must point to nd floats

	if (nd==0) return;
    float *t=new float[(np+1)*nd];
    if (p!=0)
        {
         memcpy(t,p,sizeof(float)*np*nd);
		 delete p;
        }
    p=t;
	memcpy(&p[np*nd],f,sizeof(float)*nd);
	np++;
    if (((np-4)%3)==0 && np>1)
       ns++;
}

void bezier_curve::evaluate_tangent(float u,float *f)
{	
	// evaluate the curve tangent at position u
	// f must point to nd floats

	if (p==0) return;

	static float B[4];
	float u1,u2;
	int s,a,b,c;

	if (u==1.0f)
		s=np-4;
	else s=(int)(u*(np-1))/3*3;
	u1=(u-(float)s/(np-1))*ns;

	u2=u1*u1;
	B[0] =-3.0f +  6.0f*u1 - 3.0f*u2;
	B[1] = 3.0f - 12.0f*u1 + 9.0f*u2;
	B[2] = 6.0f*u1 - 9.0f*u2;
	B[3] = 3.0f*u2;

	memset(f,0,sizeof(float)*nd);

	c=s*nd;
	for( a=0;a<4;a++ )
		for( b=0;b<nd;b++ )
			f[b]+=p[c++]*B[a];
}

void bezier_curve::evaluate(float u,float *f)
{
	// evaluate the curve point at position u
	// f must point to nd floats

	if (p==0) return;

	static float B[4];
	float u1,u2;
	int s,a,b,c;

	if (u==1.0f)
		s=np-4;
	else s=(int)(u*(np-1))/3*3;
	u1=(u-(float)s/(np-1))*ns;

	u2=1.0f-u1;
	B[0]=u2*u2*u2;
	B[1]=3.0f*u1*u2*u2;
	B[2]=3.0f*u1*u1*u2;
	B[3]=u1*u1*u1;

	memset(f,0,sizeof(float)*nd);

	c=s*nd;
	for( a=0;a<4;a++ )
		for( b=0;b<nd;b++ )
			f[b]+=p[c++]*B[a];
}

int bezier_curve::load_bez(char *file)
{
	// loads the curve from a .bez text file

	fly_pak fp;
	if (!fp.open(file))
		return 0;

	reset();
	int i,j,n,d;
	float *f;
	
	pivot.x=fp.get_float();
	pivot.y=fp.get_float();
	pivot.z=fp.get_float();
	d=fp.get_int();
	n=fp.get_int();
	set_dim(d);
	f=new float[d];
	for( i=0;i<n;i++ )
		{
		for( j=0;j<d;j++ )
			f[j]=fp.get_float();
		add_point(f);
		}
	delete f;
	fp.close();
	return 1;
}

float bezier_curve::length()
{
	if (ns==0 || nd==0) return 0;

	int i,j=ns*8,k,vv=1;
	float *v[2],len=0.0f,f;
	v[0]=new float[nd];
	v[1]=new float[nd];
	evaluate(0.0f,v[0]);
	for( i=1;i<j;i++ )
	{
		evaluate((float)i/(j-1),v[vv]);
		f=0.0f;
		for( k=0;k<nd;k++ )
			f+=(v[0][k]-v[1][k])*(v[0][k]-v[1][k]);
		len+=(float)sqrt(f);
		vv=!vv;
	}

	delete v[0];
	delete v[1];

	return len;
}

void bezier_patch::build_loft(bezier_curve *shape,bezier_curve *path,int texture,int lightmap,float tileu,float tilev)
{
	reset();
	if (shape && path && shape->nd==3 && path->nd==3)
	{
	mode=4;
	texpic=texture;
	lm=lightmap;
	npu=shape->np;
	npv=path->np;
	np=npu*npv;
	nsu=shape->ns;
	nsv=path->ns;
	p=new vector[np];
	t=new vector[np];
	vector v;
	local_system ls;
	int i,j,k=0;
	ls.align_z(vector(0,0,1));
	for( j=0;j<npv;j++ )
		{
		path->evaluate_tangent((float)j/(npv-1),&v.x);
		v.normalize();
		ls.rotate(ls.Z,v);
		v=*((vector *)&path->p[j*3]);
		for( i=0;i<npu;i++ )
			{
			p[k]=v+(*((vector *)&shape->p[i*3])*ls.mat);
			t[k].x=(float)i/(npu-1)*tileu;
			t[k].y=(float)j/(npv-1)*tilev;
			t[k].z=(float)i/(npu-1);
			t[k].w=(float)j/(npv-1);
			k++;
			}
		}
	}
}

void bezier_patch::evaluate(int evaltype,float u,float v,vector *dest)
{
	if (p==0 || t==0) 
		return;

	static float Bu[4],Bv[4],Bdu[4],Bdv[4];
	float u1,u2,v1,v2,f;
	int i,j,k,su,sv;

	vector point(0,0,0);
	vector textcoord(0,0,0,0);
	vector du(0,0,0),dv(0,0,0);

	switch(mode)
	{
	case 3:
		if (FP_BITS(u)==FP_ONE_BITS)
			su=npu-3;
		else su=(int)(u*(npu-1))/2*2;
		u1=(u-(float)su/(npu-1))*nsu;

		if (FP_BITS(v)==FP_ONE_BITS)
			sv=npv-3;
		else sv=(int)(v*(npv-1))/2*2;
		v1=(v-(float)sv/(npv-1))*nsv;

		u2=1.0f-u1;
		Bu[0]=u2*u2;
		Bu[1]=2.0f*u1*u2;
		Bu[2]=u1*u1;

		v2=1.0f-v1;
		Bv[0]=v2*v2;
		Bv[1]=2.0f*v1*v2;
		Bv[2]=v1*v1;

		if (evaltype&PATCH_EVAL_NORMAL)
			{
			Bdu[0]= 2.0f*u1-2.0f;
			Bdu[1]= 2.0f-4.0f*u1;
			Bdu[2]= 2.0f*u1;

			Bdv[0]= 2.0f*v1-2.0f;
			Bdv[1]= 2.0f-4.0f*v1;
			Bdv[2]= 2.0f*v1;
			}
		break;
	case 4:
		if (FP_BITS(u)==FP_ONE_BITS)
			su=npu-4;
		else su=(int)(u*(npu-1))/3*3;
		u1=(u-(float)su/(npu-1))*nsu;

		if (FP_BITS(v)==FP_ONE_BITS)
			sv=npv-4;
		else sv=(int)(v*(npv-1))/3*3;
		v1=(v-(float)sv/(npv-1))*nsv;

		u2=1.0f-u1;
		Bu[0]=u2*u2*u2;
		Bu[1]=3.0f*u1*u2*u2;
		Bu[2]=3.0f*u1*u1*u2;
		Bu[3]=u1*u1*u1;

		v2=1.0f-v1;
		Bv[0]=v2*v2*v2;
		Bv[1]=3.0f*v1*v2*v2;
		Bv[2]=3.0f*v1*v1*v2;
		Bv[3]=v1*v1*v1;

		if (evaltype&PATCH_EVAL_NORMAL)
			{
			u2=u1*u1;
			Bdu[0]=-3.0f +  6.0f*u1 - 3.0f*u2;
			Bdu[1]= 3.0f - 12.0f*u1 + 9.0f*u2;
			Bdu[2]= 6.0f*u1 - 9.0f*u2;
			Bdu[3]= 3.0f*u2;

			v2=v1*v1;
			Bdv[0]=-3.0f +  6.0f*v1 - 3.0f*v2;
			Bdv[1]= 3.0f - 12.0f*v1 + 9.0f*v2;
			Bdv[2]= 6.0f*v1 - 9.0f*v2;
			Bdv[3]= 3.0f*v2;
			}
	}

	for( i=0;i<mode;i++ )
		for( j=0;j<mode;j++ )
		{
			k=(sv+j)*npu+su+i;
			f=Bu[i]*Bv[j];
			if (evaltype&PATCH_EVAL_POINT)
				{
				point.x+=f*p[k].x;
				point.y+=f*p[k].y;
				point.z+=f*p[k].z;
				}
			if (evaltype&PATCH_EVAL_TEXTCOORD)
				{
				textcoord.x+=f*t[k].x;
				textcoord.y+=f*t[k].y;
				textcoord.z+=f*t[k].z;
				textcoord.w+=f*t[k].w;
				}
			if (evaltype&PATCH_EVAL_NORMAL)
				{
				du+=p[k]*(Bdu[i]*Bv[j]);
				dv+=p[k]*(Bu[i]*Bdv[j]);
				}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -