我一直在努力拼凑光线追踪器。你知道,为了好玩。到目前为止,大多数事情都按计划进行,但是一旦我开始改变我的测试领域,一切都出错了。
基本概念是使用标准形状之一作为原点,将相机光线转换为物体空间,然后相交。
只要球体在物体空间和世界空间中是相同的,它就会按预期工作,但只要球体被缩放,法线和交叉点就会变得狂野。
我一直在绞尽脑汁,一遍又一遍地研究这段代码,但我找不到错误。新鲜的眼睛将非常感激。
@implementation RTSphere
- (CGFloat)intersectsRay:(RTRay *)worldRay atPoint:(RTVector *)intersection normal:(RTVector *)normal material:(RTMaterial **)material {
RTRay *objectRay = [worldRay rayByTransformingByMatrix:self.inverseTransformation];
RTVector D = objectRay.direction;
RTVector O = objectRay.start;
CGFloat A, B, C;
A = RTVectorDotProduct(D, D);
B = 2 * RTVectorDotProduct(D,O);
C = RTVectorDotProduct(O, O) - 0.25;
CGFloat BB4AC = B * B - 4 * A * C;
if (BB4AC < 0.0) {
return -1.0;
}
CGFloat t0 = (-B - sqrt(BB4AC)) / 2 * A;
CGFloat t1 = (-B + sqrt(BB4AC)) / 2 * A;
if (t0 > t1) {
CGFloat tmp = t0;
t0 = t1;
t1 = tmp;
}
if (t1 < 0.0) {
return -1.0;
}
CGFloat t;
if (t0 < 0.0) {
t = t1;
} else {
t = t0;
}
if (material) {
*material = self.material;
}
if (intersection) {
RTVector isect_o = RTVectorAddition(objectRay.start, RTVectorMultiply(objectRay.direction, t));
*intersection = RTVectorMatrixMultiply(isect_o, self.transformation);
if (normal) {
RTVector normal_o = RTVectorSubtraction(isect_o, RTMakeVector(0.0, 0.0, 0.0));
RTVector normal_w = RTVectorUnit(RTVectorMatrixMultiply(normal_o, self.transformationForNormal));
*normal = normal_w;
}
}
return t;
}
@end
为什么法线和交点不会按预期转换为世界空间?
编辑:我中等确信我的矢量和矩阵函数在数学上是合理的;我认为这主要是方法错误,但我认识到我可能是错的。
答案 0 :(得分:1)
这里有很多RT *代码“幕后”我们无法知道是否正确,所以我首先要确保你对这些数学函数进行了良好的单元测试。根据我管理变换的经验,我最怀疑的是rayByTransformingByMatrix:
或inverseTransformation
的值。我发现在组合转换时很容易出错。旋转和缩放与缩放和旋转不同。
你什么时候出错了?你确定objectRay
本身是正确的吗? (如果不是,则此功能的其余部分无关紧要。)同样,单元测试是您的朋友。您应该手动计算几种情况,然后编写单元测试以确保您的方法返回正确的答案。