Java LWJGL - 3D模型的碰撞检测?

时间:2014-08-05 15:35:18

标签: java 3d collision-detection lwjgl

我正在使用LWJGL开发自己的小mmorpg游戏。到目前为止,我已经在我的游戏中输入了一只兔子,然后将他放在草地上方。像这样:

bunny placed above grass

我想要做的是让我在游戏中的对象能够与之交互。例如,点击它们会显示一些选项菜单,或者当你碰到它们时会发生一些事情。为此,我需要碰撞检测。我以前在2D游戏上使用过它,这简单得多。

这是我的Bunny.java类:

public class Bunny {


public static Model m = null;
public static int displayList;

public static void init() {

    displayList = glGenLists(1);
    glNewList(displayList, GL_COMPILE);
    {
        try {
            m = OBJLoader.loadModel(new File("res/models/bunny.obj"));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            Display.destroy();
            System.exit(1);
        } catch (IOException e) {
            e.printStackTrace();
            Display.destroy();
            System.exit(1);
        }

        glBegin(GL_TRIANGLES);

        for (Face face : m.faces) {
            Vector3f n1 = m.normals.get((int) face.normal.x - 1);
            glNormal3f(n1.x, n1.y, n1.z);
            Vector3f v1 = m.vertices.get((int) face.vertex.x - 1);
            glVertex3f(v1.x, v1.y, v1.z);
            Vector3f n2 = m.normals.get((int) face.normal.y - 1);
            glNormal3f(n2.x, n2.y, n2.z);
            Vector3f v2 = m.vertices.get((int) face.vertex.y - 1);
            glVertex3f(v2.x, v2.y, v2.z);
            Vector3f n3 = m.normals.get((int) face.normal.z - 1);
            glNormal3f(n3.x, n3.y, n3.z);
            Vector3f v3 = m.vertices.get((int) face.vertex.z - 1);
            glVertex3f(v3.x, v3.y, v3.z);
        }
        glEnd();

    }
    glEndList();

}

public static void draw(float x, float y, float z) {
    glPushMatrix();
    glTranslatef(x, y, z);
    glCallList(displayList);
    glPopMatrix();
}

}

我的主要课程:

public class Main {
public static float PlayerX = 0;
public static float PlayerY = 0;
public static float PlayerZ = 0;
public static float walkSpeed = 0.016f;
public static float PlayerRot = 0;

private static float[] lightPosition = {-2.19f, 1.36f, 11.45f, 1f};

public float pCenterX = 0;
public float pCenterY = 0;
public float pCenterZ = 0;

public static Model m = null;

public static void main(String[] args) {


    initDisplay();
    Bunny.init();
    gameLoop();
    cleanUp();
}


public static void gameLoop() {
    Texture tex = loadTexture("tex", "png");    
    Texture wood = loadTexture("wood", "png");

    loadLight();

    Camera camera = new Camera(70, (float) Display.getWidth() / (float) Display.getHeight(), 0.3f, 1000);

    while (!Display.isCloseRequested()) {



        if(Keyboard.isKeyDown(Keyboard.KEY_W)) camera.move(walkSpeed, 1);
        if(Keyboard.isKeyDown(Keyboard.KEY_S)) camera.move(-walkSpeed, 1);
        if(Keyboard.isKeyDown(Keyboard.KEY_A)) camera.rotateY(-0.1f);
        if(Keyboard.isKeyDown(Keyboard.KEY_D)) camera.rotateY(0.1f);
        if(Keyboard.isKeyDown(Keyboard.KEY_SPACE)) camera.moveY(0.05f, 1);
        if(Keyboard.isKeyDown(Keyboard.KEY_Z)) camera.moveY(0.05f, 0);


        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


//      glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
        glTranslatef(0, 2.5f, 0);

        glLoadIdentity();

        //camera.setX(-PlayerX); camera.setY(-PlayerY - 3); camera.setZ(-PlayerZ - 10);

        glLight(GL_LIGHT0, GL_POSITION, asFloatBuffer(new float[] {-2.19f, 1.36f, 11.45f, 1f}));

        camera.useView();

        //Draw.rect(PlayerX, PlayerY, PlayerZ, 0.5f, 0.5f, 0.5f, tex);
        Draw.rect(1, 0, 1, 100, 0.5f, 100, wood);

        Bunny.draw(10, 2.5f, 10);
        Bunny.draw(50, 2.5f, 50);

        Display.update();

    }
}


public static void cleanUp() {
    Display.destroy();
}

public static void initDisplay() {
    try {
        Display.setDisplayMode(new DisplayMode(800, 600));
        Display.create();
    } catch (LWJGLException e) {
        e.printStackTrace();
    }

}


public static Texture loadTexture(String key, String fileType) {

    try {
        return TextureLoader.getTexture(fileType, new FileInputStream(new File("res/img/" + key + "." + fileType)));
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

    return null;

}

private static FloatBuffer asFloatBuffer(float[] values) {
    FloatBuffer buffer = BufferUtils.createFloatBuffer(values.length);
    buffer.put(values);
    buffer.flip();
    return buffer;
}

public static void loadLight() {

    glShadeModel(GL_SMOOTH);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glLightModel(GL_LIGHT_MODEL_AMBIENT, asFloatBuffer(new float[] {0.05f, 0.05f, 0.05f, 1f}));
    glLight(GL_LIGHT0, GL_DIFFUSE, asFloatBuffer(new float[] {1.5f, 1.5f, 1.5f, 1f}));
    //glEnable(GL_CULL_FACE);
    //glCullFace(GL_BACK);
    glEnable(GL_COLOR_MATERIAL);
    glColorMaterial(GL_FRONT, GL_DIFFUSE);

}
}

如何获取兔子的分数,并使用算法中的分数来检测我们何时发生碰撞?

1 个答案:

答案 0 :(得分:0)

您已经在第一个代码段中显示了顶点的代码。所以你拥有它们。

至于问题的第二部分:你要找的是碰撞检测选择。在答案中覆盖它们太多了,所以你必须查找它们。

执行此操作的一种方法是场景图。

  • 每个对象都有一个包含所有点的边界框
  • 通过将对象连接到节点
  • 链接到场景图中的对象
  • 每个节点都有一个包含其子节点的所有框的边界框

这为您提供了树状结构。现在,您只需通过针对碰撞伙伴测试节点的边界框来检查是否发生了碰撞。如果它命中,则检查其子节点和对象是否发生碰撞。如果您有一个对象命中,则根据实际模型数据进行另一次检查。

对于普通对象,您可以使用其边界框和数据进行检查。对于拾取,您可以使用从鼠标点击的世界坐标点开的光线。

这只是为了做到这一点,但这个主题还有很多色调。例如,OpenGL提供自己的选择支持。