[SCM] advanced 3D real time strategy game engine branch, master, updated. debian/85.0+dfsg1-3-10-g30380f5

Jan Dittberner jandd at debian.org
Sun Mar 25 20:06:59 UTC 2012


The following commit has been merged in the master branch:
commit 6549151f12ba8e1e4fb4f42053e158645714a0ec
Merge: dedf638f08729cdf4e64da73db8cc171a8473cd4 e26fce3a64c58bfdc9723ee221ba10ea34ad6ca1
Author: Jan Dittberner <jandd at debian.org>
Date:   Sun Mar 25 21:19:43 2012 +0200

    Merge tag 'upstream/88.0+dfsg1'
    
    Upstream version 88.0+dfsg1
    
    * tag 'upstream/88.0+dfsg1':
      Imported Upstream version 88.0+dfsg1

diff --combined rts/Rendering/FarTextureHandler.cpp
index 06203b7,a211ed3..2f06752
--- a/rts/Rendering/FarTextureHandler.cpp
+++ b/rts/Rendering/FarTextureHandler.cpp
@@@ -86,7 -86,7 +86,7 @@@ CFarTextureHandler::~CFarTextureHandler
  /**
   * @brief Returns the (row, column) pair of a FarTexture in the TextureAtlas.
   */
- int2 CFarTextureHandler::GetTextureCoordsInt(const int& farTextureNum, const int& orientation)
+ int2 CFarTextureHandler::GetTextureCoordsInt(const int& farTextureNum, const int& orientation) const
  {
  	const int texnum = (farTextureNum * numOrientations) + orientation;
  
@@@ -99,7 -99,7 +99,7 @@@
  /**
   * @brief Returns the TexCoords of a FarTexture in the TextureAtlas.
   */
- float2 CFarTextureHandler::GetTextureCoords(const int& farTextureNum, const int& orientation)
+ float2 CFarTextureHandler::GetTextureCoords(const int& farTextureNum, const int& orientation) const
  {
  	float2 texcoords;
  
@@@ -115,6 -115,16 +115,16 @@@
  }
  
  
+ bool CFarTextureHandler::HaveFarIcon(const CSolidObject* obj) const
+ {
+ 	return (
+ 		   (cache.size() > obj->team)
+ 		&& (cache[obj->team].size() > obj->model->id)
+ 		&& (cache[obj->team][obj->model->id] != 0)
+ 	);
+ }
+ 
+ 
  /**
   * @brief Really create the far texture for the given model.
   */
@@@ -132,32 -142,56 +142,56 @@@ void CFarTextureHandler::CreateFarTextu
  
  	cache[obj->team][model->id] = -1;
  
- 
- 	if (!fbo.IsValid()) {
- 		LOG_L(L_DEBUG, "framebuffer not valid!");
+ 	// enough free space in the atlas?
+ 	if (!CheckResizeAtlas()) {
  		return;
  	}
  
+ 	// NOTE:
+ 	//    the icons are RTT'ed using a snapshot of the
+ 	//    current state (advModelShading, sunDir, etc)
+ 	//    and will not track later state-changes
+ 
  	fbo.Bind();
  	fbo.CreateRenderBuffer(GL_DEPTH_ATTACHMENT_EXT, GL_DEPTH_COMPONENT16, texSizeX, texSizeY);
  	fbo.CheckStatus("FARTEXTURE");
  
+ 	glPushAttrib(GL_ALL_ATTRIB_BITS);
+ 	glDisable(GL_BLEND);
+ 	glFrontFace(GL_CW);
+ 
+ 	glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+ 	glFogi(GL_FOG_MODE,   GL_LINEAR);
+ 	glFogf(GL_FOG_START,  0.0f);
+ 	glFogf(GL_FOG_END,    1e6);
+ 	glFogf(GL_FOG_DENSITY, 1.0f);
+ 
+ 	unitDrawer->SetupForUnitDrawing();
+ 	unitDrawer->GetOpaqueModelRenderer(model->type)->PushRenderState();
+ 	unitDrawer->SetTeamColour(obj->team);
+ 
+ 	if (model->type != MODELTYPE_3DO) {
+ 		texturehandlerS3O->SetS3oTexture(model->textureType);
+ 	}
+ 
+ 	//const float xs = std::max(math::fabs(model->relMidPos.x + model->maxs.x), math::fabs(model->relMidPos.x + model->mins.x));
+ 	//const float ys = std::max(math::fabs(model->relMidPos.y + model->maxs.y), math::fabs(model->relMidPos.y + model->mins.y));
+ 	//const float zs = std::max(math::fabs(model->relMidPos.z + model->maxs.z), math::fabs(model->relMidPos.z + model->mins.z));
+ 	//const float modelradius = std::max(xs, std::max(ys, zs));*/
+ 	const float modelradius = 1.15f * model->radius;
  
  	// overwrite the matrices set by SetupForUnitDrawing
  	// RTT with a top-down view; the view-matrix must be
  	// on the PROJECTION stack for the model shaders
  	glMatrixMode(GL_PROJECTION);
  		glLoadIdentity();
- 		glOrtho(-model->radius, model->radius, -model->radius, model->radius, -model->radius * 1.5f, model->radius * 1.5f);
+ 		glOrtho(-modelradius, modelradius, -modelradius, modelradius, -modelradius, modelradius);
+ 		glRotatef(45.0f, 1.0f, 0.0f, 0.0f);
+ 		glScalef(-1.0f, 1.0f, 1.0f);
  
  	glMatrixMode(GL_MODELVIEW);
  		glLoadIdentity();
  
- 
- 	glPushAttrib(GL_ALL_ATTRIB_BITS);
- 	glDisable(GL_BLEND);
- 
  	for (int orient = 0; orient < numOrientations; ++orient) {
  		// setup viewport
  		const int2 pos = GetTextureCoordsInt(usedFarTextures, orient);
@@@ -168,15 -202,17 +202,15 @@@
  		glPushMatrix();
  		glTranslatef(0.0f, -model->height * 0.5f, 0.0f);
  
- 		// draw the model to a temporary buffer
+ 		// draw model
  		model->DrawStatic();
  
  		glPopMatrix();
  
  		// rotate by 360 / numOrientations degrees for the next orientation
- 		glRotatef(360.0f / numOrientations, 0.0f, 1.0f, 0.0f);
+ 		glRotatef(-360.0f / numOrientations, 0.0f, 1.0f, 0.0f);
  	}
  
 -	unitDrawer->GetOpaqueModelRenderer(model->type)->PopRenderState();
 -	unitDrawer->CleanUpUnitDrawing();
  
  	// glViewport(globalRendering->viewPosX, 0, globalRendering->viewSizeX, globalRendering->viewSizeY);
  	glPopAttrib();
@@@ -188,8 -224,8 +222,8 @@@
  }
  
  
- 
- void CFarTextureHandler::DrawFarTexture(const CSolidObject* obj, CVertexArray* va) {
+ void CFarTextureHandler::DrawFarTexture(const CSolidObject* obj, CVertexArray* va)
+ {
  	const int farTextureNum = cache[obj->team][obj->model->id];
  
  	// not found in the atlas
@@@ -234,82 -270,58 +268,60 @@@ void CFarTextureHandler::Draw(
  		return;
  	}
  
- 	{
- 		// check if there is enough free space in the atlas, if not try resizing
- 		// it (as many times as the number of models queued for iconification)
- 		unsigned int maxNewIcons = 0;
- 
- 		for (unsigned int n = 0; n < queuedForRender.size(); n++) {
- 			if (!CheckResizeAtlas(n + 1)) { break; } maxNewIcons++;
- 		}
- 
- 		// now create the new far-icons
- 		// NOTE:
- 		//    the icons are RTT'ed using a snapshot of the
- 		//    current state (advModelShading, sunDir, etc)
- 		//    and will not track later state-changes
- 		unitDrawer->SetupForUnitDrawing();
- 
- 		GML_VECTOR<const CSolidObject*>::iterator it;
- 
- 		for (it = queuedForRender.begin(); it != queuedForRender.end() && maxNewIcons > 0; ++it) {
- 			maxNewIcons--;
- 
- 			const CSolidObject* obj = *it;
- 			const S3DModel* mdl = obj->model;
- 
- 			unitDrawer->GetOpaqueModelRenderer(mdl->type)->PushRenderState();
- 			unitDrawer->SetTeamColour(obj->team);
- 
- 			if (mdl->type != MODELTYPE_3DO) {
- 				texturehandlerS3O->SetS3oTexture(mdl->textureType);
- 			}
- 
- 			if ((int)cache.size() <= obj->team || (int)cache[obj->team].size() <= mdl->id || !cache[obj->team][mdl->id]) {
- 				CreateFarTexture(obj);
- 			}
+ 	if (!fbo.IsValid()) {
+ 		queuedForRender.clear();
+ 		return;
+ 	}
  
- 			unitDrawer->GetOpaqueModelRenderer(mdl->type)->PopRenderState();
+ 	// create new far-icons
+ 	for (GML_VECTOR<const CSolidObject*>::iterator it = queuedForRender.begin(); it != queuedForRender.end(); ++it) {
+ 		const CSolidObject* obj = *it;
+ 		if (!HaveFarIcon(obj)) {
+ 			CreateFarTexture(obj);
  		}
 +
 +		unitDrawer->CleanUpUnitDrawing();
  	}
  
- 	glEnable(GL_ALPHA_TEST);
- 	glAlphaFunc(GL_GREATER, 0.5f);
- 	glActiveTexture(GL_TEXTURE0);
- 	glEnable(GL_TEXTURE_2D);
- 	glBindTexture(GL_TEXTURE_2D, farTextureID);
- 	glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
- 	glNormal3fv((const GLfloat*) &unitDrawer->camNorm.x);
- 
- 	ISky::SetupFog();
+ 	// render current queued far icons on the screen
+ 	{
+ 		glEnable(GL_ALPHA_TEST);
+ 		glAlphaFunc(GL_GREATER, 0.5f);
+ 		glActiveTexture(GL_TEXTURE0);
+ 		glEnable(GL_TEXTURE_2D);
+ 		glBindTexture(GL_TEXTURE_2D, farTextureID);
+ 		glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+ 		glNormal3fv((const GLfloat*) &unitDrawer->camNorm.x);
+ 
+ 		ISky::SetupFog();
+ 
+ 		CVertexArray* va = GetVertexArray();
+ 		va->Initialize();
+ 		va->EnlargeArrays(queuedForRender.size() * 4, 0, VA_SIZE_T);
+ 		for (GML_VECTOR<const CSolidObject*>::iterator it = queuedForRender.begin(); it != queuedForRender.end(); ++it) {
+ 			DrawFarTexture(*it, va);
+ 		}
  
- 	CVertexArray* va = GetVertexArray();
- 	va->Initialize();
- 	va->EnlargeArrays(queuedForRender.size() * 4, 0, VA_SIZE_T);
- 	for (GML_VECTOR<const CSolidObject*>::iterator it = queuedForRender.begin(); it != queuedForRender.end(); ++it) {
- 		DrawFarTexture(*it, va);
+ 		va->DrawArrayT(GL_QUADS);
+ 		glDisable(GL_ALPHA_TEST);
  	}
  
- 	va->DrawArrayT(GL_QUADS);
- 	glDisable(GL_ALPHA_TEST);
- 
  	queuedForRender.clear();
  }
  
  
  
- bool CFarTextureHandler::CheckResizeAtlas(unsigned int newNumTextures) {
+ bool CFarTextureHandler::CheckResizeAtlas()
+ {
  	const unsigned int maxSprites = ((texSizeX / iconSizeX) * (texSizeY / iconSizeY) / numOrientations) - 1;
  
- 	if ((usedFarTextures + newNumTextures) < maxSprites)
+ 	if (usedFarTextures + 1 <= maxSprites)
  		return true;
  
  	const int oldTexSizeY = texSizeY;
  
  	if (globalRendering->supportNPOTs) {
- 		texSizeY += std::max(iconSizeY,  4 * numOrientations * iconSizeX * iconSizeY / texSizeX); // minimum additional space for 4 icons
+ 		texSizeY += std::max(iconSizeY,  4 * numOrientations * iconSizeX * iconSizeY / texSizeX); // make space for minimum 4 additional icons
  	} else {
  		texSizeY <<= 1;
  	}
@@@ -322,7 -334,7 +334,7 @@@
  
  	unsigned char* oldPixels = new unsigned char[texSizeX*texSizeY*4];
  	glBindTexture(GL_TEXTURE_2D, farTextureID);
- 	glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, oldPixels);
+ 	glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, oldPixels); //TODO use the FBO?
  	memset(oldPixels + texSizeX*oldTexSizeY*4, 0, texSizeX*(texSizeY - oldTexSizeY)*4);
  
  	GLuint newFarTextureID;
diff --combined rts/Sim/MoveTypes/GroundMoveType.cpp
index 2e0f199,e23db5e..4501a05
--- a/rts/Sim/MoveTypes/GroundMoveType.cpp
+++ b/rts/Sim/MoveTypes/GroundMoveType.cpp
@@@ -54,8 -54,15 +54,15 @@@ LOG_REGISTER_SECTION_GLOBAL(LOG_SECTION
  #define MAX_IDLING_SLOWUPDATES 16
  #define DEBUG_OUTPUT 0
  #define WAIT_FOR_PATH 1
+ #define IGNORE_OBSTACLES 0
  #define PLAY_SOUNDS 1
  
+ #define OWNER_CMD_QUE owner->commandAI->commandQue
+ #define OWNER_MOVE_CMD() (OWNER_CMD_QUE.empty() || OWNER_CMD_QUE[0].GetID() == CMD_MOVE)
+ 
+ #define FOOTPRINT_RADIUS(xs, zs, s) ((math::sqrt((xs * xs + zs * zs)) * 0.5f * SQUARE_SIZE) * s)
+ 
+ 
  
  CR_BIND_DERIVED(CGroundMoveType, AMoveType, (NULL));
  
@@@ -77,6 -84,7 +84,7 @@@ CR_REG_METADATA(CGroundMoveType, 
  	CR_MEMBER(nextWayPoint),
  	CR_MEMBER(atGoal),
  	CR_MEMBER(haveFinalWaypoint),
+ 
  	CR_MEMBER(currWayPointDist),
  	CR_MEMBER(prevWayPointDist),
  
@@@ -135,6 -143,7 +143,7 @@@ CGroundMoveType::CGroundMoveType(CUnit
  	nextWayPoint(ZeroVector),
  	atGoal(false),
  	haveFinalWaypoint(false),
+ 
  	currWayPointDist(0.0f),
  	prevWayPointDist(0.0f),
  
@@@ -374,6 -383,7 +383,7 @@@ void CGroundMoveType::StartMoving(float
  	goalRadius = _goalRadius;
  	requestedSpeed = speed;
  	atGoal = false;
+ 
  	useMainHeading = false;
  	progressState = Active;
  
@@@ -433,9 -443,9 +443,9 @@@ bool CGroundMoveType::FollowPath(
  			//     and we cannot increase tolerance safely (otherwise the unit might stop when still
  			//     outside its range and fail to start construction)
  			const float curGoalDistSq = (owner->pos - goalPos).SqLength2D();
- 			const float minGoalDistSq = (!owner->commandAI->commandQue.empty() && owner->commandAI->commandQue[0].GetID() < 0)?
- 				Square(goalRadius                             ):
- 				Square(goalRadius * (numIdlingSlowUpdates + 1));
+ 			const float minGoalDistSq = (OWNER_MOVE_CMD())?
+ 				Square(goalRadius * (numIdlingSlowUpdates + 1)):
+ 				Square(goalRadius                             );
  
  			atGoal |= (curGoalDistSq < minGoalDistSq);
  		}
@@@ -521,6 -531,8 +531,8 @@@ void CGroundMoveType::SetDeltaSpeed(flo
  		if (wantedSpeed > 0.0f) {
  			const UnitDef* ud = owner->unitDef;
  			const float groundMod = ud->movedata->moveMath->GetPosSpeedMod(*ud->movedata, owner->pos, flatFrontDir);
+ 			const float curGoalDistSq = (owner->pos - goalPos).SqLength2D();
+ 			const float minGoalDistSq = Square(BreakingDistance(currentSpeed));
  
  			const float3& goalDifFwd = waypointDir;
  			const float3  goalDifRev = -goalDifFwd;
@@@ -529,9 -541,7 +541,7 @@@
  			const short turnDeltaHeading = owner->heading - GetHeadingFromVector(goalDif.x, goalDif.z);
  
  			// NOTE: <= 2 because every CMD_MOVE has a trailing CMD_SET_WANTED_MAX_SPEED
- 			const bool startBreaking =
- 				(owner->commandAI->commandQue.size() <= 2) &&
- 				((owner->pos - goalPos).SqLength2D() <= Square(BreakingDistance(currentSpeed)));
+ 			const bool startBreaking = (OWNER_CMD_QUE.size() <= 2 && curGoalDistSq <= minGoalDistSq);
  
  			if (!fpsMode && turnDeltaHeading != 0) {
  				// only auto-adjust speed for turns when not in FPS mode
@@@ -998,7 -1008,7 +1008,7 @@@ void CGroundMoveType::CalcSkidRot(
   * follow the path even when it's not perfect.
   */
  float3 CGroundMoveType::ObstacleAvoidance(const float3& desiredDir) {
- 	#ifdef IGNORE_OBSTACLES
+ 	#if (IGNORE_OBSTACLES == 1)
  	return desiredDir;
  	#endif
  
@@@ -1019,89 -1029,103 +1029,103 @@@
  	lastAvoidanceDir = desiredDir;
  	nextObstacleAvoidanceUpdate = gs->frameNum + 4;
  
+ 	CUnit* avoider = owner;
+ 	MoveData* avoiderMD = avoider->mobility;
+ 	CMoveMath* avoiderMM = avoiderMD->moveMath;
+ 
+ 	avoiderMD->tempOwner = avoider;
+ 
+ 
  	// now we do the obstacle avoidance proper
- 	const float avoidanceRadius = std::max(currentSpeed, 1.0f) * (owner->radius * 2.0f);
+ 	// avoider always uses its never-rotated MoveDef footprint
+ 	const float avoidanceRadius = std::max(currentSpeed, 1.0f) * (avoider->radius * 2.0f);
+ 	const float avoiderRadius = FOOTPRINT_RADIUS(avoiderMD->xsize, avoiderMD->zsize, 1.0f);
  	const float3 rightOfPath = desiredDir.cross(UpVector);
  
  	float avoidLeft = 0.0f;
  	float avoidRight = 0.0f;
  
- 	MoveData* moveData = owner->mobility;
- 	CMoveMath* moveMath = moveData->moveMath;
- 	moveData->tempOwner = owner;
- 
- 	const vector<CSolidObject*>& nearbyObjects = qf->GetSolidsExact(owner->pos, avoidanceRadius);
+ 	const vector<CSolidObject*>& nearbyObjects = qf->GetSolidsExact(avoider->pos, avoidanceRadius);
  
  	for (vector<CSolidObject*>::const_iterator oi = nearbyObjects.begin(); oi != nearbyObjects.end(); ++oi) {
- 		CSolidObject* object = *oi;
+ 		CSolidObject* avoidee = *oi;
+ 		MoveData* avoideeMD = avoidee->mobility;
  
  		// cases in which there is no need to avoid this obstacle
- 		if (object == owner)
+ 		if (avoidee == owner)
  			continue;
- 		if (moveMath->IsNonBlocking(*moveData, object))
+ 		if (avoiderMM->IsNonBlocking(*avoiderMD, avoidee))
  			continue;
- 		if (!moveMath->CrushResistant(*moveData, object))
+ 		if (!avoiderMM->CrushResistant(*avoiderMD, avoidee))
  			continue;
  		// ignore objects that are slightly behind us
- 		if ((desiredDir.dot(object->pos - owner->pos) + 0.25f) <= 0.0f)
+ 		if ((desiredDir.dot(avoidee->pos - avoider->pos) + 0.25f) <= 0.0f)
  			continue;
  
- 		const float3 objectToUnit = (owner->pos - object->pos - object->speed * GAME_SPEED);
- 		const float objectDistSq = objectToUnit.SqLength();
+ 		const bool avoideeMobile = (avoideeMD != NULL);
+ 
+ 		const float3 avoideeVector = (avoider->pos - avoidee->pos - avoidee->speed * GAME_SPEED);
+ 		const float avoideeDistSq = avoideeVector.SqLength();
  
- 		// NOTE: use the footprint radii instead?
- 		const float radiusSum = owner->radius + object->radius;
- 		const float massSum = owner->mass + object->mass;
- 		const bool objectMobile = (object->mobility != NULL);
- 		const float objectMassScale = (objectMobile)? (object->mass / massSum): 1.0f;
+ 		// use the avoidee's MoveDef footprint if it is mobile
+ 		// use the avoidee's Unit (not UnitDef) footprint otherwise
+ 		const float avoideeRadius = avoideeMobile?
+ 			FOOTPRINT_RADIUS(avoideeMD->xsize, avoideeMD->zsize, 1.0f):
+ 			FOOTPRINT_RADIUS(avoidee  ->xsize, avoidee  ->zsize, 1.0f);
+ 		const float avoidanceRadiusSum = avoiderRadius + avoideeRadius;
+ 		const float avoidanceMassSum = avoider->mass + avoidee->mass;
+ 		const float avoideeMassScale = (avoideeMobile)? (avoidee->mass / avoidanceMassSum): 1.0f;
  
- 		if (objectDistSq >= Square(currentSpeed * GAME_SPEED + radiusSum))
+ 		if (avoideeMobile && !avoiderMD->avoidMobilesOnPath)
  			continue;
- 		if (objectDistSq >= owner->pos.SqDistance2D(goalPos))
+ 
+ 		if (avoideeDistSq >= Square(currentSpeed * GAME_SPEED + avoidanceRadiusSum))
+ 			continue;
+ 		if (avoideeDistSq >= avoider->pos.SqDistance2D(goalPos))
  			continue;
  
  		// note: positive angle cosines mean object is to our right
- 		const float objectDistToAvoidDirCenter = objectToUnit.dot(rightOfPath);
+ 		const float avoideeDistToAvoidDirCenter = avoideeVector.dot(rightOfPath);
  
- 		if (objectToUnit.dot(avoidanceDir) >= radiusSum)
+ 		if (avoideeVector.dot(avoidanceDir) >= avoidanceRadiusSum)
  			continue;
- 		if (math::fabs(objectDistToAvoidDirCenter) >= radiusSum)
+ 		if (math::fabs(avoideeDistToAvoidDirCenter) >= avoidanceRadiusSum)
  			continue;
  
  		// do not bother steering around idling objects
  		// (collision handling will push them aside, or
  		// us in case of "allied" features)
- 		if (!object->isMoving && object->allyteam == owner->allyteam)
+ 		if (!avoidee->isMoving && avoidee->allyteam == avoider->allyteam)
  			continue;
  
  		// if object and unit in relative motion are closing in on one another
  		// (or not yet fully apart), then the object is on the path of the unit
  		// and they are not collided
- 		if (objectMobile || (Distance2D(owner, object, SQUARE_SIZE) >= 0.0f)) {
+ 		if (avoideeMobile || (Distance2D(owner, avoidee, SQUARE_SIZE) >= 0.0f)) {
  			#if (DEBUG_OUTPUT == 1)
  			{
  				GML_RECMUTEX_LOCK(sel); // ObstacleAvoidance
  
  				if (selectedUnits.selectedUnits.find(owner) != selectedUnits.selectedUnits.end()) {
- 					geometricObjects->AddLine(owner->pos + UpVector * 20, object->pos + UpVector * 20, 3, 1, 4);
+ 					geometricObjects->AddLine(avoider->pos + UpVector * 20, object->pos + UpVector * 20, 3, 1, 4);
  				}
  			}
  			#endif
  
- 			const float iSqrtObjDist = (objectDistSq <= 1e-4f)? 1e-2f: math::isqrt2(objectDistSq);
- 			const float avoidScale = (AVOIDANCE_STRENGTH * iSqrtObjDist * iSqrtObjDist * iSqrtObjDist) * objectMassScale;
+ 			const float iSqrtDist = (avoideeDistSq <= 1e-4f)? 1e-2f: math::isqrt2(avoideeDistSq);
+ 			const float avoidScale = (AVOIDANCE_STRENGTH * iSqrtDist * iSqrtDist * iSqrtDist) * avoideeMassScale;
  
  			// avoid collision by turning either left or right
  			// using the direction thats needs most adjustment
- 			if (objectDistToAvoidDirCenter > 0.0f) {
- 				avoidRight += ((radiusSum - objectDistToAvoidDirCenter) * avoidScale);
+ 			if (avoideeDistToAvoidDirCenter > 0.0f) {
+ 				avoidRight += ((avoidanceRadiusSum - avoideeDistToAvoidDirCenter) * avoidScale);
  			} else {
- 				avoidLeft += ((radiusSum + objectDistToAvoidDirCenter) * avoidScale);
+ 				avoidLeft += ((avoidanceRadiusSum + avoideeDistToAvoidDirCenter) * avoidScale);
  			}
  		}
  	}
  
- 	moveData->tempOwner = NULL;
+ 	avoiderMD->tempOwner = NULL;
  
  
  	// Sum up avoidance.
@@@ -1112,10 -1136,10 +1136,10 @@@
  		GML_RECMUTEX_LOCK(sel); // ObstacleAvoidance
  
  		if (selectedUnits.selectedUnits.find(owner) != selectedUnits.selectedUnits.end()) {
- 			int a = geometricObjects->AddLine(owner->pos + UpVector * 20, owner->pos + UpVector * 20 + avoidanceVec * 40, 7, 1, 4);
+ 			int a = geometricObjects->AddLine(avoider->pos + UpVector * 20, avoider->pos + UpVector * 20 + avoidanceVec * 40, 7, 1, 4);
  			geometricObjects->SetColor(a, 1, 0.3f, 0.3f, 0.6f);
  
- 			a = geometricObjects->AddLine(owner->pos + UpVector * 20, owner->pos + UpVector * 20 + desiredDir * 40, 7, 1, 4);
+ 			a = geometricObjects->AddLine(avoider->pos + UpVector * 20, avoider->pos + UpVector * 20 + desiredDir * 40, 7, 1, 4);
  			geometricObjects->SetColor(a, 0.3f, 0.3f, 1, 0.6f);
  		}
  	}
@@@ -1232,9 -1256,9 +1256,9 @@@ void CGroundMoveType::GetNextWayPoint(
  
  		{
  			const float curGoalDistSq = (currWayPoint - goalPos).SqLength2D();
- 			const float minGoalDistSq = (!owner->commandAI->commandQue.empty() && owner->commandAI->commandQue[0].GetID() < 0)?
- 				Square(goalRadius                             ):
- 				Square(goalRadius * (numIdlingSlowUpdates + 1));
+ 			const float minGoalDistSq = (OWNER_MOVE_CMD())?
+ 				Square(goalRadius * (numIdlingSlowUpdates + 1)):
+ 				Square(goalRadius                             );
  
  			// trigger Arrived on the next Update (but
  			// only if we have non-temporary waypoints)
@@@ -1319,7 -1343,6 +1343,6 @@@ void CGroundMoveType::StartEngine() 
  }
  
  void CGroundMoveType::StopEngine() {
- 
  	if (pathId != 0) {
  		pathManager->DeletePath(pathId);
  		pathId = 0;
@@@ -1383,15 -1406,6 +1406,6 @@@ void CGroundMoveType::Fail(
  
  
  
- // FIXME move this to a global space to optimize the check (atm unit collision checks are done twice for the collider & collidee!)
- //
- // allow some degree of inter-penetration (1 - 0.75)
- // between objects to avoid sudden extreme responses
- //
- // FIXME: this is bad for immobile obstacles because
- // their corners might stick out through the radius
- #define FOOTPRINT_RADIUS(xs, zs) ((math::sqrt((xs * xs + zs * zs)) * 0.5f * SQUARE_SIZE) * 0.75f)
- 
  void CGroundMoveType::HandleObjectCollisions()
  {
  	static const float3 sepDirMask = float3(1.0f, 0.0f, 1.0f);
@@@ -1404,13 -1418,15 +1418,15 @@@
  		const MoveData*  colliderMD = collider->mobility;
  		const CMoveMath* colliderMM = colliderMD->moveMath;
  
+ 		// collider always uses its never-rotated MoveDef footprint
+ 		//
+ 		// allow some degree of inter-penetration (1 - 0.75)
+ 		// between objects to avoid sudden extreme responses
  		const float colliderSpeed = collider->speed.Length();
- 		const float colliderRadius = (colliderMD != NULL)?
- 			FOOTPRINT_RADIUS(colliderMD->xsize, colliderMD->zsize):
- 			FOOTPRINT_RADIUS(colliderUD->xsize, colliderUD->zsize);
+ 		const float colliderRadius = FOOTPRINT_RADIUS(colliderMD->xsize, colliderMD->zsize, 0.75f);
  
- 		HandleUnitCollisions(collider, collider->pos, oldPos, colliderSpeed, colliderRadius, sepDirMask, colliderUD, colliderMD, colliderMM);
- 		HandleFeatureCollisions(collider, collider->pos, oldPos, colliderSpeed, colliderRadius, sepDirMask, colliderUD, colliderMD, colliderMM);
+ 		HandleUnitCollisions(collider, colliderSpeed, colliderRadius, sepDirMask, colliderUD, colliderMD, colliderMM);
+ 		HandleFeatureCollisions(collider, colliderSpeed, colliderRadius, sepDirMask, colliderUD, colliderMD, colliderMM);
  	}
  
  	collider->mobility->tempOwner = NULL;
@@@ -1419,8 -1435,6 +1435,6 @@@
  
  void CGroundMoveType::HandleUnitCollisions(
  	CUnit* collider,
- 	const float3& colliderCurPos,
- 	const float3& colliderOldPos,
  	const float colliderSpeed,
  	const float colliderRadius,
  	const float3& sepDirMask,
@@@ -1430,7 -1444,7 +1444,7 @@@
  ) {
  	const float searchRadius = std::max(colliderSpeed, 1.0f) * (colliderRadius * 2.0f);
  
- 	const std::vector<CUnit*>& nearUnits = qf->GetUnitsExact(colliderCurPos, searchRadius);
+ 	const std::vector<CUnit*>& nearUnits = qf->GetUnitsExact(collider->pos, searchRadius);
  	      std::vector<CUnit*>::const_iterator uit;
  
  	// NOTE: probably too large for most units (eg. causes tree falling animations to be skipped)
@@@ -1444,22 -1458,21 +1458,21 @@@
  		if (collidee->moveType->IsSkidding()) { continue; }
  		if (collidee->moveType->IsFlying()) { continue; }
  
+ 		const bool colliderMobile = (collider->mobility != NULL);
+ 		const bool collideeMobile = (collidee->mobility != NULL);
+ 
  		const UnitDef*   collideeUD = collidee->unitDef;
  		const MoveData*  collideeMD = collidee->mobility;
- 		const CMoveMath* collideeMM = (collideeMD != NULL)? collideeMD->moveMath: NULL;
- 
- 		const float3& collideeCurPos = collidee->pos;
- 		const float3& collideeOldPos = collidee->moveType->oldPos;
- 
- 		const bool colliderMobile = (collider->mobility != NULL);
- 		const bool collideeMobile = (collideeMD != NULL);
+ 		const CMoveMath* collideeMM = (collideeMobile)? collideeMD->moveMath: NULL;
  
+ 		// use the collidee's MoveDef footprint if it is mobile
+ 		// use the collidee's Unit (not UnitDef) footprint otherwise
  		const float collideeSpeed = collidee->speed.Length();
  		const float collideeRadius = collideeMobile?
- 			FOOTPRINT_RADIUS(collideeMD->xsize, collideeMD->zsize):
- 			FOOTPRINT_RADIUS(collidee  ->xsize, collidee  ->zsize);
+ 			FOOTPRINT_RADIUS(collideeMD->xsize, collideeMD->zsize, 0.75f):
+ 			FOOTPRINT_RADIUS(collidee  ->xsize, collidee  ->zsize, 0.75f);
  
- 		const float3 separationVector   = colliderCurPos - collideeCurPos;
+ 		const float3 separationVector   = collider->pos - collidee->pos;
  		const float separationMinDistSq = (colliderRadius + collideeRadius) * (colliderRadius + collideeRadius);
  
  		if ((separationVector.SqLength() - separationMinDistSq) > 0.01f)
@@@ -1484,7 -1497,9 +1497,9 @@@
  			teamHandler->Ally(collidee->allyteam, collider->allyteam);
  		const bool collideeYields = (collider->isMoving && !collidee->isMoving);
  		const bool ignoreCollidee = ((collideeYields && alliedCollision) || colliderUD->pushResistant);
- 		const bool disablePushing = (colliderUD->pushResistant && collideeUD->pushResistant);
+ 		const bool disablePushing =
+ 			(colliderUD->pushResistant && !collider->beingBuilt) &&
+ 			(collideeUD->pushResistant && !collidee->beingBuilt);
  
  		pushCollider &= (alliedCollision || modInfo.allowPushingEnemyUnits || !collider->blockEnemyPushing);
  		pushCollidee &= (alliedCollision || modInfo.allowPushingEnemyUnits || !collidee->blockEnemyPushing);
@@@ -1500,8 -1515,12 +1515,12 @@@
  
  		eventHandler.UnitUnitCollision(collider, collidee);
  
+ 		const float colliderRelRadius = colliderRadius / (colliderRadius + collideeRadius);
+ 		const float collideeRelRadius = collideeRadius / (colliderRadius + collideeRadius);
+ 		const float collisionRadiusSum = (colliderRadius * colliderRelRadius + collideeRadius * collideeRelRadius);
+ 
  		const float  sepDistance    = separationVector.Length() + 0.01f;
- 		const float  penDistance    = std::max((colliderRadius + collideeRadius) - sepDistance, 1.0f);
+ 		const float  penDistance    = std::max(collisionRadiusSum - sepDistance, 1.0f);
  		const float  sepResponse    = std::min(SQUARE_SIZE * 2.0f, penDistance * 0.5f);
  
  		const float3 sepDirection   = (separationVector / sepDistance);
@@@ -1515,24 -1534,41 +1534,43 @@@
  			c1 = 1.0f + (1.0f - math::fabs(collider->frontdir.dot(-sepDirection))) * 5.0f,
  			c2 = 1.0f + (1.0f - math::fabs(collidee->frontdir.dot( sepDirection))) * 5.0f,
  			s1 = m1 * v1 * c1,
- 			s2 = m2 * v2 * c2;
+ 			s2 = m2 * v2 * c2,
+  			r1 = s1 / (s1 + s2 + 1.0f),
+  			r2 = s2 / (s1 + s2 + 1.0f);
  
  		// far from a realistic treatment, but works
- 		const float collisionMassSum  = s1 + s2 + 1.0f;
- 		      float colliderMassScale = std::max(0.01f, std::min(0.99f, 1.0f - (s1 / collisionMassSum)));
- 		      float collideeMassScale = std::max(0.01f, std::min(0.99f, 1.0f - (s2 / collisionMassSum)));
+ 		float colliderMassScale = std::max(0.01f, std::min(0.99f, 1.0f - r1));
+ 		float collideeMassScale = std::max(0.01f, std::min(0.99f, 1.0f - r2));
+ 
+ 		if (collider->isMoving && collidee->isMoving) {
+ 			#define SIGN(v) ((int(v >= 0.0f) * 2) - 1)
+ 			// push collider and collidee laterally in opposite directions
+ 			const int colliderSign = SIGN( separationVector.dot(collider->rightdir));
+ 			const int collideeSign = SIGN(-separationVector.dot(collidee->rightdir));
+ 			const float3 colliderSlideVec = collider->rightdir * colliderSign * (1.0f / penDistance);
+ 			const float3 collideeSlideVec = collidee->rightdir * collideeSign * (1.0f / penDistance);
+  
+ 			if (pushCollider) { collider->Move3D(colliderSlideVec * r2, true); }
+ 			if (pushCollidee) { collidee->Move3D(collideeSlideVec * r1, true); }
+ 			#undef SIGN
+ 		}
  
  		if (!collideeMobile) {
- 			const float3 colliderNxtPos = colliderCurPos + collider->speed;
- 			const CMoveMath::BlockType colliderCurPosBits = colliderMM->IsBlocked(*colliderMD, colliderCurPos);
- 			const CMoveMath::BlockType colliderNxtPosBits = colliderMM->IsBlocked(*colliderMD, colliderNxtPos);
+ 			CMoveMath::BlockType posBits;
  
- 			if ((colliderCurPosBits & CMoveMath::BLOCK_STRUCTURE) == 0)
+ 			if (collider->speed == ZeroVector)
+ 				continue;
+ 
+ 			posBits = colliderMM->IsBlocked(*colliderMD, collider->pos);
+ 
+ 			if ((posBits & CMoveMath::BLOCK_STRUCTURE) == 0)
  				continue;
 +			if (colliderNxtPos == colliderCurPos)
 +				continue;
  
- 			if ((colliderNxtPosBits & CMoveMath::BLOCK_STRUCTURE) != 0) {
+ 			posBits = colliderMM->IsBlocked(*colliderMD, collider->pos + collider->speed);
+ 
+ 			if ((posBits & CMoveMath::BLOCK_STRUCTURE) != 0) {
  				// applied every frame objects are colliding, so be careful
  				collider->AddImpulse(sepDirection * sepDirMask);
  
@@@ -1543,20 -1579,36 +1581,36 @@@
  					// repath iff obstacle is within 60-degree cone; we do this
  					// because the GNWP lookahead (for non-TIP units) can cause
  					// corners to be cut across statically blocked squares
- 					StartMoving(goalPos, goalRadius, 0.0f);
+ 					//
+ 					// NOTE:
+ 					//   we want an initial speed of 0 to avoid ramming into the
+ 					//   obstacle again right after the push, but if our leading
+ 					//   command is not a CMD_MOVE then SetMaxSpeed will not get
+ 					//   called later and 0 will immobilize us
+ 					//
+ 					if (OWNER_MOVE_CMD()) {
+ 						StartMoving(goalPos, goalRadius, 0.0f);
+ 					} else {
+ 						StartMoving(goalPos, goalRadius);
+ 					}
  				}
  			}
  		}
  
- 		const float3 colliderNewPos = colliderCurPos + (colResponseVec * colliderMassScale);
- 		const float3 collideeNewPos = collideeCurPos - (colResponseVec * collideeMassScale);
+ 		const float3 colliderPushPos = collider->pos + (colResponseVec * colliderMassScale);
+ 		const float3 collideePushPos = collidee->pos - (colResponseVec * collideeMassScale);
+ 
+ 		const bool cancelColliderPush =
+ 			((colliderMM->IsBlocked(*colliderMD, colliderPushPos) & CMoveMath::BLOCK_STRUCTURE) != 0) ||
+ 			((colliderMM->GetPosSpeedMod(*colliderMD, colliderPushPos) <= 0.01f));
+ 		const bool cancelCollideePush =
+ 			(collideeMobile && (collideeMM->IsBlocked(*collideeMD, collideePushPos) & CMoveMath::BLOCK_STRUCTURE) != 0) ||
+ 			(collideeMobile && (collideeMM->GetPosSpeedMod(*collideeMD, collideePushPos) <= 0.01f));
  
  		// try to prevent both parties from being pushed onto non-traversable
  		// squares (without stopping them dead in their tracks, which is worse)
- 		if (                  (colliderMM->IsBlocked(*colliderMD, colliderNewPos) & CMoveMath::BLOCK_STRUCTURE) != 0) { colliderMassScale = 0.0f; }
- 		if (collideeMobile && (collideeMM->IsBlocked(*collideeMD, collideeNewPos) & CMoveMath::BLOCK_STRUCTURE) != 0) { collideeMassScale = 0.0f; }
- 		if (                  colliderMM->GetPosSpeedMod(*colliderMD, colliderNewPos) <= 0.01f) { colliderMassScale = 0.0f; }
- 		if (collideeMobile && collideeMM->GetPosSpeedMod(*collideeMD, collideeNewPos) <= 0.01f) { collideeMassScale = 0.0f; }
+ 		if (cancelColliderPush) { colliderMassScale = 0.0f; }
+ 		if (cancelCollideePush) { collideeMassScale = 0.0f; }
  
  		// ignore pushing contributions from idling friendly collidee's
  		// (or if we are resistant to them) without stopping; this will
@@@ -1567,15 -1619,15 +1621,15 @@@
  
  		// either both parties are pushed, or only one party is pushed and the other is stopped, or both are stopped
  		     if (  pushCollider) { collider->Move3D( colResponseVec * colliderMassScale, true); }
- 		else if (colliderMobile) { collider->Move3D(colliderOldPos, false); }
+ 		else if (colliderMobile) { collider->Move3D(collider->moveType->oldPos, false); }
  		     if (  pushCollidee) { collidee->Move3D(-colResponseVec * collideeMassScale, true); }
- 		else if (collideeMobile) { collidee->Move3D(collideeOldPos, false); }
+ 		else if (collideeMobile) { collidee->Move3D(collidee->moveType->oldPos, false); }
  
  		#if 0
  		if (!((gs->frameNum + collider->id) & 31) && !colliderCAI->unimportantMove) {
  			// if we do not have an internal move order, tell units around us to bugger off
  			// note: this causes too much chaos among the ranks when groups get large
- 			helper->BuggerOff(colliderCurPos + collider->frontdir * colliderRadius, colliderRadius, true, false, collider->team, collider);
+ 			helper->BuggerOff(collider->pos + collider->frontdir * colliderRadius, colliderRadius, true, false, collider->team, collider);
  		}
  		#endif
  	}
@@@ -1583,8 -1635,6 +1637,6 @@@
  
  void CGroundMoveType::HandleFeatureCollisions(
  	CUnit* collider,
- 	const float3& colliderCurPos,
- 	const float3& colliderOldPos,
  	const float colliderSpeed,
  	const float colliderRadius,
  	const float3& sepDirMask,
@@@ -1594,7 -1644,7 +1646,7 @@@
  ) {
  	const float searchRadius = std::max(colliderSpeed, 1.0f) * (colliderRadius * 2.0f);
  
- 	const std::vector<CFeature*>& nearFeatures = qf->GetFeaturesExact(colliderCurPos, searchRadius);
+ 	const std::vector<CFeature*>& nearFeatures = qf->GetFeaturesExact(collider->pos, searchRadius);
  	      std::vector<CFeature*>::const_iterator fit;
  
  	const int dirSign = int(!reversing) * 2 - 1;
@@@ -1602,14 -1652,13 +1654,13 @@@
  
  	for (fit = nearFeatures.begin(); fit != nearFeatures.end(); ++fit) {
  		CFeature* collidee = const_cast<CFeature*>(*fit);
+ 		// const FeatureDef* collideeFD = collidee->def;
  
- 	//	const FeatureDef* collideeFD = collidee->def;
- 		const float3& collideeCurPos = collidee->pos;
- 
- 	//	const float collideeRadius = FOOTPRINT_RADIUS(collideeFD->xsize, collideeFD->zsize);
- 		const float collideeRadius = FOOTPRINT_RADIUS(collidee  ->xsize, collidee  ->zsize);
+ 		// use the collidee's Feature (not FeatureDef) footprint
+ 		// const float collideeRadius = FOOTPRINT_RADIUS(collideeFD->xsize, collideeFD->zsize, 0.75f);
+ 		const float collideeRadius = FOOTPRINT_RADIUS(collidee->xsize, collidee->zsize, 0.75f);
  
- 		const float3 separationVector   = colliderCurPos - collideeCurPos;
+ 		const float3 separationVector   = collider->pos - collidee->pos;
  		const float separationMinDistSq = (colliderRadius + collideeRadius) * (colliderRadius + collideeRadius);
  
  		if ((separationVector.SqLength() - separationMinDistSq) > 0.01f)
@@@ -1638,23 -1687,27 +1689,29 @@@
  			c1 = (1.0f - math::fabs( collider->frontdir.dot(-sepDirection))) * 5.0f,
  			c2 = (1.0f - math::fabs(-collider->frontdir.dot( sepDirection))) * 5.0f,
  			s1 = m1 * v1 * c1,
- 			s2 = m2 * v2 * c2;
+ 			s2 = m2 * v2 * c2,
+  			r1 = s1 / (s1 + s2 + 1.0f),
+  			r2 = s2 / (s1 + s2 + 1.0f);
  
- 		const float collisionMassSum  = s1 + s2 + 1.0f;
- 		const float colliderMassScale = std::max(0.01f, std::min(0.99f, 1.0f - (s1 / collisionMassSum)));
- 	//	const float collideeMassScale = std::max(0.01f, std::min(0.99f, 1.0f - (s2 / collisionMassSum)));
+ 		const float colliderMassScale = std::max(0.01f, std::min(0.99f, 1.0f - r1));
+ 	//	const float collideeMassScale = std::max(0.01f, std::min(0.99f, 1.0f - r2));
  
  		if (collidee->reachedFinalPos) {
- 			const float3 colliderNxtPos = colliderCurPos + collider->speed;
- 			const CMoveMath::BlockType colliderCurPosBits = colliderMM->IsBlocked(*colliderMD, colliderCurPos);
- 			const CMoveMath::BlockType colliderNxtPosBits = colliderMM->IsBlocked(*colliderMD, colliderNxtPos);
+ 			CMoveMath::BlockType posBits;
+ 
+ 			if (collider->speed == ZeroVector)
+ 				continue;
  
- 			if ((colliderCurPosBits & CMoveMath::BLOCK_STRUCTURE) == 0)
+ 			posBits = colliderMM->IsBlocked(*colliderMD, collider->pos);
+ 
+ 			if ((posBits & CMoveMath::BLOCK_STRUCTURE) == 0)
  				continue;
 +			if (colliderNxtPos == colliderCurPos)
 +				continue;
  
- 			if ((colliderNxtPosBits & CMoveMath::BLOCK_STRUCTURE) != 0) {
+ 			posBits = colliderMM->IsBlocked(*colliderMD, collider->pos + collider->speed);
+ 
+ 			if ((posBits & CMoveMath::BLOCK_STRUCTURE) != 0) {
  				// applied every frame objects are colliding, so be careful
  				collider->AddImpulse(sepDirection * sepDirMask);
  
@@@ -1662,7 -1715,11 +1719,11 @@@
  				deltaSpeed = 0.0f;
  
  				if ((gs->frameNum > pathRequestDelay) && ((-sepDirection).dot(owner->frontdir * dirSign) >= 0.5f)) {
- 					StartMoving(goalPos, goalRadius, 0.0f);
+ 					if (OWNER_MOVE_CMD()) {
+ 						StartMoving(goalPos, goalRadius, 0.0f);
+ 					} else {
+ 						StartMoving(goalPos, goalRadius);
+ 					}
  				}
  			}
  		}
@@@ -1671,8 -1728,6 +1732,6 @@@
  	}
  }
  
- #undef FOOTPRINT_RADIUS
- 
  
  
  

-- 
advanced 3D real time strategy game engine



More information about the Pkg-games-commits mailing list