[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