Różnice są na początku. Ponieważ z założenie mapować możemy nie tylko na torus, ale na dowolny kształt nie możemy zakładać, że punkty będą leżeć dokładnie na torusie. Dodatkowo do policzenia mapowania potrzebujemy punkt w lokalnych współrzędnych torusa (tak jak liczyliśmy to dla torusa) zaś tutaj dostajemy go we współrzędnych UVW. Pierwszych kilka linijek liczy więc lokalną współrzędną i mały promień związany z tym punktem na lub poza torusem.
public class TorodidalUVMapper : UVMapper
{
private double m_local_small_radius;
private double m_local_big_radius;
private double m_big_radius;
private double m_small_radius;
[YAXNode]
public double BigRadius
{
get
{
return m_big_radius;
}
set
{
m_big_radius = value;
UpdateLocalRadiuses();
}
}
[YAXNode]
public double SmallRadius
{
get
{
return m_small_radius;
}
set
{
m_small_radius = value;
UpdateLocalRadiuses();
}
}
[YAXOnDeserialized]
private void UpdateLocalRadiuses()
{
m_local_small_radius = SmallRadius / (SmallRadius + BigRadius);
m_local_big_radius = BigRadius / (SmallRadius + BigRadius);
}
public TorodidalUVMapper(double a_big_radius = 0, double a_small_radius = 0)
{
BigRadius = a_big_radius;
SmallRadius = a_small_radius;
}
public override Vector2 Map(Vector3 a_uvw)
{
Vector3 local_pos = (a_uvw - Vector3.HALF) / new Vector3(0.5, 0.5 /
m_local_small_radius, 0.5);
Vector3 p1 = new Vector3(local_pos.X, 0, local_pos.Z).Normalized *
m_local_big_radius;
double small_radius = (local_pos - p1).Length;
double ca = local_pos.Y / small_radius;
Debug.Assert(ca.IsAlmostRelativeGreaterOrEqualThen(-1));
Debug.Assert(ca.IsAlmostRelativeLessOrEqualThen(1));
ca = DoubleExtensions.Limit(ca, -1, 1);
double v = Math.Acos(ca) / Constants.PI / 2;
if (local_pos.X * local_pos.X + local_pos.Z * local_pos.Z >
m_local_big_radius * m_local_big_radius)
{
v = v + 0.25;
}
else
{
if (local_pos.Y > 0)
v = 0.25 - v;
else
v = 1.25 - v;
}
double u = Math.Atan2(local_pos.X, local_pos.Z) / (2 * Constants.PI);
if (local_pos.X < 0)
u = u + 1;
return new Vector2(u, v);
}
public override UVMappingMethod Method
{
get
{
return UVMappingMethod.Toroidal;
}
}
public override string ToString()
{
return String.Format("Toroidal uv mapper: R: {0}, r: {1}", BigRadius,
SmallRadius);
}
}
Brak komentarzy:
Prześlij komentarz