线/光线交叉不按预期工作

时间:2011-11-30 19:23:12

标签: objective-c raytracing

我一直在努力拼凑光线追踪器。你知道,为了好玩。到目前为止,大多数事情都按计划进行,但是一旦我开始改变我的测试领域,一切都出错了。

基本概念是使用标准形状之一作为原点,将相机光线转换为物体空间,然后相交。

只要球体在物体空间和世界空间中是相同的,它就会按预期工作,但只要球体被缩放,法线和交叉点就会变得狂野。

我一直在绞尽脑汁,一遍又一遍地研究这段代码,但我找不到错误。新鲜的眼睛将非常感激。

@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

为什么法线和交点不会按预期转换为世界空间?

编辑:中等确信我的矢量和矩阵函数在数学上是合理的;我认为这主要是方法错误,但我认识到我可能是错的。

1 个答案:

答案 0 :(得分:1)

这里有很多RT *代码“幕后”我们无法知道是否正确,所以我首先要确保你对这些数学函数进行了良好的单元测试。根据我管理变换的经验,我最怀疑的是rayByTransformingByMatrix:inverseTransformation的值。我发现在组合转换时很容易出错。旋转和缩放与缩放和旋转不同。

你什么时候出错了?你确定objectRay本身是正确的吗? (如果不是,则此功能的其余部分无关紧要。)同样,单元测试是您的朋友。您应该手动计算几种情况,然后编写单元测试以确保您的方法返回正确的答案。