$x = P + \vec{d}t$
Parametr t możemy potraktować jako czas. Jest ono identyczne z równaniem parametrycznym linii, nadajemy tylko innego znaczenia parametrom. Równanie parametryczne płaszczyzny w postaci wektorowej:
$\vec n \cdot x + D = 0$
Z porównania:$\vec n(P + \vec{d}t) + D = 0$
Stąd:$t=\displaystyle-\frac{D + \vec{n}P}{\vec{n} \cdot \vec d}$
Jeśli $\mathbf{t<0}$ to przecięcie nastąpiło po przed miejscem wyjścia promienia. Traktując promień jako prostą takie t ma sens. Jeśli $\mathbf{t>=0}$ punkt przecięcia promienia z prostą istnieje. Warunkiem istnienia punktu przecięcia jest to by płaszczyzn była nierównoległa do promienia, czyli $\mathbf{\vec n \cdot \vec d} \neq 0$.
Punkt przecięcia wyznaczamy podstawiając t do równania prostej.
Aby ustalić z której strony płaszczyzny nastąpiło uderzenie badamy znak wyrażenia $\mathbf{\vec{n} \cdot \vec d}$. Jeśli $\mathbf{\vec{n} \cdot \vec d}<0$ uderzenie nastąpiło z przodu płaszczyzny (z kierunku który wskazuje normalna płaszczyzny). Jeśli $\mathbf{\vec{n} \cdot \vec d}>0$ uderzenie nastąpiło z tyłu. Jeśli $\mathbf{\vec{n} \cdot \vec d}=0$ promień jest równoległy do płaszczyzny.
Przykład implementacji w C#:
public override Intersection GetIntersection(Ray a_ray) { double denom = Normal * a_ray.Dir; if (OneSide) { if (denom > 0) return Scene.NoIntersection; } if (a_ray.PrevHit == this) return Scene.NoIntersection; if (!denom.IsZero()) { double dist = ((Normal * a_ray.Start) - Distance) / (-denom); if (dist <= 0) return Scene.NoIntersection; else { bool backHit = (denom > 0); if (backHit && OneSide) return Scene.NoIntersection; else { return new Intersection() { SceneObject = this, SourceRay = a_ray, Dist = dist, Scene = Scene, BackHit = backHit, Pos = a_ray.HitPoint(dist) }; } } } else return Scene.NoIntersection; }
Brak komentarzy:
Prześlij komentarz