Я работаю над созданием трассировщика лучей. Вы знаете, для удовольствия. Пока что все идет по плану, но как только я начал преобразовывать свои тестовые сферы, все пошло не так.
Фундаментальной концепцией является использование одной из стандартных форм в качестве источника, преобразование лучей камеры в пространство объекта, а затем пересечение.
Пока сфера идентична в пространстве объектов и мировом пространстве, она работает как положено, но как только сферы масштабируются, нормали и точки пересечения становятся дикими.
Я ломал голову и перебирал этот код снова и снова, но я просто не могу найти ошибку. Буду благодарен за свежие глаза.
@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
Почему нормали и точки пересечения не переводятся в мировое пространство, как ожидалось?
Редактировать: Я умеренно уверен, что мои векторные и матричные функции математически надежны; и я думаю, что это в основном ошибка метода, но я понимаю, что могу ошибаться.