Rewrite map_Height so that the height it reports matches with what the terrain renderer shows.

git-svn-id: svn+ssh://svn.gna.org/svn/warzone/trunk@6838 4a71c877-e1ca-e34f-864e-861f7616d084
master
Gerard Krol 2009-03-11 22:39:56 +00:00
parent da04dd5173
commit 380c32bb33
1 changed files with 78 additions and 119 deletions

197
src/map.c
View File

@ -1817,146 +1817,105 @@ BOOL mapShutdown(void)
return true; return true;
} }
/* Return linear interpolated height of x,y */ /// The height of the terrain at the specified world coordinates
extern SWORD map_Height(int x, int y) extern SWORD map_Height(int x, int y)
{ {
int retVal, tileX, tileY, tileYOffset, tileX2, tileY2Offset, dx, dy, ox, oy; int tileX, tileY;
int h0, hx, hy, hxy, wTL = 0, wTR = 0, wBL = 0, wBR = 0; int i, j;
BOOL bWaterTile = false; float height[2][2], center;
float onTileX, onTileY;
float left, right, middle;
float onBottom, result;
float towardsCenter, towardsRight;
ASSERT(x >= 0, "map_Height: Negative x value"); // make sure we have valid coordinates
ASSERT(y >= 0, "map_Height: Negative y value"); if (x < 0 ||
y < 0 ||
x >= world_coord(mapWidth-1) ||
y >= world_coord(mapHeight-1))
{
// we don't so give an arbitrary height
return 0;
}
x = (x >= world_coord(mapWidth) ? world_coord(mapWidth - 1) : x); // on which tile are these coords?
y = (y >= world_coord(mapHeight) ? world_coord(mapHeight - 1) : y);
/* Turn into tile coordinates */
tileX = map_coord(x); tileX = map_coord(x);
tileY = map_coord(y); tileY = map_coord(y);
/* Inter tile comp */ // where on the tile? (scale to (0,1))
ox = map_round(x); onTileX = (x - world_coord(tileX))/(float)world_coord(1);
oy = map_round(y); onTileY = (y - world_coord(tileY))/(float)world_coord(1);
if (terrainType(mapTile(tileX,tileY)) == TER_WATER) // get the height for the corners and center
center = 0;
for (i = 0; i < 2; i++)
{ {
bWaterTile = true; for (j = 0; j < 2; j++)
wTL = environGetValue(tileX,tileY)/2;
wTR = environGetValue(tileX+1,tileY)/2;
wBL = environGetValue(tileX,tileY+1)/2;
wBR = environGetValue(tileX+1,tileY+1)/2;
}
// to account for the border of the map
if(tileX + 1 < mapWidth)
{
tileX2 = tileX + 1;
}
else
{
tileX2 = tileX;
}
tileYOffset = (tileY * mapWidth);
if(tileY + 1 < mapHeight)
{
tileY2Offset = tileYOffset + mapWidth;
}
else
{
tileY2Offset = tileYOffset;
}
ASSERT( ox < TILE_UNITS, "mapHeight: x offset too big" );
ASSERT( oy < TILE_UNITS, "mapHeight: y offset too big" );
ASSERT( ox >= 0, "mapHeight: x offset too small" );
ASSERT( oy >= 0, "mapHeight: y offset too small" );
//different code for 4 different triangle cases
if (psMapTiles[tileX + tileYOffset].texture & TILE_TRIFLIP)
{
if ((ox + oy) > TILE_UNITS)//tile split top right to bottom left object if in bottom right half
{ {
ox = TILE_UNITS - ox; height[i][j] = map_TileHeight(tileX+i, tileY+j);
oy = TILE_UNITS - oy; center += height[i][j];
hy = psMapTiles[tileX + tileY2Offset].height;
hx = psMapTiles[tileX2 + tileYOffset].height;
hxy= psMapTiles[tileX2 + tileY2Offset].height;
if(bWaterTile)
{
hy+=wBL;
hx+=wTR;
hxy+=wBR;
}
dx = ((hy - hxy) * ox )/ TILE_UNITS;
dy = ((hx - hxy) * oy )/ TILE_UNITS;
retVal = (SDWORD)(((hxy + dx + dy)) * ELEVATION_SCALE);
ASSERT( retVal<MAX_HEIGHT,"Map height's gone weird!!!" );
return ((SWORD)retVal);
} }
else //tile split top right to bottom left object if in top left half }
center /= 4;
// we have:
// y ->
// x 0,0 A 0,1
// |
// V D center B
//
// 1,0 C 1,1
// get heights for left and right corners and the distances
if (onTileY > onTileX)
{
if (onTileY < 1 - onTileX)
{ {
h0 = psMapTiles[tileX + tileYOffset].height; // A
hy = psMapTiles[tileX + tileY2Offset].height; right = height[0][0];
hx = psMapTiles[tileX2 + tileYOffset].height; left = height[0][1];
towardsCenter = onTileX;
if(bWaterTile) towardsRight = 1 - onTileY;
{ }
h0+=wTL; else
hy+=wBL; {
hx+=wTR; // B
} right = height[0][1];
dx = ((hx - h0) * ox )/ TILE_UNITS; left = height[1][1];
dy = ((hy - h0) * oy )/ TILE_UNITS; towardsCenter = 1 - onTileY;
towardsRight = 1 - onTileX;
retVal = (SDWORD)((h0 + dx + dy) * ELEVATION_SCALE);
ASSERT( retVal<MAX_HEIGHT,"Map height's gone weird!!!" );
return ((SWORD)retVal);
} }
} }
else else
{ {
if (ox > oy) //tile split topleft to bottom right object if in top right half if (onTileX > 1 - onTileY)
{ {
h0 = psMapTiles[tileX + tileYOffset].height; // C
hx = psMapTiles[tileX2 + tileYOffset].height; right = height[1][1];
ASSERT( tileX2 + tileY2Offset < mapWidth*mapHeight, "array out of bounds"); left = height[1][0];
hxy= psMapTiles[tileX2 + tileY2Offset].height; towardsCenter = 1 - onTileX;
towardsRight = onTileY;
if(bWaterTile)
{
h0+=wTL;
hx+=wTR;
hxy+=wBR;
}
dx = ((hx - h0) * ox )/ TILE_UNITS;
dy = ((hxy - hx) * oy )/ TILE_UNITS;
retVal = (SDWORD)(((h0 + dx + dy)) * ELEVATION_SCALE);
ASSERT( retVal<MAX_HEIGHT,"Map height's gone weird!!!" );
return ((SWORD)retVal);
} }
else //tile split topleft to bottom right object if in bottom left half else
{ {
h0 = psMapTiles[tileX + tileYOffset].height; // D
hy = psMapTiles[tileX + tileY2Offset].height; right = height[1][0];
hxy = psMapTiles[tileX2 + tileY2Offset].height; left = height[0][0];
towardsCenter = onTileY;
if(bWaterTile) towardsRight = onTileX;
{
h0+=wTL;
hy+=wBL;
hxy+=wBR;
}
dx = ((hxy - hy) * ox )/ TILE_UNITS;
dy = ((hy - h0) * oy )/ TILE_UNITS;
retVal = (SDWORD)((h0 + dx + dy) * ELEVATION_SCALE);
ASSERT( retVal<MAX_HEIGHT,"Map height's gone weird!!!" );
return ((SWORD)retVal);
} }
} }
return 0; ASSERT(towardsCenter <= 0.5, "towardsCenter is too high");
// now we have:
// center
// left m right
middle = (left + right)/2;
onBottom = left * (1 - towardsRight) + right * towardsRight;
result = onBottom + (center - middle) * towardsCenter * 2;
return (SDWORD)(result+0.5f);
} }
/* returns true if object is above ground */ /* returns true if object is above ground */