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