在Android下使用OpenGLES 2.0的基于像素的碰撞检测问题

时间:2011-09-02 15:16:46

标签: android opengl-es-2.0


这是我在这里发表的第一篇文章,因此对任何大错都道歉 我正在开发一个使用OpenGL ES 2.0和Android 2.3的简单动作游戏。我目前正在研究的游戏框架基于二维精灵,它存在于三维世界中。当然,我的世界实体拥有诸如虚拟世界中的位置,float []矩阵形式的旋转值,OpenGL纹理句柄以及Android的Bitmap句柄等信息(我不确定后者是否是必要的,因为我正在做使用OpenGl机器的光栅化,但暂时它就在那里,为了我的方便)。现在简要介绍问题的背景 目前我坚持使用基于像素的碰撞检测,因为我不确定我需要采样哪个对象(这里是OGL纹理或Android Bitmap)。我的意思是,我已经尝试过对Android的Bitmap进行采样,但它完全不适用于我 - 许多运行时崩溃与位图外部的读取有关。当然为了能够从位图读取像素,我使用了 Bitmap.create 方法来获得正确旋转的精灵。这是代码段:

android.graphics.Matrix m = new android.graphics.Matrix();
if(o1.angle != 0.0f) {          
    m.setRotate(o1.angle);
    b1 = Bitmap.createBitmap(b1, 0, 0, b1.getWidth(), b1.getHeight(), m, false);
}

另一个问题,可能会增加问题,甚至是主要问题,是我的交叉矩形(指示两个对象的两维空间的矩形)是从两个边界框的部分构建的,这两个边界框是用使用OpenGL矩阵 Matrix.multiplyMV 功能(下面的代码)。可能是,这两个Android和OpenGL矩阵的计算方法不相等吗?

Matrix.rotateM(mtxRotate, 0, -angle, 0, 0, 1);

// original bitmap size, equal to sprite size in it's model space,
// as well as in world's space
float[] rect = new float[] {
    origRect.left, origRect.top, 0.0f, 1.0f, 
    origRect.right, origRect.top, 0.0f, 1.0f,
    origRect.left, origRect.bottom, 0.0f, 1.0f,
    origRect.right, origRect.bottom, 0.0f, 1.0f 
};

android.opengl.Matrix.multiplyMV(rect, 0, mtxRotate, 0, rect, 0);
android.opengl.Matrix.multiplyMV(rect, 4, mtxRotate, 0, rect, 4);
android.opengl.Matrix.multiplyMV(rect, 8, mtxRotate, 0, rect, 8);
android.opengl.Matrix.multiplyMV(rect, 12, mtxRotate, 0, rect, 12);

// computation of object's bounding box (it is necessary as object has been
// rotated second ago and now it's bounding rectangle doesn't match it's host
float left = rect[0];
float top = rect[1];
float right = rect[0];
float bottom = rect[1];
for(int i = 4; i < 16; i += 4) {
    left = Math.min(left, rect[i]);
    top = Math.max(top, rect[i+1]);
    right = Math.max(right, rect[i]);
    bottom = Math.min(bottom, rect[i+1]);
};

1 个答案:

答案 0 :(得分:0)

干杯,

首先请注意您的代码中存在错误。你不能使用与源和目标向量相同的Matrix.multiplyMV()(该函数将正确计算它将在源向量中覆盖的x坐标。但是,它需要原始x来计算y,z和w坐标 - 反过来又有缺陷)。另请注意,在第一次检测碰撞步骤中使用边界球会更容易,因为它们不需要如此复杂的代码来执行矩阵变换。

然后,碰撞检测。你不应该从位图和纹理中读取。你应该做的是为你的对象建立一个轮廓(这很简单,轮廓只是一个位置列表)。之后,您需要构建填充(非凸)轮廓的凸起对象。它可以通过例如实现。耳剪切算法。它可能不是最快的,但它很容易实现,只能完成一次。一旦你有了凸面物体,就可以使用矩阵变换它们的坐标并检测与你的世界的碰撞(你可以使用许多关于光线三角形交叉点的好文章),你得到的精度就像你使用像素一样基于碰撞检测。

我希望它有所帮助...