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

标签 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);

}
}

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

最佳答案

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

至于问题的第二部分:您正在寻找的是碰撞检测拾取。在答案中涵盖它们实在太多了,因此您必须查找它们。

做到这一点的一种方法是场景图。

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

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

对于普通对象,您可以使用它们的边界框和数据进行检查。为了进行拾取,您可以使用从鼠标单击的世界坐标中发射的光线。

这只是实现这一目标的方法,但该主题还有更多内容。例如,OpenGL 提供了自己的拾取支持。

关于Java LWJGL - 3D 模型上的碰撞检测?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25142812/

相关文章:

java - 如何在android中禁用系统对话框窗口或弹出窗口?

javascript - 在 THREE.Geometry 对象上设置顶点后,THREE.Shape.Utils.triangulateShape 失败并出现 TypeError

java - 简单的 3d 代码会抛出异常!

javascript - 需要。 JavaScript 3D 框架,具有帧速率和键盘事件的精确时间戳

ios - Sprite Kit 仅对屏幕左右边缘进行碰撞检测

c# - Unity 2D 碰撞检测不起作用

android - Android 中的碰撞检测

java - "Ant not recognized as an internal or external command"- 开发Spring应用教程

java - CoreNLP MaxentTagger 架构选项 - 含义和有效性

java - IBM Worklight 6.0 - 在 native Android 应用程序中调用 WL.Client.Login