基本的に私がやろうとしているのは、非常に基本的なレイキャスティング システムを使用して 2D ハイトマップをシェーディングすることです。しかし、それは正しく機能しておらず、私はこれについて数時間頭を悩ませてきました.それを見て、または非常に複雑であるため、頭を悩ませることは決してありません。
私はこのような地図を持っています:
そして、レイキャスティングは私にこれを与えています(これは単なるデバッグ色であることに注意してください。赤はレイインターセプトですが、意図した位置の前(シェーディング)、青は正しい場所でのレイインターセプトです(ハイライトまたはそのまま)、そして黄色は、while ループのカットアウトの前に光線の相互作用がまったくなかったことを意味します)。
結果は、後ろ向きの斜面と大きな山の後ろの領域 (影) が赤になり、太陽に面した斜面 (ハイライト) が青になります。黄色があってはなりません。したがって、この画像は、すべての光線が間違った場所に当たっているか、光線がターゲットに到達する前に常に別の場所で交差していることを示していますが、これは不可能です。
この時点で、問題は私のトリガーにあると強く思います。
レイクラスは次のとおりです。
class Ray
{
public Vector2 Position;
public Vector2 Direction; // Think in XZ coordinates for these (they are on a perpendicular plane to the heightmap)
// Angle is angle from horizon (I think), and height is height above zero (arbitrary)
public float Angle, Height;
private TerrainUnit[,] Terrainmap;
private float U, V;
public Ray(ref TerrainUnit[,] Terrainmap, float height, float angle)
{
this.Terrainmap = Terrainmap;
this.Angle = angle;
this.Height = this.V = height;
// Create new straight vector
this.Direction = new Vector2(0, 1);
// Rotate it to the values determined by the angle
this.Direction = Vector2.Transform(Direction, Matrix.CreateRotationX(Angle));
//this.Direction = new Vector2((float)Math.Sin(angle), -(float)Math.Cos(angle));
// Find the horizontal distance of the origin-destination triangle
this.U = V / (float)Math.Tan(Angle);
// Bleh just initialize the vector to something
this.Position = new Vector2(U, V);
}
public void CastTo(int x, int y)
{
// Get the height of the target terrain unit
float H = (float)Terrainmap[x, y].Height;
// Find where the ray would have to be to intersect that terrain unit based on its angle and height
Position = new Vector2(x - U, H + V);
float Z = 1000 * (float)Terrainmap[0, y].Height;
// As long as the ray is not below the terrain and not past the destination point
while (Position.Y > Z && Position.X <= x)
{
// If the ray has passed into terrain bounds update Z every step
if (Position.X > 0) Z = 1000 * (float)Terrainmap[(int)Position.X, y].Height;
Position.X += Direction.X;
Position.Y += Direction.Y;
}
Terrainmap[x, y].TypeColor = Color.Yellow;
if ((int)Position.X == x) Terrainmap[x, y].TypeColor = Color.Blue;
else Terrainmap[x, y].TypeColor = Color.Red;
}
}
また、形式として、各レイをキャストしている関数と、それを呼び出す方法は次のとおりです。
if (lighting) CastSunRays(1f, MathHelper.PiOver4);
private void CastSunRays(float height, float angle)
{
Ray ray = new Ray(ref Terrainmap, height, angle);
for (int x = 0; x < Width; x++)
for (int y = 0; y < Height; y++)
ray.CastTo(x, y);
}