平滑地形碰撞 - 3D

时间:2014-10-09 07:55:39

标签: java opengl collision smooth terrain

我想在我的游戏引擎中进行平滑的地形碰撞,当我说光滑时我的意思是玩家的高度不是由一个顶点决定的。我相信重心坐标是要走的路。我花了7个小时来研究这个问题,但是我所看到的代码中没有一个实际上有效,而且它也不能用简单的英语解释它。

到目前为止,这就是我所拥有的一切。 :(

public float getHeightAt(float xPos, float zPos) {
        Vector3f one = new Vector3f((float)xPos, ((float)new Color(heightMap.getRGB((int)xPos, (int)zPos)).getRed())/255f*exaggeration*scale, (float)zPos);
        Vector3f two = new Vector3f((float)xPos+1, ((float)new Color(heightMap.getRGB((int)xPos+1, (int)zPos)).getRed())/255f*exaggeration*scale, (float)zPos);
        Vector3f three = new Vector3f((float)xPos, ((float)new Color(heightMap.getRGB((int)xPos, (int)zPos+1)).getRed())/255f*exaggeration*scale, (float)zPos+1);

        float height = mid(one, two, three, new Vector3f(xPos, 0f, zPos));
        System.out.println(height);
        return height + 0.25f;
    }

    private float mid(Vector3f a, Vector3f b, Vector3f c, Vector3f p) {
        Vector3f AB = a.mul(b);
        Vector3f BC = b.mul(c);

        Vector3f norm = AB.cross(BC);
        float n0 = norm.getX();
        float n1 = norm.getY();
        float n2 = norm.getZ();

        return (n0*a.getX() + n1*a.getY() + n2*a.getZ() - n0*p.getX() - n2*p.getZ()) / n1;
    }

虽然有效,但它并不顺畅,我甚至不知道它是否是重心。

以下是我想要的示例:https://www.youtube.com/watch?v=ngJ6ISfXG3I

2 个答案:

答案 0 :(得分:0)

位置和坡度

球员位置可以由一个点确定。这里的情况是从高度图上的不同值创建一个相对平滑的函数。

插值应该可以解决问题。在最简单的情况下,它将在整个高度图上提供斜率。

双线性插值(四元组)

在任何时间点,palyer位于高度图的某个矩形(四边形)中。我们可以通过双线性插值来评估该矩形的任何点的高度。

我们对两个边上的一个轴进行此操作,然后对剩余边进行第二个轴。

^
| A--------B
| |        |
| | P      |
| |        |
| C--------D
Y 
*X------------>

// This could be different depending on how you get points
// (basically generates a [0, 1] value depending on the position in quad;
px = P.x - (int)P.x
py = P.y - (int)P.y
AB = A.h * (1.0 - px) + B.h * px;
CD = C.h * (1.0 - px) + D.h * px;
ABCD = AB * (1.0 - py) + CD * py;

ABCD是生成的高度

考虑

此方法并不完美,可能会产生视觉故障,具体取决于您在渲染管道中实际绘制四边形的方式。

另请注意,如果四边形比实际移动的演员更大,这种效果最佳。如果演员同时站在几个瓷砖上,则应使用某种平均方法。

答案 1 :(得分:0)

要获得平滑的高度,有两个主要步骤:

I - 创建一个从位置

获取高度的函数

按照以下说明创建函数public float getHeightAt(float xPos, float zPos)

  1. 检查相机/播放器是否在地面正方形

    if(xPos > 0 && xPos < nbVerticesX && zPos > 0 && zPos < nbVerticesZ) 
    
  2. 获取 P 最接近 xPos zPos

  3. 的点
  4. 获取正常 N 或计算

  5. 计算平面方程

    的常数 d
    double d = -(P.x * N.x + P.y * N.y + P.z * N.z);
    
  6. 返回计算高度

    return -(d + N.z * zPos + N.x * xPos)/N.y;
    
  7. II - 计算近似高度

    使用此功能获得平滑的高度:

    public float getHeightApprox(float x, float z)
    {
        return ( (getHeightAt(x,z)
                + getHeightAt(x + 1, z)
                + getHeightAt(x - 1, z)
                + getHeightAt(x, z + 1)
                + getHeightAt(x, z - 1)) / 5);
    }
    

    也许你必须调整你的代码,但这些代码对我来说很好。希望这会对你有所帮助。