Po pierwsze intersekcje zacząłem sprawdzać w lokalnym układzie współrzędnych.
Po drugie testowanie cieni półprzeźroczystych wymagało wielu testów dla promienia podążającego w tym samym kierunku, tak że zmienia się tylko punkt startu dla kolejnych powierzchni półprzeźroczystych. Pokusa manipulowania danymi promienia okazała się duża. Z drugiej strony promień jest wykorzystywany w wielu miejscach. Po takiej manipulacji i przed powrotem z funkcji trzeba go przywrócić do stanu pierwotnego, nie wspominając o innych możliwych niepożądanych interakcjach, kiedy zmodyfikujemy promień z klasy intersekcji, a później chcemy coś z niej liczyć - wiele elementów tej klasy jest liczona w sposób opóźniony na żądanie. Tak więc modyfikacje promieni musiały zostać zakazane, a promień musiał stać się klasą immutable. Tzn. poprzednio nie był immutable, ale raczej go nie modyfikowałem. Teraz zostało to zakazane jawnie.
Wyleciała z niego przede wszystkim właściwość wskazująca na źródłową intersekcję. Została ona dodana jako parametr wielu funkcji. Wraz z tym z promienia poleciało wiele funkcji, których wartość wymagała do obliczenia intersekcji. Okazało się, że kod dało się bez problemu przekształcić, tak by się bez nich obejść, ale w kodzie promienia musiała się pojawić jedna dodatkowa informacja mówiąca nam o tym z jakim promieniem mamy do czynienia: odbitym czy załamanym. Bez tej informacji wiele funkcji nie może działać.
Stary kod promienia:
public class Ray
{
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private Vector3 m_dir;
public int Depth = 0;
public Vector3 Start;
public Intersection SourceIntersection;
public bool Refracted;
public RenderableObject PrevHit
{
get
{
if (SourceIntersection != null)
return SourceIntersection.SceneObject;
else
return null;
}
}
public bool PrevBackHit
{
get
{
if (SourceIntersection != null)
return SourceIntersection.BackHit;
else
return false;
}
}
public Vector3 Dir
{
get
{
return m_dir;
}
set
{
Debug.Assert(value.IsNormalized);
m_dir = value;
}
}
public Vector3 HitPoint(float a_distance)
{
return Start + Dir * a_distance;
}
public override string ToString()
{
return String.Format("start: {0}; direction: {1}; depth: {2}",
Start, Dir, Depth);
}
public void Transform(Matrix4 a_matrix, out Vector3 a_local_dir, out Vector3 a_local_start)
{
a_local_dir = (a_matrix.Rotation * Dir).Normalized;
a_local_start = a_matrix * Start;
}
}Nowy kod:
public enum RaySurfaceSide
{
///
/// i.e. Camera ray, LightTestRay.
///
NonDetermined,
///
/// i.e. RefractedRay. ShadowRay.
///
RefractedSide,
///
/// i.e. ReflectedRay, ShadowRay.
///
ReflectedSide
}
public abstract class Ray
{
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private Vector3 m_dir;
public int Depth { get; protected set; }
public Vector3 Start { get; protected set; }
public RaySurfaceSide RaySurfaceSide { get; protected set; }
protected Ray(Scene a_scene)
{
a_scene.Statistics.RaysCreated++;
}
public Vector3 Dir
{
get
{
return m_dir;
}
protected set
{
Debug.Assert(value.IsNormalized);
m_dir = value;
}
}
public Vector3 HitPoint(float a_distance)
{
return Start + Dir * a_distance;
}
public override string ToString()
{
return String.Format("{3}, Start: {0}; Dir: {1}; Depth: {2}, Type: {4}",
Start, Dir, Depth, GetType().Name, RaySurfaceSide);
}
public void Transform(Matrix4 a_matrix, out Vector3 a_local_dir, out Vector3 a_local_start)
{
a_local_dir = (a_matrix.Rotation * Dir).Normalized;
a_local_start = a_matrix * Start;
}
}
Brak komentarzy:
Prześlij komentarz