$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