java - 这个光线转换算法正确吗?这是测试线/射线和立方体相交的正确方法吗?

标签 java 3d geometry raytracing

我正在构建一个 LWJGL 程序来测试一个立方体是否在相机前面。我认为它有效,但我得到了很多不同的数字。我在想这是因为平面会永远持续下去,而且它们不是有限的正方形。我该怎么做才能解决这个问题? (我还注意到我的代码相当慢,这可能是什么原因造成的???)

这是我的路口代码:

public static float getCubeInteresection(Cube b, Vector3f camera, Vector3f lookat)
{
    Vector3f l = b.Location;
    float boxs = 0.5f;
    Plane3f[] bplanes = Plane3f.getBoxDefaults(l, boxs);
    Vector3f result = null;
    for (int t = 0; t < bplanes.length; t++)
    {
        Vector3f raytrace = getIntersection(camera, lookat,bplanes[t].Point0,bplanes[t].Point1,bplanes[t].Point2);
        if (raytrace != null)
        {
            result = raytrace;
            break;
        }
    }
    if (result == null)
        return -1.0f; //not hit, waste of time... lol
    float x = (float) Math.pow(result.x - camera.x, 2);
    float y = (float) Math.pow(result.y - camera.y, 2);
    float z = (float) Math.pow(result.z - camera.z, 2);
    float dist = (float) Math.sqrt(x + y + z);
    return dist;
}
private static Vector3f getIntersection(Vector3f line12, Vector3f line22,Vector3f plane12, Vector3f plane22, Vector3f plane32)
{
    javax.vecmath.Vector3f plane1 = new javax.vecmath.Vector3f(plane12.x,plane12.y,plane12.z);
    javax.vecmath.Vector3f plane2 = new javax.vecmath.Vector3f(plane22.x,plane22.y,plane22.z);
    javax.vecmath.Vector3f plane3 = new javax.vecmath.Vector3f(plane32.x,plane32.y,plane32.z);
    javax.vecmath.Vector3f line1 = new javax.vecmath.Vector3f(line12.x,line12.y,line12.z);
    javax.vecmath.Vector3f line2 = new javax.vecmath.Vector3f(line22.x,line22.y,line22.z);
    javax.vecmath.Vector3f p1 = new javax.vecmath.Vector3f(plane1);
    javax.vecmath.Vector3f p2 = new javax.vecmath.Vector3f(plane2);
    javax.vecmath.Vector3f p3 = new javax.vecmath.Vector3f(plane3);
    javax.vecmath.Vector3f p2minusp1 = new javax.vecmath.Vector3f(p2);
    p2minusp1.sub(p1);
    javax.vecmath.Vector3f p3minusp1 = new javax.vecmath.Vector3f(p3);
    p3minusp1.sub(p1);
    javax.vecmath.Vector3f normal = new javax.vecmath.Vector3f();
    normal.cross(p2minusp1, p3minusp1);
    double d = -p1.dot(normal);
    javax.vecmath.Vector3f i1 = new javax.vecmath.Vector3f(line1);
    javax.vecmath.Vector3f direction = new javax.vecmath.Vector3f(line1);
    direction.sub(line2);
    double dot = direction.dot(normal);
    if (dot == 0) return null;
    double t = (-d - i1.dot(normal)) / (dot);
    javax.vecmath.Vector3f intersection = new javax.vecmath.Vector3f(line1);
    javax.vecmath.Vector3f scaledDirection = new javax.vecmath.Vector3f(direction);
    float scalent = (float)t;
    scaledDirection.scale(scalent);
    intersection.add(scaledDirection);
    javax.vecmath.Vector3f intersectionPoint = new javax.vecmath.Vector3f(intersection);
    return new Vector3f(intersectionPoint.x,intersectionPoint.y,intersectionPoint.z);
}

这是我的 Cube 代码:

import org.lwjgl.util.vector.Vector3f;

public class Plane3f
{
public Vector3f Point0;
public Vector3f Point1;
public Vector3f Point2;
public Plane3f(Vector3f p0, Vector3f p1, Vector3f p2)
{
    Point0 = p0;
    Point1 = p1;
    Point2 = p2;
}
public static Plane3f[] getBoxDefaults(Vector3f l, float boxs)
{
    Plane3f[] plane = new Plane3f[24];
    Vector3f p0p0 = new Vector3f(-boxs +  l.x, -boxs +  l.y, boxs +  l.z);
    Vector3f p0p1 = new Vector3f(boxs +  l.x, -boxs +  l.y, boxs +  l.z);
    Vector3f p0p2 = new Vector3f(boxs +  l.x, boxs +  l.y, boxs +  l.z);
    //Vector3f p0p3 = new Vector3f(-boxs +  l.x, boxs +  l.y, boxs +  l.z);
    Plane3f p0 = new Plane3f(p0p0, p0p1, p0p2);

    Vector3f p1p0 = new Vector3f(-boxs +  l.x, -boxs +  l.y, -boxs +  l.z);
    Vector3f p1p1 = new Vector3f(-boxs +  l.x, boxs +  l.y, -boxs +  l.z);
    Vector3f p1p2 = new Vector3f(boxs +  l.x, boxs +  l.y, -boxs +  l.z);
    //Vector3f p1p3 = new Vector3f(boxs +  l.x, -boxs +  l.y, -boxs +  l.z);
    Plane3f p1 = new Plane3f(p1p0, p1p1, p1p2);

    Vector3f p2p0 = new Vector3f(-boxs +  l.x, boxs +  l.y, -boxs +  l.z);
    Vector3f p2p1 = new Vector3f(-boxs +  l.x, boxs +  l.y, boxs +  l.z);
    Vector3f p2p2 = new Vector3f(boxs +  l.x, boxs +  l.y, boxs +  l.z);
    //Vector3f p2p3 = new Vector3f(boxs +  l.x, boxs +  l.y, -boxs +  l.z);
    Plane3f p2 = new Plane3f(p2p0, p2p1, p2p2);

    Vector3f p3p0 = new Vector3f(-boxs +  l.x, -boxs +  l.y, -boxs +  l.z);
    Vector3f p3p1 = new Vector3f(boxs +  l.x, -boxs +  l.y, -boxs +  l.z);
    Vector3f p3p2 = new Vector3f(boxs +  l.x, -boxs +  l.y, boxs +  l.z);
    Plane3f p3 = new Plane3f(p3p0, p3p1, p3p2);

    Vector3f p4p0 = new Vector3f(boxs +  l.x, -boxs +  l.y, -boxs +  l.z);
    Vector3f p4p1 = new Vector3f(boxs +  l.x, boxs +  l.y, -boxs +  l.z);
    Vector3f p4p2 = new Vector3f(boxs +  l.x, boxs +  l.y, boxs +  l.z);
    Plane3f p4 = new Plane3f(p4p0, p4p1, p4p2);

    Vector3f p5p0 = new Vector3f(-boxs +  l.x, -boxs +  l.y, -boxs +  l.z);
    Vector3f p5p1 = new Vector3f(-boxs +  l.x, -boxs +  l.y, boxs +  l.z);
    Vector3f p5p2 = new Vector3f(-boxs +  l.x, boxs +  l.y, boxs +  l.z);
    Plane3f p5 = new Plane3f(p5p0, p5p1, p5p2);
    plane[0] = p0;
    plane[1] = p1;
    plane[2] = p2;
    plane[3] = p3;
    plane[4] = p4;
    plane[5] = p5;
    return plane;
}

控制台的输出:

相机:(0.0,0.0,6.0)LookAt(行尾):(124.33239,274.9127,-1000.5496) 距离(从“getBlockInteresection”返回):2.6099026 立方体位置:6,7,8

最佳答案

我不得不在我的游戏中处理这个问题,但是光线转换和视锥体剔除是两种不同的东西。视锥体剔除在大量对象上执行的成本通常更高,而且准确性也较低,但它更简单,可能适合您的程序。

如果您只需要知道立方体是否在视口(viewport)中,您可以使用链接中的函数。这将测试立方体是否在您的视锥体内,而不仅仅是在它的前面,所以如果它在前面但离侧面太远,它将返回 false。

否则,您将需要使用新的 glortho 和 gldeproject 编写光线转换算法。

http://www.crownandcutlass.com/features/technicaldetails/frustum.html

关于java - 这个光线转换算法正确吗?这是测试线/射线和立方体相交的正确方法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7909855/

相关文章:

java - Wicket:在提交时更改 AjaxButton 的文本

java - 使用 Swing 制作交通动画

java - 动态生成透明跟踪像素

c++ - 从没有奇点的矩阵中获取俯仰和滚动

javascript - 围绕一个圆绝对定位元素

algorithm - 凸多面体中体积最大的四面体

java - 我如何测试是否抛出了 ClassNotFoundException?

r - 在 R 中绘制体素图像

java - libgdx Bullet 3D 和滚动摩擦导致 NaN

c# - 快速找到线和网格之间的交点