我正在寻找一些数学帮助。我有一个游戏是生成2D高度图,然后使用长度/方向公式在球体上拉伸。现在我需要知道如何计算高度图上2点之间的高度。
我所知道的:
我的问题看起来有点像:
红色和蓝色线是2个高度图点,浅蓝色是我想要计算高度的位置。
这是我当前的代码,但它不能很好地工作。
public double getheight(double angle)
{
//find out angle between 2 heightmap point
double offset = MathHelper.TwoPi / (heightmap.Length - 1);
//total brainfart attempt
double lowerAngle = offset * angle;
double upperAngle = offset * angle + offset;
//find heights
double height1 = heightmap[(int)lowerAngle];
double height2 = heightmap[(int)upperAngle];
//find offset angle
double u = angle - lowerAngle / (upperAngle - lowerAngle);
//return the height
return height1 + (height1 - height2) * u;
}
从我的植被代码中,这似乎工作正常,但是对于单位等用途是粗略的,因为它们在移动时上下移动,因为它仅使用1个高度图点。
double[] hMap = planet.getHeightMap();
double i = hMap.Length / (Math.PI * 2);
this.height = hMap[(int)(angle * i)];
答案 0 :(得分:1)
编辑:基于其他问题信息的结尾示例
对我来说就像一个线性插值 - 如果你从二维视角看它,你有两点:
(x1, y1) = point one on heightmap
(x2, y2) = point two on heightmap
在(x1,x2)
之间某处未知高度的地方:
pu = (xu, yu)
LERP的通用公式是:
pu = p0 + (p1 - p0) * u
其中:
p0
=第一个值p1
=第二个值u
=%,其中您的未知点位于(p0,p1)
在这里,我们会说p0
== y2
和p1
== y1
。现在我们需要确定x1
和x2
之间未知点的“距离” - 如果您知道两个高度图点的角度,这很容易:
u = ang(xu) - ang(x1) / (ang(x2) - ang(x1))
或者,你可以将你的角度投射到Max(y1,y2)
并以这种方式得到“未知的x pos”,然后计算上面的。
所以,让我们尝试一个人为的例子:
p1 = point one in map = (1,2) therefore ang(p1) ~ 57 degrees
p2 = point two in map = (2,4) therefore ang(p2) ~ 114 degrees
请注意,这里“x轴”沿球体表面,“y轴”是距离中心的距离。
pu = object location = py @angle 100 degrees ~ 1.74 radians
px = (1.74 rad - 1 rad ) / (2 rad - 1 rad) = 0.74 / 1.0 = 0.74 => 74%
py = y0 + (y1 - y0) * u
= 2 + (4 - 2) * 0.74
= 2.96
希望我没有在某处丢弃或错放标志......:)
好的,你的示例代码 - 我稍微调了一下,这就是我想出的:
首先,让我们定义一些自己的帮手:
public static class MathHelper
{
public const double TwoPi = Math.PI * 2.0;
public static double DegToRad(double deg)
{
return (TwoPi / 360.0) * deg;
}
public static double RadToDeg(double rad)
{
return (360.0 / TwoPi) * rad;
}
// given an upper/lower bounds, "clamp" the value into that
// range, wrapping over to lower if higher than upper, and
// vice versa
public static int WrapClamp(int value, int lower, int upper)
{
return value > upper ? value - upper - 1
: value < lower ? upper - value - 1
: value;
}
}
我们的测试设置:
void Main()
{
var random = new Random();
// "sea level"
var baseDiameter = 10;
// very chaotic heightmap
heightmap = Enumerable
.Range(0, 360)
.Select(_ => random.NextDouble() * baseDiameter)
.ToArray();
// let's walk by half degrees, since that's roughly how many points we have
for(double i=0;i<360;i+=0.5)
{
var angleInDegrees = i;
var angleInRads = MathHelper.DegToRad(i);
Console.WriteLine("Height at angle {0}°({1} rad):{2} (using getheight:{3})",
angleInDegrees,
angleInRads,
heightmap[(int)angleInDegrees],
getheight(angleInRads));
}
}
double[] heightmap;
我们的“getheight”方法:
// assume: input angle is in radians
public double getheight(double angle)
{
//find out angle between 2 heightmap point
double dTheta = MathHelper.TwoPi / (heightmap.Length);
// our "offset" will be how many dThetas we are
double offset = angle / dTheta;
// Figure out two reference points in heightmap
// THESE MAY BE THE SAME POINT, if angle ends up
// landing on a heightmap index!
int lowerAngle = (int)offset;
int upperAngle = (int)Math.Round(
offset,
0,
MidpointRounding.AwayFromZero);
// find closest heightmap points to angle, wrapping
// around if we go under 0 or over max
int closestPointIndex = MathHelper.WrapClamp(
lowerAngle,
0,
heightmap.Length-1);
int nextPointIndex = MathHelper.WrapClamp(
upperAngle,
0,
heightmap.Length-1);
//find heights
double height1 = heightmap[closestPointIndex];
double height2 = heightmap[nextPointIndex];
// percent is (distance from angle to closest angle) / (angle "step" per heightmap point)
double percent = (angle - (closestPointIndex * dTheta)) / dTheta;
// find lerp height = firstvalue + (diff between values) * percent
double lerp = Math.Abs(height1 + (height2 - height1) * percent);
// Show what we're doing
Console.WriteLine("Delta ang:{0:f3}, Offset={1:f3} => compare indices:[{2}, {3}]",
dTheta,
offset,
closestPointIndex,
nextPointIndex);
Console.WriteLine("Lerping {0:p} between heights {1:f4} and {2:f4} - lerped height:{3:f4}",
percent,
height1,
height2,
lerp);
return lerp;
}