我正在尝试编写一个最简单的光线追踪器,它只会将一个圆输出到 PPM 文件,但我什么也没得到。问题不在于 PPM 代码,而在于光线代码。我数学不好,所以我真的不知道问题出在哪里,如果有人可以帮助我,我将不胜感激,因为我真的不知道我做错了什么。
这是代码:
public class Main {
static int WITDH = 200;
static int HEIGHT = 200;
public static void main(String[] args) {
Sphere Ball = new Sphere(0, 0, -1 ,1);
Vector Camera = new Vector(0, 0, -1);
int [][] Pic = new int[200][200];
int number=0;
for (int y = 0;y<HEIGHT;y++) {
for (int x = 0; x < WITDH; x++) {
number++;
Ray test = new Ray(Camera);
double first=0.5*(WITDH-x)/(double)WITDH;
double second=0.5*(HEIGHT-y)/(double)HEIGHT;
Vector direc=new Vector(first,second,-1.0);
test.at(number,direc);
if (Sphere.intersects(test, Ball) == true) {
Pic[y][x]=0;
} else if(Sphere.intersects(test,Ball) == false) {
Pic[y][x]=1;
}
}
}
}
}
static Boolean intersects(Ray ray, Sphere Shape) {
Vector Origin = ray.origin;
Vector center = Shape.Pozicija;
double discrimant;
Vector L = Vector.SubtractVector(Origin, center);
double a = Vector.ReturnDotProduct(ray.Direction, ray.Direction);
double b = 2.0 * Vector.ReturnDotProduct(L, ray.Direction);
double c = Vector.ReturnDotProduct(L, L) - (Shape.radius * Shape.radius);
double t0=0.0;
double t1=0.0;
discrimant = (b * b) - (4.0 * a * c);
double q;
if(discrimant<0.0){
return false;
}else if(discrimant==0.0){
t0=t1=-0.5*b/a;
}else {
if(b>0) {
q = -0.5*(b+Math.sqrt(discrimant));
}else{
q = -0.5*(b-Math.sqrt(discrimant));
}
t0=q/a;
t1=c/q;
}
if(t0>t1){
double t3;
t3=t1;
t0=t1;
t1=t3;
}
if (t0 < 0) {
t0 = t1;
if (t0 < 0) {
return false;
}
}
System.out.println(t0+t1);
return true;
}
Vector at(double t,Vector d2){
Vector d1=new Vector(0,0,0);
if(t==0){
d1=Direction;
}else if(t>0){
d1=Vector.GetDirection(d2);
}
return Vector.AddVector(origin,Vector.MultiplyScalar(d1,t));
}
您的代码似乎是尝试实现一个简单的光线追踪器,但需要解决一些问题才能使其正常工作。我将帮助您识别并解决这些问题:
Ray 类:在 Ray 类中,您有一个方法 at(double t, Vector d2) 尝试计算给定 t 值的新向量。但是,您似乎正在尝试改变 Ray 类的 Direction 字段,这是不正确的。相反,您应该使用更新的原点和方向创建一个新的 Ray 实例。这是更正的 at 方法:
射线 at(double t, Vector d2) { 向量 newDirection = Vector.GetDirection(d2); Vector newOrigin = Vector.AddVector(origin, Vector.MultiplyScalar(newDirection, t)); 返回新射线(新原点,新方向); }
Intersect 方法: intersects 方法在代码中似乎是静态方法,但它应该在 Sphere 类中定义,因为它对 Sphere 对象进行操作。将 intersects 方法移至 Sphere 类中。
if(判别式 < 0.0) { return false; } else if (discriminant == 0.0) { t0 = t1 = -0.5 * b / a; } else { if (b > 0){ q = -0.5 * (b + Math.sqrt(判别式)); } 别的 { q = -0.5 * (b - Math.sqrt(判别式)); } t0 = q / a; t1=c/q; }
如果(t0< 0 && t1 < 0) { return false; }
返回真;
循环问题:在你的 main 方法中,变量 number 被用作递增因子,但这不是必需的。您应该在循环内增加数字,而不是事先增加。
PPM 文件生成:您提到 PPM 代码正在运行,但它未包含在提供的代码中。确保写入 PPM 文件的代码正常运行,并确保使用正确的扩展名 (.ppm) 保存文件。
通过这些更正并确保其余代码(包括 Vector 和 Sphere 类)正确实现后,您的光线追踪器应该能够将圆渲染到 PPM 文件。此外,您可能需要考虑使用适当的开发环境或 IDE,因为它可以帮助您调试和编写更清晰的代码。