Java 这个光线投射算法正确吗?这是测试直线/光线与立方体相交的正确方法吗?
我正在建立一个LWJGL程序,测试立方体是否在摄像机前面。我认为这是可行的,但我得到了大量不同的数据。我认为这是因为平面永远在运动,它们不是有限的正方形。我该怎么做才能解决这个问题?(我也注意到我的代码相当慢,是什么原因造成的?) 这是我的交叉口代码:Java 这个光线投射算法正确吗?这是测试直线/光线与立方体相交的正确方法吗?,java,3d,geometry,raytracing,Java,3d,Geometry,Raytracing,我正在建立一个LWJGL程序,测试立方体是否在摄像机前面。我认为这是可行的,但我得到了大量不同的数据。我认为这是因为平面永远在运动,它们不是有限的正方形。我该怎么做才能解决这个问题?(我也注意到我的代码相当慢,是什么原因造成的?) 这是我的交叉口代码: public static float getCubeInteresection(Cube b, Vector3f camera, Vector3f lookat) { Vector3f l = b.Location; float
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);
}
控制台的输出:
摄影机:(0.0,0.0,6.0)注视(线的末端):(124.33239274.9127,-1000.5496)距离(从“GetBlockInterestment”返回):2.6099026立方体位置:6,7,8我必须在游戏中处理这个问题,但是光线投射和截锥体剔除是两件不同的事情。在大量对象上执行截头体剔除通常成本较高,精确度也较低,但它更简单,可能适合您的程序 如果只需要知道立方体是否在视口中,可以使用链接中的函数。这将测试立方体是否在视锥体内,而不仅仅是在它前面,因此如果它在前面但离侧面太远,它将返回false 否则,您将需要使用新的glortho和gldeproject编写光线投射算法
你说的“我得到了很多不同的数字”是什么意思?您的输出仅显示一个交叉点。抱歉,我的意思是,每次场景更新时,我都会得到不同的数字(数字表示从getBlockIntersection返回的距离),我会移动摄影机的注视点,但实际位置保持静止。摄影机和注视点变量都会传递到交叉点代码,所以我认为,如果你改变其中一个,你会得到不同的数字,这并不奇怪。对,但我应该使用平面,还是应该使用正方形/四边形?如果是这样的话,我该怎么做呢?如果你只是在寻找与框的交点,那么你应该寻找轴对齐的边界框交点或定向边界框交点。有很多书都在谈论这个话题。另外,我们有很多关于这方面的资源,例如:。
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;
}