По сути, я пытаюсь закрасить 2D карту высот, используя очень простую систему лучевого вещания, которая в основном просто проверяет, перехватывается ли луч, прежде чем его затенять.Однако это не работает должным образом, и я уже несколько часов бьюсь головой об этом, поэтому я подумал, что не повредит передать это вам, ребята, потому что я думаю, что это, возможно, что-то настолько ослепительно очевидное, что я не будувижу это или так сложно, что я никогда не буду оборачиваться вокруг него.
У меня есть такая карта: ![Map](https://i.stack.imgur.com/cjenD.png)
И радиовещание дает мне это (имейте в виду, что этопросто отладка цветов, красный - это перехват лучей, но перед намеченным положением (таким образом, затенение), синий будет перехватывать лучи в правильном месте (таким образом, выделение или просто как есть), а желтый означает, что точка вообще не имела взаимодействия лучей допока петля вырезана).![Badx2](https://i.stack.imgur.com/dK9rS.png)
Результат должен быть с красным на откосных склонах и участках за большими горами (тени) и синим на солнечных склонах (блики).Там не должно быть никакого желтого цвета.Таким образом, это изображение указывает, что либо все лучи попадают в неправильное место, либо лучи пересекаются ВСЕГДА где-то еще, прежде чем они достигнут своей цели, что невозможно.
На данный момент я подозреваю, что проблема заключается в том, чтос моим тригоном.
Вот класс Ray:
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);
}