У меня есть код, который выполняет какой-то упрощенный c метод интерполяции треугольника, чтобы получить высоту от объекта, который находится внутри треугольника, я попытаюсь объяснить.
Способ тестирования высоты реализован на этот код сейчас заключается в том, что мы выясняем, на каком треугольнике ландшафта находится объект (из позиции X и Y), после нахождения треугольника мы получаем вершины треугольника, а затем используем интерполяцию для определения высоты определенная точка внутри этого треугольника, это можно увидеть в прикрепленном коде плохого поста ранее.
Это немного упрощенная c реализация тестирования высоты, и она не совпадает с клиентом, о чем я расскажу ниже.
Если они не совпадают, и клиент думает, что мы находимся под землей, тогда мы просто попадем под мир. Чтобы учесть это, мы взломали добавление смещения к высоте, чтобы предотвратить падение объекта через землю, как смещение + 0,5f или + 2,0f в зависимости от окружающего кода, но это добавляет недостаток игрока, который падает немного позже мигает на ровной поверхности.
На стороне сервера используется интерполяция треугольника, в то время как, используя мою текущую информацию после отладки, клиент использует пересечение сферической плоскости.
Идея состоит в том, чтобы улучшить код ниже в каким-то образом, вместо использования простой треугольной интерполяции, мы делаем пересечение сферической плоскости (aka barycentri c интерполяция), но в настоящее время никогда не приближаемся к чему-то подобному, возможно, переработка с другой формулой должна сделать эту работу?
float GridMap::getHeightFromFloat(float x, float y) const // 2D Given coords
{
if (!m_V8 || !m_V9) // No data given, just return standard height
return _gridHeight;
// MAX_NUMBER_OF_GRIDS = 64
// MAP_RESOLUTION = 128 | CENTER_GRID_ID = 32 | SIZE_OF_GRIDS = 533.3333f
x = MAP_RESOLUTION * (CENTER_GRID_ID - x / SIZE_OF_GRIDS);
y = MAP_RESOLUTION * (CENTER_GRID_ID - y / SIZE_OF_GRIDS);
int x_int = (int)x;
int y_int = (int)y;
x -= x_int;
y -= y_int;
x_int&=(MAP_RESOLUTION - 1);
y_int&=(MAP_RESOLUTION - 1);
// Height stored as: h5 - its v8 grid, h1-h4 - its v9 grid
// +--------------> X
// | h1-------h2 Coordinates is:
// | | \ 1 / | h1 0, 0 TOP LEFT
// | | \ / | h2 0, 1 TOP RIGHT
// | | 2 h5 3 | h3 1, 0 BOTTOM LEFT
// | | / \ | h4 1, 1 BOTTOM RIGHT
// | | / 4 \ | h5 1/2, 1/2 CENTER
// | h3-------h4
// V Y
// For find height need
// 1 - detect triangle
// 2 - solve linear equation from triangle points
// Calculate coefficients for solve h = a*x + b*y + c
// This is what our height data looks like
// 0 1 2 3 4 5 6 7 8 // v9 grid
// 9 10 11 12 13 14 15 16 // v8 grid
// 17 18 19 20 21 22 23 24 25 // v9 grid
// 26 27 28 29 30 31 32 33 // v8 grid
// 34 35 36 37 38 39 40 41 42 // v9 grid
// 43 44 45 46 47 48 49 50 // v8 grid
// 51 52 53 54 55 56 57 58 59 // v9 grid
// 60 61 62 63 64 65 66 67 // v8 grid
// 68 69 70 71 72 73 74 75 76 // v9 grid
// 77 78 79 80 81 82 83 84 // v8 grid
// 85 86 87 88 89 90 91 92 93 // v9 grid
// 94 95 96 97 98 99 100 101 // v8 grid
// 102 103 104 105 106 107 108 109 110 // v9 grid
// 111 112 113 114 115 116 117 118 // v8 grid
// 119 120 121 122 123 124 125 126 127 // v9 grid
// 128 129 130 131 132 133 134 135 // v8 grid
// 136 137 138 139 140 141 142 143 144 // v9 grid
float a, b, c;
// Select triangle:
if (x+y < 1)
{
if (x > y)
{
// 1 triangle (h1, h2, h5 points)
float topLeft = m_V9[(x_int)*129 + y_int]; // m_V9 = v9 grid (single corner) == 129 * 129
float topRight = m_V9[(x_int+1)*129 + y_int]; // m_V9 = v9 grid (single corner) == 129 * 129
float center = 2 * m_V8[x_int*128 + y_int]; // m_V8 = v8 grid (always center) == 128 * 128
a = topRight - topLeft;
b = center - topLeft - topRight;
c = topLeft;
}
else
{
// 2 triangle (h1, h3, h5 points)
float topLeft = m_V9[x_int*129 + y_int ]; // m_V9 = v9 grid (single corner) == 129 * 129
float bottomLeft = m_V9[x_int*129 + y_int+1]; // m_V9 = v9 grid (single corner) == 129 * 129
float center = 2 * m_V8[x_int*128 + y_int]; // m_V8 = v8 grid (always center) == 128 * 128
a = center - topLeft - bottomLeft;
b = bottomLeft - topLeft;
c = topLeft;
}
}
else
{
if (x > y)
{
// 3 triangle (h2, h4, h5 points)
float topRight = m_V9[(x_int+1)*129 + y_int ]; // m_V9 = v9 grid (single corner) == 129 * 129
float bottomRight = m_V9[(x_int+1)*129 + y_int+1]; // m_V9 = v9 grid (single corner) == 129 * 129
float center = 2 * m_V8[x_int*128 + y_int]; // m_V8 = v8 grid (always center) == 128 * 128
a = topRight + bottomRight - center;
b = bottomRight - topRight;
c = center - bottomRight;
}
else
{
// 4 triangle (h3, h4, h5 points)
float bottomLeft = m_V9[(x_int)*129 + y_int+1]; // m_V9 = v9 grid (single corner) == 129 * 129
float bottomRight = m_V9[(x_int+1)*129 + y_int+1]; // m_V9 = v9 grid (single corner) == 129 * 129
float center = 2 * m_V8[x_int*128 + y_int]; // m_V8 = v8 grid (always center) == 128 * 128
a = bottomRight - bottomLeft;
b = bottomLeft + bottomRight - center;
c = center - bottomRight;
}
}
// Calculate height
return a * x + b * y + c;
}