c# - 二维高度图上的基本(假)光线转换

标签 c# xna raycasting terrain

基本上我想做的是使用非常非常基本的光线转换系统对 2D 高度图进行着色,该系统基本上只是在应该对光线进行着色之前检查光线是否被拦截。然而,它不能正常工作,我已经为此苦苦思索了几个小时,所以我认为把它交给你们也没什么坏处,因为我认为这可能是非常明显的事情,我不会看到它或如此复杂以至于我永远不会全神贯注。

我有这样一张 map : Map

光线转换给了我这个(记住它只是调试颜色;红色是光线拦截,但在预期位置之前(所以阴影),蓝色将是正确位置的光线拦截(所以高亮或原样), 黄色表示该点在 while 循环切断之前根本没有光线相互作用)。 Badx2

结果应该是在背面的斜坡和大山后面的区域(阴影)是红色的,在朝阳的斜坡(高光)是蓝色的。不应该有任何黄色。所以这张图片表明要么所有的光线都击中了错误的地方,要么光线在到达目标之前总是在其他地方相交,这是不可能的。

此时我高度怀疑问题出在我的触发器上。

这是 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);
    }

最佳答案

我最终使用了一种更简单的方法 Bresenham's Line Algorithm找到拦截点;我想它比我尝试做的方式更快、更有效。

关于c# - 二维高度图上的基本(假)光线转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6804664/

相关文章:

c++ - 看不懂HDU 2823的解决办法

c# - 带where条件的mvc 5 asp.net selectlist

c# - Blazor 中的 ElementReference 如何工作?

c# - linq匿名对象利用父对象属性和子对象属性

c# - 在属性 == true 中查找 List 的总和?

c# - 模型在 XNA 中显示为黑色

c++ - PixelToaster 库上的鼠标处理

unity3d - 将 XNA Shader channel 、混合和剔除模式移植到 Unity shaderlab 中

xna - XNA 中非常简单的菜单

javascript - 基于网格的环境中的 2D 光线转换