为什么第二个方法调用会使java崩溃?

问题描述 投票:0回答:1

我正在使用 lwjgl 制作一个 java 3d 项目。

调用 Sphere.getVertices() 方法时,

Java 崩溃。但是当我尝试检测两个立方体之间的碰撞时,我看到黑屏没有任何组件,但是java不会崩溃。

日志

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00007ffbbedaa293, pid=2500, tid=1752
#
# JRE version: OpenJDK Runtime Environment Temurin-17.0.7+7 (17.0.7+7) (build 17.0.7+7)
# Java VM: OpenJDK 64-Bit Server VM Temurin-17.0.7+7 (17.0.7+7, mixed mode, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, windows-amd64)
# Problematic frame:
# C  [lwjgl_opengl.dll+0xa293]
#
# No core dump will be written. Minidumps are not enabled by default on client versions of Windows
#
# If you would like to submit a bug report, please visit:
#   https://github.com/adoptium/adoptium-support/issues
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#

---------------  S U M M A R Y ------------

Command Line: -XX:+ShowCodeDetailsInExceptionMessages Main

Host: Intel(R) Core(TM) i5-8265U CPU @ 1.60GHz, 8 cores, 7G,  Windows 10 , 64 bit Build 19041 (10.0.19041.3155)
Time: Tue Aug 22 12:57:53 2023 RTZ 2 (s 10 , 64 bit Build 19041 (10.0.19041.3155) elapsed time: 0.495254 seconds (0d 0h 0m 0s)

---------------  T H R E A D  ---------------

Current thread (0x000001bc95c0e1a0):  JavaThread "main" [_thread_in_native, id=1752, stack(0x000000481f200000,0x000000481f300000)]

Stack: [0x000000481f200000,0x000000481f300000],  sp=0x000000481f2ff4c8,  free space=1021k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C  [lwjgl_opengl.dll+0xa293]

Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j  org.lwjgl.opengl.GL11.glColor3f(FFF)V+0
j  Models.Sphere$1.<init>(LModels/Sphere;)V+21
j  Models.Sphere.getVertices()Ljava/util/ArrayList;+5
j  Engine.Component.checkColision(LEngine/Component;)Z+21
j  Main.main([Ljava/lang/String;)V+86
v  ~StubRoutines::call_stub

siginfo: EXCEPTION_ACCESS_VIOLATION (0xc0000005), reading address 0x00000000000000b0


Register to memory mapping:

RIP=0x00007ffbbedaa293 lwjgl_opengl.dll
RAX=0x000001bcb84a83e0 points into unknown readable memory: 0x0000000000000000 | 00 00 00 00 00 00 00 00
RBX={method} {0x000001bcb4704b78} 'glColor3f' '(FFF)V' in 'org/lwjgl/opengl/GL11'
RCX=0x0 is NULL
RDX=0x000000481f2ff560 is pointing into the stack for thread: 0x000001bc95c0e1a0
RSP=0x000000481f2ff4c8 is pointing into the stack for thread: 0x000001bc95c0e1a0
RBP=0x000000481f2ff550 is pointing into the stack for thread: 0x000001bc95c0e1a0
RSI=0x000001bcb4007c98 is pointing into metadata
RDI=0x0000000000009c1a is an unknown value
R8 =0x0000000000000002 is an unknown value
R9 =0x0000000000000002 is an unknown value
R10=0x000001bca4c3d5f2 is at code_begin+946 in an Interpreter codelet
method entry point (kind = native)  [0x000001bca4c3d240, 0x000001bca4c3dbc0]  2432 bytes
R11=0x00000000894524c0 is an oop: java.lang.Class 
{0x00000000894524c0} - klass: 'java/lang/Class']

Component.java代码:

import java.util.ArrayList;
import java.util.List;

import org.joml.Matrix4f;
import org.joml.Vector3f;


public abstract class Component {
    private Vector3f pos = new Vector3f(0, 0, 0);
    private Vector3f rotate = new Vector3f(0, 0, 0);
    private Vector3f scale = new Vector3f(1, 1, 1);

    public boolean checkColision(Component component) {
        ArrayList<Vector3f> transformedVertices = transformVertices(getVertices(), pos, rotate, scale);
        ArrayList<Vector3f> componentTransformedVertices = transformVertices(component.getVertices(), component.getPos(), component.getRotate(), component.getScale()); //The problem is probably here.


        Vector3f max = new Vector3f(Float.MIN_VALUE, Float.MIN_VALUE, Float.MIN_VALUE);
        Vector3f min = new Vector3f(Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE);

        for(Vector3f vertex : transformedVertices) {
            if(vertex.x > max.x) max.x = vertex.x;
            if(vertex.y > max.y) max.y = vertex.y;
            if(vertex.z > max.z) max.z = vertex.z;

            if(vertex.x < min.x) min.x = vertex.x;
            if(vertex.y < min.y) min.y = vertex.y;
            if(vertex.z < min.z) min.z = vertex.z;
        }

        Vector3f componentMax = new Vector3f(Float.MIN_VALUE, Float.MIN_VALUE, Float.MIN_VALUE);
        Vector3f componentMin = new Vector3f(Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE);

        for(Vector3f vertex : componentTransformedVertices) {
            if(vertex.x > componentMax.x) componentMax.x = vertex.x;
            if(vertex.y > componentMax.y) componentMax.y = vertex.y;
            if(vertex.z > componentMax.z) componentMax.z = vertex.z;

            if(vertex.x < componentMin.x) componentMin.x = vertex.x;
            if(vertex.y < componentMin.y) componentMin.y = vertex.y;
            if(vertex.z < componentMin.z) componentMin.z = vertex.z;
        }

        if (max.x <= componentMin.x || min.x >= componentMax.x) return false;
        if (max.y <= componentMin.y || min.y >= componentMax.y) return false;
        if (max.z <= componentMin.z || min.z >= componentMax.z) return false;
        return true;
    }

//some getters and setters.

    public abstract ArrayList<Vector3f> getVertices(); //returns an arraylist of object vertex coordinates for collision detection.

    private synchronized static ArrayList<Vector3f> transformVertices(ArrayList<Vector3f> vertices, Vector3f position, Vector3f rotation, Vector3f scale) {
        ArrayList<Vector3f> transformedVertices = new ArrayList<>();
        Matrix4f transformationMatrix = new Matrix4f()
            .translate(position)
            .rotateX((float) Math.toRadians(rotation.x))
            .rotateY((float) Math.toRadians(rotation.y))
            .rotateZ((float) Math.toRadians(rotation.z))
            .scale(scale);

        for (Vector3f vertex : vertices) {
            Vector3f transformedVertex = new Vector3f(vertex);
            transformedVertex.mulPosition(transformationMatrix);
            transformedVertices.add(transformedVertex);
        }

        return transformedVertices;
    }
}

Sphere.java代码:

package Models;

import Engine.Component;
import org.lwjgl.opengl.GL11;

import static org.lwjgl.opengl.GL11.*;

import java.util.ArrayList;

import org.joml.Vector3f;

public class Sphere extends Component {
    public float radius = 1.0f;
    public int gradation = 100;
    public final float PI = (float) Math.PI;
    @Override
    public void draw() {
        float x, y, z, alpha, beta;
        for (alpha = 0.0f; alpha < Math.PI; alpha += PI / gradation) {
            glBegin(GL_TRIANGLE_STRIP);
            GL11.glColor3f(0.7f, 0.7f, 0.7f);
            for (beta = 0.0f; beta < 2.01f * Math.PI; beta += PI / gradation) {
                x = (float) (radius * Math.cos(beta) * Math.sin(alpha));
                y = (float) (radius * Math.sin(beta) * Math.sin(alpha));
                z = (float) (radius * Math.cos(alpha));
                glTexCoord2f(beta / (2.0f * PI), alpha / PI);
                glVertex3f(x, y, z);
                x = (float) (radius * Math.cos(beta) * Math.sin(alpha + PI / gradation));
                y = (float) (radius * Math.sin(beta) * Math.sin(alpha + PI / gradation));
                z = (float) (radius * Math.cos(alpha + PI / gradation));
                glTexCoord2f(beta / (2.0f * PI), alpha / PI + 1.0f / gradation);
                glVertex3f(x, y, z);
            }
            glEnd();
        }
    }
    @Override
    public ArrayList<Vector3f> getVertices() {
        return new ArrayList<Vector3f>() {{
            float x, y, z, alpha, beta;
            for (alpha = 0.0f; alpha < Math.PI; alpha += PI / gradation) {
                GL11.glColor3f(0.7f, 0.7f, 0.7f);
                for (beta = 0.0f; beta < 2.01f * Math.PI; beta += PI / gradation) {
                    x = (float) (radius * Math.cos(beta) * Math.sin(alpha));
                    y = (float) (radius * Math.sin(beta) * Math.sin(alpha));
                    z = (float) (radius * Math.cos(alpha));
                    glTexCoord2f(beta / (2.0f * PI), alpha / PI);
                    add(new Vector3f(x, y, z));
                    x = (float) (radius * Math.cos(beta) * Math.sin(alpha + PI / gradation));
                    y = (float) (radius * Math.sin(beta) * Math.sin(alpha + PI / gradation));
                    z = (float) (radius * Math.cos(alpha + PI / gradation));
                    glTexCoord2f(beta / (2.0f * PI), alpha / PI + 1.0f / gradation);
                    add(new Vector3f(x, y, z));
                }
            }
        }};
    }
}

Cube.java代码:

package Models;

import Engine.Component;

import java.util.ArrayList;

import org.joml.Vector3f;
import org.lwjgl.opengl.GL11;

public class Cube extends Component {
    public float size = 1.0f;
    @Override
    public void draw() {
        GL11.glBegin(GL11.GL_QUADS);
        GL11.glColor3f(0.7f, 0.7f, 0.7f);

        GL11.glVertex3f(-size, size, -size);
        GL11.glVertex3f(size, size, -size);
        GL11.glVertex3f(size, size, size);
        GL11.glVertex3f(-size, size, size);

        GL11.glVertex3f(-size, -size, -size);
        GL11.glVertex3f(-size, -size, size);
        GL11.glVertex3f(size, -size, size);
        GL11.glVertex3f(size, -size, -size);

        GL11.glVertex3f(-size, -size, size);
        GL11.glVertex3f(-size, size, size);
        GL11.glVertex3f(size, size, size);
        GL11.glVertex3f(size, -size, size);

        GL11.glVertex3f(-size, -size, -size);
        GL11.glVertex3f(size, -size, -size);
        GL11.glVertex3f(size, size, -size);
        GL11.glVertex3f(-size, size, -size);

        GL11.glVertex3f(-size, -size, -size);
        GL11.glVertex3f(-size, -size, size);
        GL11.glVertex3f(-size, size, size);
        GL11.glVertex3f(-size, size, -size);

        GL11.glVertex3f(size, -size, -size);
        GL11.glVertex3f(size, size, -size);
        GL11.glVertex3f(size, size, size);
        GL11.glVertex3f(size, -size, size);

        GL11.glEnd();
    }

    @Override
    public ArrayList<Vector3f> getVertices() {
        return new ArrayList<Vector3f>() {{
            add(new Vector3f(-size, size, -size));
            add(new Vector3f(size, size, -size));
            add(new Vector3f(size, size, size));
            add(new Vector3f(-size, size, size));
            add(new Vector3f(-size, -size, -size));
            add(new Vector3f(-size, -size, size));
            add(new Vector3f(size, -size, size));
            add(new Vector3f(size, -size, -size));
            add(new Vector3f(-size, -size, size));
            add(new Vector3f(-size, size, size));
            add(new Vector3f(size, size, size));
            add(new Vector3f(size, -size, size));
            add(new Vector3f(-size, -size, -size));
            add(new Vector3f(size, -size, -size));
            add(new Vector3f(size, size, -size));
            add(new Vector3f(-size, size, -size));
            add(new Vector3f(-size, -size, -size));
            add(new Vector3f(-size, -size, size));
            add(new Vector3f(-size, size, size));
            add(new Vector3f(-size, size, -size));
            add(new Vector3f(size, -size, -size));
            add(new Vector3f(size, size, -size));
            add(new Vector3f(size, size, size));
            add(new Vector3f(size, -size, size));
        }};
    }
}

我希望有一个方法,当跨越对象边界时返回 true,而不是崩溃

java collision-detection lwjgl java-17 joml
1个回答
0
投票

看来您在使用 LWJGL 的 Java 3D 项目中面临着挑战。您遇到的崩溃似乎源于

Sphere
类的
getVertices
方法中某些不适当的 OpenGL 使用。让我们一步步解决这个问题:

第 1 步: 细化

Sphere
类的
getVertices
方法,仅专注于构造顶点数据,而不需要任何 OpenGL 调用:

@Override
public ArrayList<Vector3f> getVertices() {
    ArrayList<Vector3f> vertices = new ArrayList<>();
    float x, y, z, alpha, beta;
    for (alpha = 0.0f; alpha < Math.PI; alpha += PI / gradation) {
        for (beta = 0.0f; beta < 2.01f * Math.PI; beta += PI / gradation) {
            x = (float) (radius * Math.cos(beta) * Math.sin(alpha));
            y = (float) (radius * Math.sin(beta) * Math.sin(alpha));
            z = (float) (radius * Math.cos(alpha));
            vertices.add(new Vector3f(x, y, z));
            x = (float) (radius * Math.cos(beta) * Math.sin(alpha + PI / gradation));
            y = (float) (radius * Math.sin(beta) * Math.sin(alpha + PI / gradation));
            z = (float) (radius * Math.cos(alpha + PI / gradation));
            vertices.add(new Vector3f(x, y, z));
        }
    }
    return vertices;
}

第 2 步: 在渲染循环中,一定要在渲染对象之前设置 OpenGL 状态(包括颜色)。这是 OpenGL 调用合适的地方:

while (!glfwWindowShouldClose(window)) {
    // Clear the buffer
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // Set OpenGL state, e.g., color
    glColor3f(0.7f, 0.7f, 0.7f);

    // Render objects
    // ...

    // Swap the buffer
    glfwSwapBuffers(window);
    glfwPollEvents();
}

通过分离设置 OpenGL 状态和渲染调用的过程,您应该能够防止与 OpenGL 使用不当相关的问题。这种方法应该有助于减轻您在项目中遇到的崩溃。如果问题仍然存在,您可能会考虑探索可能解决该问题的 LWJGL 或 OpenGL 驱动程序的潜在更新。有时,有缺陷或过时的驱动程序会导致一系列错误,因此请务必进行检查。

© www.soinside.com 2019 - 2024. All rights reserved.