Fix #472 (fixed-point CTerrain::GetExactGroundLevel), based on patch from JubJub
This was SVN commit r7443.
This commit is contained in:
parent
c02771fef2
commit
2f34e5fbc6
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2009 Wildfire Games.
|
||||
/* Copyright (C) 2010 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -340,6 +340,26 @@ float CTerrain::GetExactGroundLevel(float x, float z) const
|
||||
+ zf * ((1 - xf) * h01 + xf * h11)));
|
||||
}
|
||||
|
||||
CFixed_23_8 CTerrain::GetExactGroundLevelFixed(CFixed_23_8 x, CFixed_23_8 z) const
|
||||
{
|
||||
// Clamp to size-2 so we can use the tiles (xi,zi)-(xi+1,zi+1)
|
||||
const ssize_t xi = clamp((ssize_t)(x/CELL_SIZE).ToInt_RoundToZero(), (ssize_t)0, m_MapSize-2);
|
||||
const ssize_t zi = clamp((ssize_t)(z/CELL_SIZE).ToInt_RoundToZero(), (ssize_t)0, m_MapSize-2);
|
||||
|
||||
const CFixed_23_8 one = CFixed_23_8::FromInt(1);
|
||||
|
||||
const CFixed_23_8 xf = clamp((x/CELL_SIZE)-CFixed_23_8::FromInt(xi), CFixed_23_8::FromInt(0), one);
|
||||
const CFixed_23_8 zf = clamp((z/CELL_SIZE)-CFixed_23_8::FromInt(zi), CFixed_23_8::FromInt(0), one);
|
||||
|
||||
u16 h00 = m_Heightmap[zi*m_MapSize + xi];
|
||||
u16 h01 = m_Heightmap[(zi+1)*m_MapSize + xi];
|
||||
u16 h10 = m_Heightmap[zi*m_MapSize + (xi+1)];
|
||||
u16 h11 = m_Heightmap[(zi+1)*m_MapSize + (xi+1)];
|
||||
// Linearly interpolate
|
||||
return ((one - zf).Multiply((one - xf) * h00 + xf * h10)
|
||||
+ zf.Multiply((one - xf) * h01 + xf * h11)) / HEIGHT_UNITS_PER_METRE;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Resize: resize this terrain to the given size (in patches per side)
|
||||
void CTerrain::Resize(ssize_t size)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2009 Wildfire Games.
|
||||
/* Copyright (C) 2010 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -23,6 +23,7 @@
|
||||
#define INCLUDED_TERRAIN
|
||||
|
||||
#include "maths/Vector3D.h"
|
||||
#include "maths/Fixed.h"
|
||||
#include "graphics/SColor.h"
|
||||
#include "lib/sysdep/cpu.h"
|
||||
|
||||
@ -80,6 +81,7 @@ public:
|
||||
|
||||
float GetVertexGroundLevel(ssize_t i, ssize_t j) const;
|
||||
float GetExactGroundLevel(float x, float z) const;
|
||||
CFixed_23_8 GetExactGroundLevelFixed(CFixed_23_8 x, CFixed_23_8 z) const;
|
||||
float GetExactGroundLevel(const CVector2D& v) const;
|
||||
|
||||
float GetSlope(float x, float z) const ;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2009 Wildfire Games.
|
||||
/* Copyright (C) 2010 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -22,6 +22,7 @@
|
||||
#include "graphics/Patch.h"
|
||||
#include "graphics/RenderableObject.h"
|
||||
#include "maths/FixedVector3D.h"
|
||||
#include "maths/Fixed.h"
|
||||
|
||||
class TestTerrain : public CxxTest::TestSuite
|
||||
{
|
||||
@ -53,7 +54,73 @@ class TestTerrain : public CxxTest::TestSuite
|
||||
|
||||
}
|
||||
|
||||
void SetHighPlateau(CTerrain& terrain, int height)
|
||||
{
|
||||
SetVertex(terrain, 4, 0, 100 + height*CELL_SIZE*HEIGHT_UNITS_PER_METRE);
|
||||
SetVertex(terrain, 4, 1, 100 + height*CELL_SIZE*HEIGHT_UNITS_PER_METRE);
|
||||
SetVertex(terrain, 4, 2, 100 + height*CELL_SIZE*HEIGHT_UNITS_PER_METRE);
|
||||
SetVertex(terrain, 5, 0, 100 + height*CELL_SIZE*HEIGHT_UNITS_PER_METRE);
|
||||
SetVertex(terrain, 5, 1, 100 + height*CELL_SIZE*HEIGHT_UNITS_PER_METRE);
|
||||
SetVertex(terrain, 5, 2, 100 + height*CELL_SIZE*HEIGHT_UNITS_PER_METRE);
|
||||
}
|
||||
|
||||
public:
|
||||
void test_GetExactGroundLevel()
|
||||
{
|
||||
CTerrain terrain;
|
||||
terrain.Initialize(4, NULL);
|
||||
Set45Slope(terrain);
|
||||
SetHighPlateau(terrain, 20);
|
||||
|
||||
float ground;
|
||||
|
||||
ground = terrain.GetExactGroundLevel(0.f, 1.5f*CELL_SIZE);
|
||||
TS_ASSERT_DELTA(ground, 100.f/HEIGHT_UNITS_PER_METRE, 0.01f);
|
||||
|
||||
ground = terrain.GetExactGroundLevel(0.5f*CELL_SIZE, 1.5f*CELL_SIZE);
|
||||
TS_ASSERT_DELTA(ground, 100.f/HEIGHT_UNITS_PER_METRE+0.5f*CELL_SIZE, 0.01f);
|
||||
|
||||
ground = terrain.GetExactGroundLevel(1.5f*CELL_SIZE, 1.5f*CELL_SIZE);
|
||||
TS_ASSERT_DELTA(ground, 100.f/HEIGHT_UNITS_PER_METRE+1.5f*CELL_SIZE, 0.01f);
|
||||
|
||||
ground = terrain.GetExactGroundLevel(2.5f*CELL_SIZE, 1.5f*CELL_SIZE);
|
||||
TS_ASSERT_DELTA(ground, 100.f/HEIGHT_UNITS_PER_METRE+2.f*CELL_SIZE, 0.01f);
|
||||
|
||||
ground = terrain.GetExactGroundLevel(3.5f*CELL_SIZE, 1.5f*CELL_SIZE);
|
||||
TS_ASSERT_DELTA(ground, 100.f/HEIGHT_UNITS_PER_METRE+11.f*CELL_SIZE, 0.01f);
|
||||
|
||||
ground = terrain.GetExactGroundLevel(4.5f*CELL_SIZE, 1.5f*CELL_SIZE);
|
||||
TS_ASSERT_DELTA(ground, 100.f/HEIGHT_UNITS_PER_METRE+20.f*CELL_SIZE, 0.01f);
|
||||
}
|
||||
|
||||
void test_GetExactGroundLevelFixed()
|
||||
{
|
||||
CTerrain terrain;
|
||||
terrain.Initialize(4, NULL);
|
||||
Set45Slope(terrain);
|
||||
SetHighPlateau(terrain, 20);
|
||||
|
||||
CFixed_23_8 ground;
|
||||
|
||||
ground = terrain.GetExactGroundLevelFixed(CFixed_23_8::FromFloat(0.f), CFixed_23_8::FromFloat(1.5f*CELL_SIZE));
|
||||
TS_ASSERT_DELTA(ground.ToFloat(), 100.f/HEIGHT_UNITS_PER_METRE, 0.01f);
|
||||
|
||||
ground = terrain.GetExactGroundLevelFixed(CFixed_23_8::FromFloat(0.5f*CELL_SIZE), CFixed_23_8::FromFloat(1.5f*CELL_SIZE));
|
||||
TS_ASSERT_DELTA(ground.ToFloat(), 100.f/HEIGHT_UNITS_PER_METRE+0.5f*CELL_SIZE, 0.01f);
|
||||
|
||||
ground = terrain.GetExactGroundLevelFixed(CFixed_23_8::FromFloat(1.5f*CELL_SIZE), CFixed_23_8::FromFloat(1.5f*CELL_SIZE));
|
||||
TS_ASSERT_DELTA(ground.ToFloat(), 100.f/HEIGHT_UNITS_PER_METRE+1.5f*CELL_SIZE, 0.01f);
|
||||
|
||||
ground = terrain.GetExactGroundLevelFixed(CFixed_23_8::FromFloat(2.5f*CELL_SIZE), CFixed_23_8::FromFloat(1.5f*CELL_SIZE));
|
||||
TS_ASSERT_DELTA(ground.ToFloat(), 100.f/HEIGHT_UNITS_PER_METRE+2.f*CELL_SIZE, 0.01f);
|
||||
|
||||
ground = terrain.GetExactGroundLevelFixed(CFixed_23_8::FromFloat(3.5f*CELL_SIZE), CFixed_23_8::FromFloat(1.5f*CELL_SIZE));
|
||||
TS_ASSERT_DELTA(ground.ToFloat(), 100.f/HEIGHT_UNITS_PER_METRE+11.f*CELL_SIZE, 0.01f);
|
||||
|
||||
ground = terrain.GetExactGroundLevelFixed(CFixed_23_8::FromFloat(4.5f*CELL_SIZE), CFixed_23_8::FromFloat(1.5f*CELL_SIZE));
|
||||
TS_ASSERT_DELTA(ground.ToFloat(), 100.f/HEIGHT_UNITS_PER_METRE+20.f*CELL_SIZE, 0.01f);
|
||||
}
|
||||
|
||||
void test_CalcNormal()
|
||||
{
|
||||
CTerrain terrain;
|
||||
|
@ -60,10 +60,7 @@ public:
|
||||
|
||||
virtual entity_pos_t GetGroundLevel(entity_pos_t x, entity_pos_t z)
|
||||
{
|
||||
float height = m_Terrain->GetExactGroundLevel(x.ToFloat(), z.ToFloat());
|
||||
// TODO: get rid of floats
|
||||
|
||||
return entity_pos_t::FromFloat(height);
|
||||
return m_Terrain->GetExactGroundLevelFixed(x, z);
|
||||
}
|
||||
|
||||
virtual float GetGroundLevel(float x, float z)
|
||||
|
Loading…
Reference in New Issue
Block a user