06 1月

从一个球开始

好了,我们定义好光线了,那么接下来我们需要拿些物体来检测了光线碰撞了,我们会介绍光线和平面交互,光线和box,光线和三角平面,光线和圆。

很多人会问,为什么不介绍复杂模型碰撞检测呢,比如说茶壶,龙。因为在三维中所有的三维模型都能用三角面组成,所以只要讲光线和三角面碰撞检测,我们就能融会贯通了。

首先我们使用圆来进行。为什么用圆来做碰撞检测呢。因为圆最简单。(为什么最简单,等以后你就知道了)

我们在初中学过圆的方程:

(x-c)²=r²

光线的方程:

p=o+t*d;  (  t>0  )

当光线和圆交互也就是有交点的时候,点p是在圆上面。得到

(p-c)²=r²;

(p-c)²-r²=0;

将光线代入:

(o+t*d-c)²-r²=0;

现在我们唯一不知道的是未知数t:

所以就变成解二元一次方程解:

d²t²+[2(o-c)d]t+(o-c)(o-c)-r²=0;

简化方程:

at²+bt+c=0;

a=d²

b=2(o-c)d

c=(o-c)(o-c)-r²

那么得到t的解是:

b_4abc

我们确定有没有解,就要判断开根号里面的值是否>0

所以,我们要判断试着个等式

d=b²-4ac;

如果,d>0,那么t有两个解,如果d=0,那么t有一个解。如果d<0则无解。我们用一张图来表示

sphere

这是第一步。因为如果我求出d>0,不等于就一定就有交互。我们还要看t的值。t值必须大于0,因为光线只会向前进,不会倒着走。

ok,求出了p的值之后,那么再将t代入p=o+t*d,我们就能知道撞击点的位置了。

Hitpos=0+t*d

现在我们来看看圆的类

以下是碰撞检测函数,

*这里来解释一下为什么t要大于0.0001而不是0,以后章节会提到,我这里简单说一下,之后为了判断这个点在不在阴影里面还要从这个点再继续射出一根shadow_ray。为了避免碰到自己本身=0的极端值,用着个方法把碰撞点往外推了一点点。