mirror of https://github.com/OpenTTD/OpenTTD
(svn r27351) [1.5] -Backport from trunk:
- Fix: Do not rerandomise the town name when only cost-estimating the founding [FS#6332] (r27341) - Fix: Make variety distribution not assume that sea level is at height 0.2 / 3 * TGPGetMaxHeight() [FS#6335] (r27331, r27330, r27329, r27328) - Fix: Remove corner-case optimisation for line drawing, which failed for dashed lines (r27324) - Fix: Clipping of inclined lines did not account for the 'horizontal width' being bigger than the 'real width' (r27323, r27322)release/1.5
parent
5e34e09891
commit
d96bfbde1d
37
src/gfx.cpp
37
src/gfx.cpp
|
@ -175,40 +175,35 @@ static inline void GfxDoDrawLine(void *video, int x, int y, int x2, int y2, int
|
||||||
|
|
||||||
assert(width > 0);
|
assert(width > 0);
|
||||||
|
|
||||||
if (y2 == y) {
|
if (y2 == y || x2 == x) {
|
||||||
/* Special case: horizontal line. */
|
/* Special case: horizontal/vertical line. All checks already done in GfxPreprocessLine. */
|
||||||
blitter->DrawLine(video,
|
blitter->DrawLine(video, x, y, x2, y2, screen_width, screen_height, colour, width, dash);
|
||||||
Clamp(x, 0, screen_width), y,
|
|
||||||
Clamp(x2, 0, screen_width), y2,
|
|
||||||
screen_width, screen_height, colour, width, dash);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (x2 == x) {
|
|
||||||
/* Special case: vertical line. */
|
|
||||||
blitter->DrawLine(video,
|
|
||||||
x, Clamp(y, 0, screen_height),
|
|
||||||
x2, Clamp(y2, 0, screen_height),
|
|
||||||
screen_width, screen_height, colour, width, dash);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int grade_y = y2 - y;
|
int grade_y = y2 - y;
|
||||||
int grade_x = x2 - x;
|
int grade_x = x2 - x;
|
||||||
|
|
||||||
|
/* Clipping rectangle. Slightly extended so we can ignore the width of the line. */
|
||||||
|
uint extra = CeilDiv(3 * width, 4); // not less then "width * sqrt(2) / 2"
|
||||||
|
Rect clip = { -extra, -extra, screen_width - 1 + extra, screen_height - 1 + extra };
|
||||||
|
|
||||||
/* prevent integer overflows. */
|
/* prevent integer overflows. */
|
||||||
int margin = 1;
|
int margin = 1;
|
||||||
while (INT_MAX / abs(grade_y) < max(abs(x), abs(screen_width - x))) {
|
while (INT_MAX / abs(grade_y) < max(abs(clip.left - x), abs(clip.right - x))) {
|
||||||
grade_y /= 2;
|
grade_y /= 2;
|
||||||
grade_x /= 2;
|
grade_x /= 2;
|
||||||
margin *= 2; // account for rounding errors
|
margin *= 2; // account for rounding errors
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the line is outside the screen on the same side at X positions 0
|
/* Imagine that the line is infinitely long and it intersects with
|
||||||
* and screen_width, we don't need to draw anything. */
|
* infinitely long left and right edges of the clipping rectangle.
|
||||||
int offset_0 = y - x * grade_y / grade_x;
|
* If both intersection points are outside the clipping rectangle
|
||||||
int offset_width = y + (screen_width - x) * grade_y / grade_x;
|
* and both on the same side of it, we don't need to draw anything. */
|
||||||
if ((offset_0 > screen_height + width / 2 + margin && offset_width > screen_height + width / 2 + margin) ||
|
int left_isec_y = y + (clip.left - x) * grade_y / grade_x;
|
||||||
(offset_0 < -width / 2 - margin && offset_width < -width / 2 - margin)) {
|
int right_isec_y = y + (clip.right - x) * grade_y / grade_x;
|
||||||
|
if ((left_isec_y > clip.bottom + margin && right_isec_y > clip.bottom + margin) ||
|
||||||
|
(left_isec_y < clip.top - margin && right_isec_y < clip.top - margin)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
26
src/tgp.cpp
26
src/tgp.cpp
|
@ -538,7 +538,7 @@ static void HeightMapSineTransform(height_t h_min, height_t h_max)
|
||||||
*/
|
*/
|
||||||
static void HeightMapCurves(uint level)
|
static void HeightMapCurves(uint level)
|
||||||
{
|
{
|
||||||
int mh = TGPGetMaxHeight();
|
height_t mh = TGPGetMaxHeight() - I2H(1); // height levels above sea level only
|
||||||
|
|
||||||
/** Basically scale height X to height Y. Everything in between is interpolated. */
|
/** Basically scale height X to height Y. Everything in between is interpolated. */
|
||||||
struct control_point_t {
|
struct control_point_t {
|
||||||
|
@ -547,10 +547,10 @@ static void HeightMapCurves(uint level)
|
||||||
};
|
};
|
||||||
/* Scaled curve maps; value is in height_ts. */
|
/* Scaled curve maps; value is in height_ts. */
|
||||||
#define F(fraction) ((height_t)(fraction * mh))
|
#define F(fraction) ((height_t)(fraction * mh))
|
||||||
const control_point_t curve_map_1[] = { { F(0.0), F(0.0) }, { F(0.6 / 3), F(0.1) }, { F(2.4 / 3), F(0.4 / 3) }, { F(1.0), F(0.4) } };
|
const control_point_t curve_map_1[] = { { F(0.0), F(0.0) }, { F(0.8), F(0.13) }, { F(1.0), F(0.4) } };
|
||||||
const control_point_t curve_map_2[] = { { F(0.0), F(0.0) }, { F(0.2 / 3), F(0.1) }, { F(1.6 / 3), F(0.4 / 3) }, { F(2.4 / 3), F(0.8 / 3) }, { F(1.0), F(0.6) } };
|
const control_point_t curve_map_2[] = { { F(0.0), F(0.0) }, { F(0.53), F(0.13) }, { F(0.8), F(0.27) }, { F(1.0), F(0.6) } };
|
||||||
const control_point_t curve_map_3[] = { { F(0.0), F(0.0) }, { F(0.2 / 3), F(0.1) }, { F(1.6 / 3), F(0.8 / 3) }, { F(2.4 / 3), F(1.8 / 3) }, { F(1.0), F(0.8) } };
|
const control_point_t curve_map_3[] = { { F(0.0), F(0.0) }, { F(0.53), F(0.27) }, { F(0.8), F(0.57) }, { F(1.0), F(0.8) } };
|
||||||
const control_point_t curve_map_4[] = { { F(0.0), F(0.0) }, { F(0.2 / 3), F(0.1) }, { F(1.2 / 3), F(0.9 / 3) }, { F(2.0 / 3), F(2.4 / 3) } , { F(5.5 / 6), F(0.99) }, { F(1.0), F(0.99) } };
|
const control_point_t curve_map_4[] = { { F(0.0), F(0.0) }, { F(0.4), F(0.3) }, { F(0.7), F(0.8) }, { F(0.92), F(0.99) }, { F(1.0), F(0.99) } };
|
||||||
#undef F
|
#undef F
|
||||||
|
|
||||||
/** Helper structure to index the different curve maps. */
|
/** Helper structure to index the different curve maps. */
|
||||||
|
@ -628,10 +628,17 @@ static void HeightMapCurves(uint level)
|
||||||
|
|
||||||
height_t *h = &_height_map.height(x, y);
|
height_t *h = &_height_map.height(x, y);
|
||||||
|
|
||||||
|
/* Do not touch sea level */
|
||||||
|
if (*h < I2H(1)) continue;
|
||||||
|
|
||||||
|
/* Only scale above sea level */
|
||||||
|
*h -= I2H(1);
|
||||||
|
|
||||||
/* Apply all curve maps that are used on this tile. */
|
/* Apply all curve maps that are used on this tile. */
|
||||||
for (uint t = 0; t < lengthof(curve_maps); t++) {
|
for (uint t = 0; t < lengthof(curve_maps); t++) {
|
||||||
if (!HasBit(corner_bits, t)) continue;
|
if (!HasBit(corner_bits, t)) continue;
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
const control_point_t *cm = curve_maps[t].list;
|
const control_point_t *cm = curve_maps[t].list;
|
||||||
for (uint i = 0; i < curve_maps[t].length - 1; i++) {
|
for (uint i = 0; i < curve_maps[t].length - 1; i++) {
|
||||||
const control_point_t &p1 = cm[i];
|
const control_point_t &p1 = cm[i];
|
||||||
|
@ -639,13 +646,18 @@ static void HeightMapCurves(uint level)
|
||||||
|
|
||||||
if (*h >= p1.x && *h < p2.x) {
|
if (*h >= p1.x && *h < p2.x) {
|
||||||
ht[t] = p1.y + (*h - p1.x) * (p2.y - p1.y) / (p2.x - p1.x);
|
ht[t] = p1.y + (*h - p1.x) * (p2.y - p1.y) / (p2.x - p1.x);
|
||||||
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
assert(found);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Apply interpolation of curve map results. */
|
/* Apply interpolation of curve map results. */
|
||||||
*h = (height_t)((ht[corner_a] * yri + ht[corner_b] * yr) * xri + (ht[corner_c] * yri + ht[corner_d] * yr) * xr);
|
*h = (height_t)((ht[corner_a] * yri + ht[corner_b] * yr) * xri + (ht[corner_c] * yri + ht[corner_d] * yr) * xr);
|
||||||
|
|
||||||
|
/* Readd sea level */
|
||||||
|
*h += I2H(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -869,13 +881,13 @@ static void HeightMapNormalize()
|
||||||
HeightMapSmoothCoasts(water_borders);
|
HeightMapSmoothCoasts(water_borders);
|
||||||
HeightMapSmoothSlopes(roughness);
|
HeightMapSmoothSlopes(roughness);
|
||||||
|
|
||||||
HeightMapSineTransform(12, h_max_new);
|
HeightMapSineTransform(I2H(1), h_max_new);
|
||||||
|
|
||||||
if (_settings_game.game_creation.variety > 0) {
|
if (_settings_game.game_creation.variety > 0) {
|
||||||
HeightMapCurves(_settings_game.game_creation.variety);
|
HeightMapCurves(_settings_game.game_creation.variety);
|
||||||
}
|
}
|
||||||
|
|
||||||
HeightMapSmoothSlopes(16);
|
HeightMapSmoothSlopes(I2H(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1113,7 +1113,8 @@ public:
|
||||||
bool success = DoCommandP(tile, this->town_size | this->city << 2 | this->town_layout << 3 | random << 6,
|
bool success = DoCommandP(tile, this->town_size | this->city << 2 | this->town_layout << 3 | random << 6,
|
||||||
townnameparts, CMD_FOUND_TOWN | CMD_MSG(errstr), cc, name);
|
townnameparts, CMD_FOUND_TOWN | CMD_MSG(errstr), cc, name);
|
||||||
|
|
||||||
if (success) this->RandomTownName();
|
/* Rerandomise name, if success and no cost-estimation. */
|
||||||
|
if (success && !_shift_pressed) this->RandomTownName();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void OnClick(Point pt, int widget, int click_count)
|
virtual void OnClick(Point pt, int widget, int click_count)
|
||||||
|
|
Loading…
Reference in New Issue