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

📄 flybezier.cpp

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

	if (evaltype&PATCH_EVAL_POINT)
		*(dest++)=point;
	if (evaltype&PATCH_EVAL_TEXTCOORD)
		*(dest++)=textcoord;
	if (evaltype&PATCH_EVAL_NORMAL)
		{
		dest->cross(dv,du);
		dest->normalize();
		}
}

void bezier_patch::reset()
{
	if (p) 
		delete p;
	p=0;
	if (t)
		delete t;
	t=0;
	if (surf)
		delete surf;
	surf=0;
	np=npu=npv=nsu=nsv=0;
	mode=0;
	levelu=0;
	levelv=0;
	nvertu=0;
	nvertv=0;
}

int bezier_patch::load_pch(char *file)
{
	reset();

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

	mode=3;

	char texture[256];
	fp.get_string(texture);
	texpic=flyengine->get_picture(texture);

	int lm_pic=fp.get_int();
	int lm_offsetx=fp.get_int();
	int lm_offsety=fp.get_int();
	int lm_sizex=fp.get_int();
	int lm_sizey=fp.get_int();
	lm=-1;
	if (lm_pic<flyengine->nlmpic)
		{
		flyengine->lm[flyengine->nlm]=new light_map(-1,lm_pic,lm_offsetx,lm_offsety,lm_sizex,lm_sizey,3);
		flyengine->fm[flyengine->nlm]=new light_map(-1,lm_pic,lm_offsetx,lm_offsety,lm_sizex,lm_sizey,4);
		lm=flyengine->nlm++;
		}

	npu=fp.get_int();
	npv=fp.get_int();

	pivot.x=fp.get_float();
	pivot.y=fp.get_float();
	pivot.z=fp.get_float();

	np=npu*npv;
	nsu=(npu-1)/2;
	nsv=(npv-1)/2;

	p=new vector[np];
	t=new vector[np];
	
	int i;
	for( i=0;i<np;i++ )
	{
		p[i].x=fp.get_float();
		p[i].y=fp.get_float();
		p[i].z=fp.get_float();

		t[i].x=fp.get_float();
		t[i].y=fp.get_float();
		t[i].z=fp.get_float();
		t[i].w=fp.get_float();
	}

	fp.close();
	return 1;
}

int find_subdiv_level(vector v0,vector v1,vector v2)
{
    int level;
    vector a, b, dist;
	
	float factor=flyengine->curveerr*flyengine->curveerr;

    for (level=0;level<8;level++)
    {
	a=(v0+v1)*0.5f;
	b=(v1+v2)*0.5f;
	v2=(a+b)*0.5f;

	dist=v2-v1;
	if (vec_dot(dist,dist)<factor)
	    break;
	v1=a;
    }

    return level;
}



void bezier_patch::build_surface()
{
	if (mode!=3 || p==0 || t==0)
		return;
	int i,j,k,a;
	vector normal;

	levelu=0;
	levelv=0;
	k=0;
	for( j=0;j<=nsv;j++,k+=npu-1 )
	for( i=0;i<=nsu;i++,k+=2 )
	{
		if (i<nsu)
		{
			a=find_subdiv_level(p[k],p[k+1],p[k+2]);
			if (a>levelu)
				levelu=a;
		}
		if (j<nsv)
		{
			a=find_subdiv_level(p[k],p[k+npu],p[k+2*npu]);
			if (a>levelv)
				levelv=a;
		}
	}

	nvertu=(1<<levelu)*nsu+1;
	nvertv=(1<<levelv)*nsv+1;
	if (nvertu<2) nvertu=2;
	if (nvertv<2) nvertv=2;

	if (surf) delete surf;
	surf=new vector[nvertu*nvertv*2];

	k=0;
	for( j=0;j<nvertv;j++ )
		for( i=0;i<nvertu;i++,k+=2 )
			evaluate(PATCH_EVAL_POINT|PATCH_EVAL_TEXTCOORD,
				(float)i/(nvertu-1),(float)j/(nvertv-1),&surf[k]);
}

void bezier_patch::illuminate(vector& p,float rad,vector& color,int shadows)
{
	if (lm==-1)
		return;

	int i,j,k;
	float dist,u,v;
	vector point,dir;

	// get lightmap applied to patch
	light_map *l=flyengine->lm[lm];
	unsigned char *uc;

	rad*=rad;
	// for each lightmap pixel in y
	for( j=0;j<l->sizey;j++ )
	{
		uc=&l->bmp[j*l->bytesx];
		v=(j+0.5f)/l->sizey;
		// for each lightmap pixel in x
		for( i=0;i<l->sizex;i++ )
		{
		u=(i+0.5f)/l->sizex;

		// get lightmap pixel position in the patch surface
		evaluate(PATCH_EVAL_POINT,u,v,&point);
		
		// check if point is inside light radius
		dir=p-point;
		dist=vec_dot(dir,dir);
		if (dist>rad)
			uc+=3;
		else 
			{
			// compute lighting factor based on light radius and pixel distance
			dist=(1.0f-dist/rad)*255.0f;

			// apply colors to lightmap
			k=(int)(color.x*dist)+(int)(*uc);
			*(uc++)=k>255?255:k;

			k=(int)(color.y*dist)+(int)(*uc);
			*(uc++)=k>255?255:k;

			k=(int)(color.z*dist)+(int)(*uc);
			*(uc++)=k>255?255:k;
			}
		}
	}
	
	l->lastupdate=flyengine->cur_step;
}

void bezier_patch::draw(int nleveldrop)
{
	if (surf==0)
		return;

	int i,j,k,l,mapcount=0;
	float *f1,*f2;
	int dropu,dropv,numstrips;

	if (levelu>=nleveldrop)
		dropu=nleveldrop;
	else dropu=levelu;
	if (levelv>=nleveldrop)
		dropv=nleveldrop;
	else dropv=levelv;
	numstrips=(1<<(levelv-dropv))*nsv;
	dropu=(1<<dropu);
	dropv=(1<<dropv);
	k=dropu*8;
	l=dropv*nvertu*2;

	glColor3ub(255,255,255);

	if (flyengine->multitexture && ntextureunits>1 && flyengine->nlm)
		{
		tc->use(texpic);
		if (lm!=-1)
			tc->use(flyengine->lm[lm]->pic+flyengine->lmbase,1);
		for( j=0;j<numstrips;j++ )
			{
			f1=(float * )&surf[j*l]; f2=f1+(l<<2);
			glBegin(GL_TRIANGLE_STRIP);
			for( i=0;i<nvertu;i+=dropu,f1+=k,f2+=k)
				{
				glMultiTexCoord2fvARB(GL_TEXTURE0_ARB,f2+4);
				glMultiTexCoord2fvARB(GL_TEXTURE1_ARB,f2+6);
				glVertex3fv(f2);
				glMultiTexCoord2fvARB(GL_TEXTURE0_ARB,f1+4);
				glMultiTexCoord2fvARB(GL_TEXTURE1_ARB,f1+6);
				glVertex3fv(f1);
				}
			glEnd();
			}
		tc->use(-1,1);
		tc->use(-1,0);
		mapcount+=2;
		}
	else
	{
	if (flyengine->mapmode&MAPPING_TEXTURE)
		{
		tc->use(texpic);
		for( j=0;j<numstrips;j++ )
			{
			f1=(float * )&surf[j*l]; f2=f1+(l<<2);
			glBegin(GL_TRIANGLE_STRIP);
			for( i=0;i<nvertu;i+=dropu,f1+=k,f2+=k)
				{
				glTexCoord2fv(f2+4);
				glVertex3fv(f2);
				glTexCoord2fv(f1+4);
				glVertex3fv(f1);
				}
			glEnd();
			}
		mapcount++;
		}

	if (flyengine->mapmode&MAPPING_DETAIL &&
		flyengine->detailpic!=-1)
		{
		if (mapcount)
			{
			glBlendFunc(GL_ZERO,GL_SRC_COLOR);
			glDepthMask(GL_FALSE);
			glDepthFunc(GL_EQUAL);
			}
		tc->use(flyengine->detailpic);
		for( j=0;j<numstrips;j++ )
			{
			f1=(float * )&surf[j*l]; f2=f1+(l<<2);
			glBegin(GL_TRIANGLE_STRIP);
			for( i=0;i<nvertu;i+=dropu,f1+=k,f2+=k)
				{
				glTexCoord2f(f2[4]*flyengine->detailtile,f2[5]*flyengine->detailtile);
				glVertex3fv(f2);
				glTexCoord2f(f1[4]*flyengine->detailtile,f1[5]*flyengine->detailtile);
				glVertex3fv(f1);
				}
			glEnd();
			}
		mapcount++;
		}

	if (flyengine->mapmode&MAPPING_LIGHTMAP &&
		flyengine->nlm!=0)
		{
		if (mapcount)
			{
			glBlendFunc(GL_ZERO,GL_SRC_COLOR);
			glDepthMask(GL_FALSE);
			glDepthFunc(GL_EQUAL);
			}
		tc->use(flyengine->lm[lm]->pic+flyengine->lmbase);
		for( j=0;j<numstrips;j++ )
			{
			f1=(float * )&surf[j*l]; f2=f1+(l<<2);
			glBegin(GL_TRIANGLE_STRIP);
			for( i=0;i<nvertu;i+=dropu,f1+=k,f2+=k)
				{
				glTexCoord2fv(f2+6);
				glVertex3fv(f2);
				glTexCoord2fv(f1+6);
				glVertex3fv(f1);
				}
			glEnd();
			}
		mapcount++;
		}
	}

	if (flyengine->mapmode&MAPPING_FOGMAP)
	if (flyengine->nlm!=0)
		{
		if (mapcount)
			{
			glDepthMask(GL_FALSE);
			glDepthFunc(GL_EQUAL);
			glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
			}
		tc->use(flyengine->lm[lm]->pic+flyengine->fmbase);
		for( j=0;j<numstrips;j++ )
			{
			f1=(float * )&surf[j*l]; f2=f1+(l<<2);
			glBegin(GL_TRIANGLE_STRIP);
			for( i=0;i<nvertu;i+=dropu,f1+=k,f2+=k)
				{
				glTexCoord2fv(f2+6);
				glVertex3fv(f2);
				glTexCoord2fv(f1+6);
				glVertex3fv(f1);
				}
			glEnd();
			}
		mapcount++;
		}

	glDepthMask(GL_TRUE);
	glDepthFunc(GL_LESS);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}

mesh *bezier_patch::build_mesh()
{
	int i,j,k;
	
	mesh *m=new mesh;
	
	m->nv=nvertu*nvertv;
	m->vert=new vector[m->nv];
	k=0;
	for( i=0;i<m->nv;i++,k+=2 )
		m->vert[i]=surf[k];

	m->nf=(nvertu-1)*(nvertv-1)*2;
	m->localfaces=new face[m->nf];
	m->faces=new face *[m->nf];
	k=0;
	for( j=0;j<nvertv-1;j++ )
	for( i=0;i<nvertu-1;i++ )
	{
		m->localfaces[k].color.vec(1,1,1,1);
		m->localfaces[k].vert[0]=&m->vert[j*nvertu+i];
		m->localfaces[k].vert[1]=&m->vert[j*nvertu+i+1];
		m->localfaces[k].vert[2]=&m->vert[(j+1)*nvertu+i+1];
		m->faces[k]=&m->localfaces[k];
		k++;
		m->localfaces[k].color.vec(1,1,1,1);
		m->localfaces[k].vert[0]=&m->vert[j*nvertu+i];
		m->localfaces[k].vert[1]=&m->vert[(j+1)*nvertu+i+1];
		m->localfaces[k].vert[2]=&m->vert[(j+1)*nvertu+i];
		m->faces[k]=&m->localfaces[k];
		k++;
	}

	m->compute_normals(MESH_FACENORM|MESH_VERTNORM|MESH_BBOX);

	return m;
}

⌨️ 快捷键说明

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