projectilehandler.cpp

来自「这是整套横扫千军3D版游戏的源码」· C++ 代码 · 共 881 行 · 第 1/2 页

CPP
881
字号

			numFlyingPieces += fpl->size();

			for(std::list<FlyingPiece*>::iterator pi=fpl->begin();pi!=fpl->end();++pi){
				CMatrix44f m;
				m.Rotate((*pi)->rot,(*pi)->rotAxis);
				float3 interPos=(*pi)->pos+(*pi)->speed*gu->timeOffset;

				SS3OVertex * verts = (*pi)->verts;

				float3 tp, tn;

				for (int i = 0; i < 4; i++){
					tp=m.Mul(verts[i].pos);
					tn=m.Mul(verts[i].normal);
					tp+=interPos;
					va->AddVertexTN(tp,verts[i].textureX,verts[i].textureY,tn);
				}
			}
			drawnPieces+=va->drawIndex/32;
			va->DrawArrayTN(GL_QUADS);
		}
	}

	unitDrawer->CleanUpS3ODrawing();

	/*
	 * TODO Nearly cut here.
	 */

	unitDrawer->SetupForUnitDrawing();
	Projectile_List::iterator psi;
	distlist.clear();
	for(psi=ps.begin();psi != ps.end();++psi){
		if(camera->InView((*psi)->pos,(*psi)->drawRadius) && (gu->spectatingFullView || loshandler->InLos(*psi,gu->myAllyTeam) || ((*psi)->owner && gs->Ally((*psi)->owner->allyteam,gu->myAllyTeam)))){
			if(drawReflection){
				if((*psi)->pos.y < -(*psi)->drawRadius)
					continue;
				float dif=(*psi)->pos.y-camera->pos.y;
				float3 zeroPos=camera->pos*((*psi)->pos.y/dif) + (*psi)->pos*(-camera->pos.y/dif);
				if(ground->GetApproximateHeight(zeroPos.x,zeroPos.z)>3+0.5f*(*psi)->drawRadius)
					continue;
			}
			if(drawRefraction && (*psi)->pos.y>(*psi)->drawRadius)
				continue;
			if((*psi)->s3domodel){
				if((*psi)->s3domodel->textureType){
					unitDrawer->QueS3ODraw(*psi,(*psi)->s3domodel->textureType);
				} else {
					(*psi)->DrawUnitPart();
				}
			}
			struct projdist tmp;
			tmp.proj=*psi;
			tmp.dist=(*psi)->pos.dot(camera->forward);
			distlist.push_back(tmp);
		}
	}
	unitDrawer->CleanUpUnitDrawing();
	unitDrawer->DrawQuedS3O();

	sort(distlist.begin(), distlist.end(), CompareProjDist);

	glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
	glEnable(GL_TEXTURE_2D);
	textureAtlas->BindTexture();
	glEnable(GL_BLEND);
	glDepthMask(0);
	glColor4f(1,1,1,0.2f);
	glAlphaFunc(GL_GREATER,0.0f);
	glEnable(GL_ALPHA_TEST);
//	glFogfv(GL_FOG_COLOR,FogLand);
	glDisable(GL_FOG);

	currentParticles=0;
	CProjectile::inArray=false;
	CProjectile::va=GetVertexArray();
	CProjectile::va->Initialize();
	for(int a=0;a<distlist.size();a++){
		distlist.at(a).proj->Draw();
	}
	if(CProjectile::inArray)
		CProjectile::DrawArray();
	glDisable(GL_TEXTURE_2D);
	glDepthMask(1);
	currentParticles=(int)(ps.size()*0.8f+currentParticles*0.2f);
	currentParticles+=(int)(0.2f*drawnPieces+0.3f*numFlyingPieces);
	particleSaturation=(float)currentParticles/(float)maxParticles;
//	glFogfv(GL_FOG_COLOR,FogLand);
}

void CProjectileHandler::DrawShadowPass(void)
{
	distlist.clear();
	Projectile_List::iterator psi;
	glBindProgramARB( GL_VERTEX_PROGRAM_ARB, projectileShadowVP );
	glEnable( GL_VERTEX_PROGRAM_ARB );
	glDisable(GL_TEXTURE_2D);
	for(psi=ps.begin();psi != ps.end();++psi){
		if((loshandler->InLos(*psi,gu->myAllyTeam) || gu->spectatingFullView ||
		   ((*psi)->owner && gs->Ally((*psi)->owner->allyteam,gu->myAllyTeam)))){
			if((*psi)->s3domodel)
				(*psi)->DrawUnitPart();
			if((*psi)->castShadow){
				struct projdist tmp;
				tmp.proj = *psi;
				distlist.push_back(tmp);
			}
		}
	}

	glEnable(GL_TEXTURE_2D);
	textureAtlas->BindTexture();
	glColor4f(1,1,1,1);
	glAlphaFunc(GL_GREATER,0.3f);
	glEnable(GL_ALPHA_TEST);
	glShadeModel(GL_SMOOTH);

	CProjectile::inArray=false;
	CProjectile::va=GetVertexArray();
	CProjectile::va->Initialize();
	for(int b=0;b<distlist.size();b++){
		distlist.at(b).proj->Draw();
	}
	if(CProjectile::inArray)
		CProjectile::DrawArray();

	glShadeModel(GL_FLAT);
	glDisable(GL_ALPHA_TEST);
	glDisable(GL_TEXTURE_2D);
	glDisable( GL_VERTEX_PROGRAM_ARB );
}

void CProjectileHandler::AddProjectile(CProjectile* p)
{
	ps.push_back(p);
//	toBeAddedProjectile.push(p);
}

void CProjectileHandler::CheckUnitCol()
{
	Projectile_List::iterator psi;

	CUnit* tempUnits[MAX_UNITS];
	CFeature* tempFeatures[MAX_UNITS];

	for(psi=ps.begin();psi != ps.end();++psi){
		CProjectile* p=(*psi);
		if(p->checkCol && !p->deleteMe){
			float speedf=p->speed.Length();

			CUnit** endUnit = tempUnits;
			CFeature** endFeature = tempFeatures;

			qf->GetUnitsAndFeaturesExact(p->pos, p->radius+speedf, endUnit, endFeature);

			for(CUnit** ui=tempUnits;ui!=endUnit;++ui){
				CUnit* unit=*ui;
				if(p->owner == unit || ((p->collisionFlags&COLLISION_NOFRIENDLY) && p->owner && (unit->allyteam==p->owner->allyteam)) )
					continue;

				float ispeedf=1.0f/speedf;
				float3 normSpeed=p->speed*ispeedf;

				float totalRadius=unit->radius+p->radius;
				float3 dif(unit->midPos-p->pos);
				float closeTime=dif.dot(normSpeed)*ispeedf;
				if(closeTime<0)
					closeTime=0;
				if(closeTime>1)
					closeTime=1;
				float3 closeVect=dif-(p->speed*closeTime);
				if(closeVect.SqLength() < totalRadius*totalRadius){

					if(unit->isMarkedOnBlockingMap && unit->physicalState != CSolidObject::Flying){
						float3 closePos(p->pos+p->speed*closeTime);
						int square=(int)max(0.0f,min((float)(gs->mapSquares-1),closePos.x*(1.0f/8.0f)+int(closePos.z*(1.0f/8.0f))*gs->mapx));
						if(readmap->groundBlockingObjectMap[square]!=unit)
							continue;
					}
					//adjust projectile position so explosion happens at the correct position
					p->pos = p->pos + p->speed*closeTime;
					p->Collision(*ui);
					break;
				}
				float diflength = dif.Length();
				float closesqlength = closeVect.SqLength();
				assert(! ((!(closesqlength < totalRadius*totalRadius)) && (diflength<totalRadius)));
			}

			if(!(p->collisionFlags&COLLISION_NOFEATURE))
			{
				for(CFeature** fi=tempFeatures;fi!=endFeature;++fi){
					if(!(*fi)->blocking)
						continue;
					float ispeedf=1.0f/speedf;
					float3 normSpeed=p->speed*ispeedf;
					float totalRadius=(*fi)->radius+p->radius;
					float3 dif=(*fi)->midPos-p->pos;
					float closeTime=dif.dot(normSpeed)/speedf;
					if(closeTime<0)
						closeTime=0;
					if(closeTime>1)
						closeTime=1;
					float3 closeVect=dif-(p->speed*closeTime);
					if(dif.SqLength() < totalRadius*totalRadius){
						if((*fi)->isMarkedOnBlockingMap){
							float3 closePos(p->pos+p->speed*closeTime);
							int square=(int)max(0.0f,min((float)(gs->mapSquares-1),closePos.x*(1.0f/8.0f)+int(closePos.z*(1.0f/8.0f))*gs->mapx));
							if(readmap->groundBlockingObjectMap[square]!=(*fi))
								continue;
						}
						p->Collision(*fi);
						break;
					}
				}
			}
		}
	}
}

void CProjectileHandler::AddGroundFlash(CGroundFlash* flash)
{
	groundFlashes.push_back(flash);
}


void CProjectileHandler::DrawGroundFlashes(void)
{
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA,GL_ONE);
	glActiveTextureARB(GL_TEXTURE0_ARB);
//	glBindTexture(GL_TEXTURE_2D, CGroundFlash::texture);
	groundFXAtlas->BindTexture();
	glEnable(GL_TEXTURE_2D);
	glDepthMask(0);
	glPolygonOffset(-20,-1000);
	glEnable(GL_POLYGON_OFFSET_FILL);
	glFogfv(GL_FOG_COLOR,FogBlack);

	CGroundFlash::va=GetVertexArray();
	CGroundFlash::va->Initialize();

	std::vector<CGroundFlash*>::iterator gfi;
	for(gfi=groundFlashes.begin();gfi!=groundFlashes.end();++gfi){
		if ((*gfi)->alwaysVisible || gu->spectatingFullView ||
		    loshandler->InAirLos((*gfi)->pos,gu->myAllyTeam))
			(*gfi)->Draw();
	}
	CGroundFlash::va->DrawArrayTC(GL_QUADS);

	glFogfv(GL_FOG_COLOR,FogLand);
	glDepthMask(1);
	glDisable(GL_POLYGON_OFFSET_FILL);
	glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
	glDisable(GL_BLEND);
}

void CProjectileHandler::ConvertTex(unsigned char tex[512][512][4], int startx, int starty, int endx, int endy, float absorb)
{
	for(int y=starty;y<endy;++y){
		for(int x=startx;x<endx;++x){
			float alpha=tex[y][x][3];
			float mul=alpha/255.0f;
			tex[y][x][0]=(unsigned char)(mul * (float)tex[y][x][0]);
			tex[y][x][1]=(unsigned char)(mul * (float)tex[y][x][1]);
			tex[y][x][2]=(unsigned char)(mul * (float)tex[y][x][2]);
		}
	}
}


void CProjectileHandler::AddFlyingPiece(float3 pos,float3 speed,S3DO* object,S3DOPrimitive* piece)
{
	FlyingPiece* fp=new FlyingPiece;
	fp->pos=pos;
	fp->speed=speed;
	fp->prim=piece;
	fp->object=object;
	fp->verts=NULL;

	fp->rotAxis=gu->usRandVector();
	fp->rotAxis.Normalize();
	fp->rotSpeed=gu->usRandFloat()*0.1f;
	fp->rot=0;

	flying3doPieces->push_back(fp);
}

void CProjectileHandler::AddFlyingPiece(int textureType, int team, float3 pos, float3 speed, SS3OVertex * verts){
	FlyingPiece_List * pieceList = NULL;

	while(flyings3oPieces.size()<=textureType)
		flyings3oPieces.push_back(std::vector<FlyingPiece_List*>());

	while(flyings3oPieces[textureType].size()<=team){
		//logOutput.Print("Creating piece list %d %d.", textureType, flyings3oPieces[textureType].size());

		FlyingPiece_List * fpl = SAFE_NEW FlyingPiece_List;
		flyings3oPieces[textureType].push_back(fpl);
		flyingPieces.push_back(fpl);
	}

	pieceList=flyings3oPieces[textureType][team];

	FlyingPiece* fp=new FlyingPiece;
	fp->pos=pos;
	fp->speed=speed;
	fp->prim=NULL;
	fp->object=NULL;
	fp->verts=verts;

	/* Duplicated with AddFlyingPiece. */
	fp->rotAxis=gu->usRandVector();
	fp->rotAxis.Normalize();
	fp->rotSpeed=gu->usRandFloat()*0.1f;
	fp->rot=0;

	pieceList->push_back(fp);
}

void CProjectileHandler::UpdateTextures()
{
	if(numPerlinProjectiles && drawPerlinTex)
		UpdatePerlin();
/*
	if(gs->frameNum==300){
		logOutput.Print("Saving tex");
		perlinFB->select();
		unsigned char* buf=SAFE_NEW unsigned char[512*512*4];
		glReadPixels(0,0,512,512,GL_RGBA,GL_UNSIGNED_BYTE,buf);
		CBitmap b(buf,512,512);
		b.ReverseYAxis();
		b.Save("proj2.tga");
		delete[] buf;
		perlinFB->deselect();
	}*/
}

void CProjectileHandler::UpdatePerlin()
{
	perlinFB->select();
	glViewport(perlintex.ixstart,perlintex.iystart,128,128);

	glMatrixMode(GL_PROJECTION);
	glPushMatrix();
	glLoadIdentity();
	glOrtho(0,1,0,1,-1,1);
	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	glLoadIdentity();

	glDisable(GL_DEPTH_TEST);
	glDepthMask(0);
	glEnable(GL_BLEND);
	glBlendFunc(GL_ONE, GL_ONE);
	glEnable(GL_TEXTURE_2D);
	glDisable(GL_ALPHA_TEST);
	glDisable(GL_FOG);

	unsigned char col[4];
	float time=gu->lastFrameTime*gs->speedFactor*3;
	float speed=1;
	float size=1;
	for(int a=0;a<4;++a){
		perlinBlend[a]+=time*speed;
		if(perlinBlend[a]>1){
			unsigned int temp=perlinTex[a*2];
			perlinTex[a*2]=perlinTex[a*2+1];
			perlinTex[a*2+1]=temp;
			GenerateNoiseTex(perlinTex[a*2+1],16);
			perlinBlend[a]-=1;
		}

		float tsize=8/size;

		if(a==0)
			glDisable(GL_BLEND);

		CVertexArray* va=GetVertexArray();
		va->Initialize();
		for(int b=0;b<4;++b)
			col[b]=int((1-perlinBlend[a])*16*size);
		glBindTexture(GL_TEXTURE_2D, perlinTex[a*2]);
		va->AddVertexTC(float3(0,0,0),0,0,col);
		va->AddVertexTC(float3(0,1,0),0,tsize,col);
		va->AddVertexTC(float3(1,1,0),tsize,tsize,col);
		va->AddVertexTC(float3(1,0,0),tsize,0,col);
		va->DrawArrayTC(GL_QUADS);

		if(a==0)
			glEnable(GL_BLEND);

		va=GetVertexArray();
		va->Initialize();
		for(int b=0;b<4;++b)
			col[b]=int(perlinBlend[a]*16*size);
		glBindTexture(GL_TEXTURE_2D, perlinTex[a*2+1]);
		va->AddVertexTC(float3(0,0,0),0,0,col);
		va->AddVertexTC(float3(0,1,0),0,tsize,col);
		va->AddVertexTC(float3(1,1,0),tsize,tsize,col);
		va->AddVertexTC(float3(1,0,0),tsize,0,col);
		va->DrawArrayTC(GL_QUADS);

		speed*=0.6f;
		size*=2;
	}
/*
	glBindTexture(GL_TEXTURE_2D, CProjectile::textures[0]);
	glCopyTexSubImage2D(GL_TEXTURE_2D,0,384,256,0,0,128,128);
*/
	perlinFB->deselect();
	glViewport(gu->viewPosX,0,gu->viewSizeX,gu->viewSizeY);

	glEnable(GL_DEPTH_TEST);
	glDisable(GL_TEXTURE_2D);
	glDepthMask(1);

	glPopMatrix();
	glMatrixMode(GL_PROJECTION);
	glPopMatrix();
	glMatrixMode(GL_MODELVIEW);
}

void CProjectileHandler::GenerateNoiseTex(unsigned int tex,int size)
{
	unsigned char* mem=SAFE_NEW unsigned char[4*size*size];

	for(int a=0;a<size*size;++a){
		unsigned char rnd=int(max(0.f,gu->usRandFloat()*555-300));
		mem[a*4+0]=rnd;
		mem[a*4+1]=rnd;
		mem[a*4+2]=rnd;
		mem[a*4+3]=rnd;
	}
	glBindTexture(GL_TEXTURE_2D, tex);
	glTexSubImage2D(GL_TEXTURE_2D,0,0,0,size,size,GL_RGBA,GL_UNSIGNED_BYTE,mem);
	delete[] mem;
}

⌨️ 快捷键说明

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