mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2025-03-12 10:30:28 +00:00
(svn r21883) -Codechange: make UpdateZPosition() faster by not calling GetSlopeZ() when not needed
This commit is contained in:
parent
e860075a16
commit
8b9f0d5ade
@ -148,16 +148,73 @@ struct GroundVehicle : public SpecializedVehicle<T, Type> {
|
|||||||
/**
|
/**
|
||||||
* Updates vehicle's Z position.
|
* Updates vehicle's Z position.
|
||||||
* Inclination can't change in the middle of a tile.
|
* Inclination can't change in the middle of a tile.
|
||||||
|
* The faster code is used for trains and road vehicles unless they are
|
||||||
|
* reversing on a sloped tile.
|
||||||
*/
|
*/
|
||||||
FORCEINLINE void UpdateZPosition()
|
FORCEINLINE void UpdateZPosition()
|
||||||
{
|
{
|
||||||
/* Vehicle's Z position can change only if it has GVF_GOINGUP_BIT or GVF_GOINGDOWN_BIT set */
|
#if 0
|
||||||
if (HasBit(this->gv_flags, GVF_GOINGUP_BIT) || HasBit(this->gv_flags, GVF_GOINGDOWN_BIT)) {
|
/* The following code does this: */
|
||||||
this->z_pos = GetSlopeZ(this->x_pos, this->y_pos);
|
|
||||||
} else {
|
if (HasBit(this->gv_flags, GVF_GOINGUP_BIT)) {
|
||||||
/* Verify that assumption. */
|
switch (this->direction) {
|
||||||
assert(this->z_pos == GetSlopeZ(this->x_pos, this->y_pos));
|
case DIR_NE:
|
||||||
|
this->z_pos += (this->x_pos & 1); break;
|
||||||
|
case DIR_SW:
|
||||||
|
this->z_pos += (this->x_pos & 1) ^ 1; break;
|
||||||
|
case DIR_NW:
|
||||||
|
this->z_pos += (this->y_pos & 1); break;
|
||||||
|
case DIR_SE:
|
||||||
|
this->z_pos += (this->y_pos & 1) ^ 1; break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
} else if (HasBit(this->gv_flags, GVF_GOINGDOWN_BIT)) {
|
||||||
|
switch (this->direction) {
|
||||||
|
case DIR_NE:
|
||||||
|
this->z_pos -= (this->x_pos & 1); break;
|
||||||
|
case DIR_SW:
|
||||||
|
this->z_pos -= (this->x_pos & 1) ^ 1; break;
|
||||||
|
case DIR_NW:
|
||||||
|
this->z_pos -= (this->y_pos & 1); break;
|
||||||
|
case DIR_SE:
|
||||||
|
this->z_pos -= (this->y_pos & 1) ^ 1; break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* But gcc 4.4.5 isn't able to nicely optimise it, and the resulting
|
||||||
|
* code is full of conditional jumps. */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Vehicle's Z position can change only if it has GVF_GOINGUP_BIT or GVF_GOINGDOWN_BIT set.
|
||||||
|
* Furthermore, if this function is called once every time the vehicle's position changes,
|
||||||
|
* we know the Z position changes by +/-1 at certain moments - when x_pos, y_pos is odd/even,
|
||||||
|
* depending on orientation of the slope and vehicle's direction */
|
||||||
|
|
||||||
|
if (HasBit(this->gv_flags, GVF_GOINGUP_BIT) || HasBit(this->gv_flags, GVF_GOINGDOWN_BIT)) {
|
||||||
|
if (T::From(this)->HasToUseGetSlopeZ()) {
|
||||||
|
/* In some cases, we have to use GetSlopeZ() */
|
||||||
|
this->z_pos = GetSlopeZ(this->x_pos, this->y_pos);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* DirToDiagDir() is a simple right shift */
|
||||||
|
DiagDirection dir = DirToDiagDir(this->direction);
|
||||||
|
/* Read variables, so the compiler knows the access doesn't trap */
|
||||||
|
int8 x_pos = this->x_pos;
|
||||||
|
int8 y_pos = this->y_pos;
|
||||||
|
/* DiagDirToAxis() is a simple mask */
|
||||||
|
int8 d = DiagDirToAxis(dir) == AXIS_X ? x_pos : y_pos;
|
||||||
|
/* We need only the least significant bit */
|
||||||
|
d &= 1;
|
||||||
|
/* Conditional "^ 1". Optimised to "(dir - 1) <= 1". */
|
||||||
|
d ^= (int8)(dir == DIAGDIR_SW || dir == DIAGDIR_SE);
|
||||||
|
/* Subtraction instead of addition because we are testing for GVF_GOINGUP_BIT.
|
||||||
|
* GVF_GOINGUP_BIT is used because it's bit 0, so simple AND can be used,
|
||||||
|
* without any shift */
|
||||||
|
this->z_pos += HasBit(this->gv_flags, GVF_GOINGUP_BIT) ? d : -d;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(this->z_pos == GetSlopeZ(this->x_pos, this->y_pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -262,6 +262,36 @@ protected: // These functions should not be called outside acceleration code.
|
|||||||
|
|
||||||
return trackbits == TRACK_BIT_X || trackbits == TRACK_BIT_Y;
|
return trackbits == TRACK_BIT_X || trackbits == TRACK_BIT_Y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Road vehicles have to use GetSlopeZ() to compute their height
|
||||||
|
* if they are reversing because in that case, their direction
|
||||||
|
* is not parallel with the road. It is safe to return \c true
|
||||||
|
* even if it is not reversing.
|
||||||
|
* @return are we (possibly) reversing?
|
||||||
|
*/
|
||||||
|
FORCEINLINE bool HasToUseGetSlopeZ()
|
||||||
|
{
|
||||||
|
const RoadVehicle *rv = this->First();
|
||||||
|
|
||||||
|
/* Check if this vehicle is in the same direction as the road under.
|
||||||
|
* We already know it has either GVF_GOINGUP_BIT or GVF_GOINGDOWN_BIT set. */
|
||||||
|
|
||||||
|
if (rv->state <= RVSB_TRACKDIR_MASK && IsReversingRoadTrackdir((Trackdir)rv->state)) {
|
||||||
|
/* If the first vehicle is reversing, this vehicle may be reversing too
|
||||||
|
* (especially if this is the first, and maybe the only, vehicle).*/
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (rv != this) {
|
||||||
|
/* If any previous vehicle has different direction,
|
||||||
|
* we may be in the middle of reversing. */
|
||||||
|
if (this->direction != rv->direction) return true;
|
||||||
|
rv = rv->Next();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#define FOR_ALL_ROADVEHICLES(var) FOR_ALL_VEHICLES_OF_TYPE(RoadVehicle, var)
|
#define FOR_ALL_ROADVEHICLES(var) FOR_ALL_VEHICLES_OF_TYPE(RoadVehicle, var)
|
||||||
|
10
src/train.h
10
src/train.h
@ -380,6 +380,16 @@ protected: // These functions should not be called outside acceleration code.
|
|||||||
/* Any track that isn't TRACK_BIT_X or TRACK_BIT_Y cannot be sloped. */
|
/* Any track that isn't TRACK_BIT_X or TRACK_BIT_Y cannot be sloped. */
|
||||||
return this->track == TRACK_BIT_X || this->track == TRACK_BIT_Y;
|
return this->track == TRACK_BIT_X || this->track == TRACK_BIT_Y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trains can always use the faster algorithm because they
|
||||||
|
* have always the same direction as the track under them.
|
||||||
|
* @return false
|
||||||
|
*/
|
||||||
|
FORCEINLINE bool HasToUseGetSlopeZ()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#define FOR_ALL_TRAINS(var) FOR_ALL_VEHICLES_OF_TYPE(Train, var)
|
#define FOR_ALL_TRAINS(var) FOR_ALL_VEHICLES_OF_TYPE(Train, var)
|
||||||
|
Loading…
Reference in New Issue
Block a user