Loading [MathJax]/jax/output/HTML-CSS/jax.js

2011-07-20

Intersekcja promienia z płaszczyzną

Równanie promienia w postaci parametrycznej wychodzącego z punktu P w kierunku d

x=P+dt
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:

nx+D=0
Z porównania:

n(P+dt)+D=0
Stąd:

t=D+nPnd
Jeśli 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 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 nd0.

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 nd. Jeśli nd<0 uderzenie nastąpiło z przodu płaszczyzny (z kierunku który wskazuje normalna płaszczyzny). Jeśli nd>0 uderzenie nastąpiło z tyłu. Jeśli nd=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