The following commit has been merged in the master branch:
commit 6549151f12ba8e1e4fb4f42053e158645714a0ec
Merge: dedf638f08729cdf4e64da73db8cc171a8473cd4 
e26fce3a64c58bfdc9723ee221ba10ea34ad6ca1
Author: Jan Dittberner <[email protected]>
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

_______________________________________________
Pkg-games-commits mailing list
[email protected]
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-games-commits

Reply via email to