斜坡上的碰撞检查

| 我正在开发一款新游戏,并且正在尝试根据相对于坡度坐标的坐标来检测玩家(在坡度上)是否与给定的网格物体发生碰撞。我正在使用此功能,该功能似乎无效(坡度似乎太小或其他什么)
//Slopes



        float slopeY = max.Y-min.Y;

    float slopeZ = max.Z-min.Z;

    float slopeX = max.X-min.X;

    float angle = (float)Math.Atan(slopeZ/slopeY);

    //Console.WriteLine(OpenTK.Math.Functions.RadiansToDegrees((float)Math.Atan(slopeZ/slopeY)).ToString()+\" degrees incline\");



    slopeY = slopeY/slopeZ;

    float slopeZX = slopeY/slopeX;

    //End slopes

    float surfaceposX = max.X-coord.X;

    float surfaceposY = max.Y-coord.Y;

    float surfaceposZ = min.Z-coord.Z;



    min-=sval;

    max+=sval;

    //Surface coords



    //End surface coords



    //Y SHOULD = mx+b, where M = slope and X = surfacepos, and B = surfaceposZ



    if(coord.X<max.X& coord.X>min.X&coord.Y>min.Y&coord.Y<max.Y&coord.Z>min.Z&coord.Z<max.Z) {







        if(slopeY !=0) {

        Console.WriteLine(\"Slope = \"+slopeY.ToString()+\"SlopeZX=\"+slopeZX.ToString()+\" surfaceposZ=\"+surfaceposZ.ToString());

            Console.WriteLine(surfaceposY-(surfaceposY*slopeY));



            //System.Threading.Thread.Sleep(40000);



        if(surfaceposY-(surfaceposZ*slopeY)<3 || surfaceposY-(surfaceposX*slopeZX)<3) {

        return true;

        } else {

        return false;

        }

        } else {

        return true;

        }



    } else {





    return false;

    }
有什么建议么? 样本输出: 59.86697 6.225558 2761.331 68.3019度倾斜 59.86698,46.12445 59.86698 6.225558 2761.332 0度倾斜 编辑:部分解决了问题。斜坡检测有效,但是现在我可以穿过墙壁了???
//Slopes



        float slopeY = max.Y-min.Y;

    float slopeZ = max.Z-min.Z;

    float slopeX = max.X-min.X;

    float angle = (float)Math.Atan(slopeZ/slopeY);

    //Console.WriteLine(OpenTK.Math.Functions.RadiansToDegrees((float)Math.Atan(slopeZ/slopeY)).ToString()+\" degrees incline\");



    slopeY = slopeY/slopeZ;

    float slopey = slopeY+1/slopeZ;

    float slopeZX = slopeY/slopeX;

    //End slopes

    float surfaceposX = min.X-coord.X;

    float surfaceposY = max.Y-coord.Y;

    float surfaceposZ = min.Z-coord.Z;



    min-=sval;

    max+=sval;

    //Surface coords



    //End surface coords



    //Y SHOULD = mx+b, where M = slope and X = surfacepos, and B = surfaceposZ



    if(coord.X<max.X& coord.X>min.X&coord.Y>min.Y&coord.Y<max.Y&coord.Z>min.Z&coord.Z<max.Z) {







        if(slopeY !=0) {

        Console.WriteLine(\"Slope = \"+slopeY.ToString()+\"SlopeZX=\"+slopeZX.ToString()+\" surfaceposZ=\"+surfaceposZ.ToString());

            Console.WriteLine(surfaceposY-(surfaceposY*slopeY));



            //System.Threading.Thread.Sleep(40000);

         surfaceposZ = Math.Abs(surfaceposZ);



        if(surfaceposY>(surfaceposZ*slopeY) & surfaceposY-2<(surfaceposZ*slopeY) || surfaceposY>(surfaceposX*slopeZX) & surfaceposY-2<(surfaceposX*slopeZX)) {

        return true;

        } else {

        return false;

        }

        } else {

        return true;

        }



    } else {





    return false;

    }
    
已邀请:
您是否考虑过实施BSP树?即使您用现在使用的代码找出了错误,使用任何体面的大小/复杂度的网格也会使速度变慢。 BSP或四叉树在简化代码和提高性能方面将有很长的路要走,它们非常容易实现。 编辑 这是一个不错的BSP教程和概述的链接。 如果您只关注地形(没有垂直的墙壁,门等),则四叉树可能更合适: 这是gamedev.net上的一个不错的四叉树教程。 这两种算法都旨在将您的几何图形划分为一棵树,以使搜索更加容易。在您的情况下,您正在搜索多边形以进行碰撞。要构建BSP树(非常简短): 为树中的节点定义结构:
public class BspNode
{
    public List<Vector3> Vertices { get; set; }

    // plane equation coefficients
    float A, B, C, D;

    BspNode front;
    BspNode back;

    public BspNode(Vector3 v1, Vector3 v2, Vector3 v3)
    {
        Vertices = new List<Vector3>();
        Vertices.AddRange(new[] { v1, v2, v3 });
        GeneratePlaneEquationCoefficients();
    }

    void GeneratePlaneEquationCoefficients()
    {

        // derive the plane equation coefficients A,B,C,D from the input vertex list.
    }

    bool IsInFront(Vector3 point)
    {
        bool pointIsInFront=true;
        // substitute point.x/y/z into the plane equation and compare the result to D
        // to determine if the point is in front of or behind the partition plane.
        if (pointIsInFront && front!=null)
        {
            // POINT is in front of this node\'s plane, so check it against the front list.
            pointIsInFront = front.IsInFront(point);
        }
        else if (!pointIsInFront && back != null)
        {
            // POINT is behind this plane, so check it against the back list.
            pointIsInFront = back.IsInFront(point);
        }
        /// either POINT is in front and there are no front children,
        /// or POINT is in back and there are no back children. 
        /// Either way, recursion terminates here.
        return pointIsInFront;            
    }

    /// <summary>
    /// determines if the line segment defined by v1 and v2 intersects any geometry in the tree.
    /// </summary>
    /// <param name=\"v1\">vertex that defines the start of the ray</param>
    /// <param name=\"v2\">vertex that defines the end of the ray</param>
    /// <returns>true if the ray collides with the mesh</returns>
    bool SplitsRay(Vector3 v1, Vector3 v2)
    {

        var v1IsInFront = IsInFront(v1);
        var v2IsInFront = IsInFront(v2);
        var result = v1IsInFront!=v2IsInFront;

        if (!result)
        {
            /// both vertices are on the same side of the plane,
            /// so this node doesn\'t split anything. Check it\'s children.
            if (v1IsInFront && front != null)
                result =  front.SplitsRay(v1, v2);
            else if (!v1IsInFront && back != null)
                result = back.SplitsRay(v1, v2);
        }
        else
        {
            /// this plane splits the ray, but the intersection point may not be within the face boundaries.
            /// 1. calculate the intersection of the plane and the ray : intersection
            /// 2. create two new line segments: v1->intersection and intersection->v2
            /// 3. Recursively check those two segments against the rest of the tree.
            var intersection = new Vector3();

            /// insert code to magically calculate the intersection here.

            var frontSegmentSplits = false;
            var backSegmentSplits = false;


            if (front!=null)
            {
                if (v1IsInFront) frontSegmentSplits=front.SplitsRay(v1,intersection);
                else if (v2IsInFront) frontSegmentSplits=front.SplitsRay(v2,intersection);
            }
            if (back!=null)
            {
                if (!v1IsInFront) backSegmentSplits=back.SplitsRay(v1,intersection);
                else if (!v2IsInFront) backSegmentSplits=back.SplitsRay(v2,intersection);
            }

            result = frontSegmentSplits || backSegmentSplits;
        }

        return result;
    }
} 
从网格中选择一个“分区”平面(面),将其余的网格大致分为两部分。这对于复杂的几何图形而言要容易得多,因为完全凸出的项目(球体等)趋向于像列表而不是树。 从定义分区平面的顶点创建一个新的“ 3”实例。 将剩余的面分为两个列表-一个在分区平面的前面,另一个包含后面的面。 递归到步骤2,直到列表中没有更多节点为止。 检查碰撞时,有两个选择。 单点:通过调用根节点的ѭ4来检查角色或对象相对于树的坐标,如果该方法返回false,则目标点位于网格的“内部”,并且您已经相撞。如果该方法返回true,则目标点为网格的“外部”,并且没有发生碰撞。 射线相交。这个有点棘手。用对象的当前位置和目标位置调用根节点的“ 5”方法。如果方法返回“ 6”,则在两个位置之间移动将在网格中过渡。这是一种高级检查(尽管更为复杂),因为它可以捕获边缘情况,例如所需的移动将使一个步骤中的对象完全通过对象时。 我只是迅速地将这些示例代码放在一起。它不完整,甚至可能无法编译,但是它应该使您朝着正确的方向前进。 关于BSP的另一件好事:使用
.SplitsRay()
方法,您可以确定地图上的一个点是否可以从另一点看到。一些游戏使用它来确定NPC / AI是否可以看到对方或真正的玩家。您可以对此稍作修改,以确定他们是否可以听到彼此的走动等。 这似乎比您原来的方法要复杂得多,但最终它会变得更加强大和灵活。值得您花时间进行调查。     

要回复问题请先登录注册