public override Intersection GetIntersection(Ray a_ray)
{
bool backHit = false;
Vector3 c = Pos - a_ray.Start;
double c2 = c.Length * c.Length;
double r2 = Radius * Radius;
double dist;
if (a_ray.PrevHit == this)
{
if (a_ray.PrevBackHit)
{
backHit = true;
if (OneSide)
return Scene.NoIntersection;
else
{
double v = c * a_ray.Dir;
double m2 = r2 - (c2 - v * v);
dist = v + Math.Sqrt(m2);
}
}
else
return Scene.NoIntersection;
}
else
{
double v = c * a_ray.Dir;
double m2 = r2 - (c2 - v * v);
if (c2 > r2)
{
if (v <= 0)
return Scene.NoIntersection;
else
{
if (m2 < 0)
return Scene.NoIntersection;
else
dist = v - Math.Sqrt(m2);
}
}
else
{
backHit = true;
if (OneSide)
return Scene.NoIntersection;
else
dist = v + Math.Sqrt(m2);
}
}
return new Intersection()
{
SceneObject = this,
SourceRay = a_ray,
Dist = dist,
Scene = Scene,
BackHit = backHit,
Pos = a_ray.HitPoint(dist)
};
}
public override Vector3 GetNormal(Intersection a_intersection)
{
if (a_intersection.BackHit)
return (Pos - a_intersection.Pos).Normalized;
else
return (a_intersection.Pos - Pos).Normalized;
}Nowy kod:public Ray Transform(Matrix4 a_matrix)
{
return new Ray()
{
Dir = (a_matrix.Rotation * this.Dir).Normalized,
Start = a_matrix * this.Start,
SourceIntersection = this.SourceIntersection,
Depth = this.Depth
};
}
public override Intersection GetIntersection(Ray a_ray)
{
Ray ray_local = a_ray.Transform(WorldToLocal);
bool backHit = false;
float dist;
if (ray_local.PrevHit == this)
{
if (ray_local.PrevBackHit)
{
backHit = true;
if (OneSide)
return Scene.NoIntersection;
else
{
float v = -(ray_local.Start * ray_local.Dir);
float m2 = Radius * Radius - (ray_local.Start.SqrLen - v * v);
dist = v + (float)Math.Sqrt(m2);
}
}
else
return Scene.NoIntersection;
}
else
{
float c2 = ray_local.Start.SqrLen;
float r2 = Radius * Radius;
if (c2 > r2)
{
float v = -(ray_local.Start * ray_local.Dir);
if (v <= 0)
return Scene.NoIntersection;
else
{
float m2 = r2 - (c2 - v * v);
if (m2 < 0)
return Scene.NoIntersection;
else
dist = v - (float)Math.Sqrt(m2);
}
}
else
{
backHit = true;
if (OneSide)
return Scene.NoIntersection;
else
{
float v = -(ray_local.Start * ray_local.Dir);
float m2 = r2 - (c2 - v * v);
dist = v + (float)Math.Sqrt(m2);
}
}
}
var pos = ray_local.Start + ray_local.Dir * dist;
pos = LocalToWorld * pos;
dist = (pos - a_ray.Start).Length;
return new Intersection()
{
SceneObject = this,
SourceRay = a_ray,
Dist = dist,
Scene = Scene,
BackHit = backHit,
Pos = pos
};
}
public override Vector3 GetNormal(Intersection a_intersection)
{
if (a_intersection.BackHit)
return -(LocalToWorldNormal * a_intersection.UVW).Normalized;
else
return (LocalToWorldNormal * a_intersection.UVW).Normalized;
}Główne zmiany są na początku badania intersekcji kiedy promień jest transformowany do lokalnego układu współrzędnych. Dzięki temu z obliczeń wylatuje Pos. Dodatkowo poprzenosiłem wgłąb wyliczenia niektórych zmiennych do momentu, aż są one potrzebne. Na samym końcu przed zwróceniem wyniku intersekcji wyliczamy miejsce uderzenia i dystans w współrzędnych świata.W kodzie na wyliczenie normalnej korzystamy od teraz z specjalnej macierzy na transformację normalnych. Zauważmy, że współrzędne UVW są zmapowane na sferę.
Pozostały kod na wyliczanie UVW, UV, tangensów nie ulega zmianie.
Brak komentarzy:
Prześlij komentarz