Advertisement
Staggart

Reproject Spline

Jul 29th, 2024
240
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 2.84 KB | None | 0 0
  1. using System;
  2. using System.Linq;
  3. using UnityEngine;
  4. using UnityEngine.Splines;
  5.  
  6. namespace sc.modeling.splines.runtime.auxiliary
  7. {
  8.     //Samples the source spline at regular intervals and creates a new spline from the data
  9.     //Negatives the unwanted side effects of scaling a SplineContainer
  10.     [ExecuteAlways]
  11.     public class ReprojectSpline : MonoBehaviour
  12.     {
  13.         public SplineContainer source;
  14.         public SplineContainer destination;
  15.  
  16.         public float knotDistance = 2f;
  17.        
  18.         private void Reset()
  19.         {
  20.             destination = GetComponent<SplineContainer>();
  21.         }
  22.        
  23.         private void OnEnable()
  24.         {
  25.             Spline.Changed += OnSplineChanged;
  26.             Resample();
  27.         }
  28.  
  29.         private void OnDisable()
  30.         {
  31.             Spline.Changed -= OnSplineChanged;
  32.         }
  33.  
  34.         private void OnSplineChanged(Spline spline, int index, SplineModification modificationType)
  35.         {
  36.             if (!source) return;
  37.  
  38.             if (spline.GetHashCode() != source.GetHashCode()) return;
  39.  
  40.             //Spline belongs to the assigned container?
  41.             var splineIndex = Array.IndexOf(source.Splines.ToArray(), spline);
  42.             if (splineIndex < 0)
  43.                 return;
  44.  
  45.             Resample();
  46.         }
  47.  
  48.         public void Resample()
  49.         {
  50.             if (!source || !destination) return;
  51.            
  52.             for (int s = 0; s < destination.Splines.Count; s++)
  53.             {
  54.                 destination.RemoveSplineAt(s);
  55.             }
  56.            
  57.             for (int i = 0; i < source.Splines.Count; i++)
  58.             {
  59.                 Spline spline = new Spline();
  60.                 float length = source.Splines[i].CalculateLength(source.transform.localToWorldMatrix);
  61.  
  62.                
  63.                 int sampleCount = Mathf.CeilToInt(length / knotDistance);
  64.                 for (int j = 0; j <= sampleCount; j++)
  65.                 {
  66.                     float t = (float) j / sampleCount;
  67.  
  68.                     t = Mathf.Clamp(t, 0.001f, 0.999f);
  69.                     source.Splines[i].Evaluate(t, out var position, out var tangent, out var up);
  70.                     position = source.transform.TransformPoint(position);
  71.                     position = destination.transform.InverseTransformPoint(position);
  72.  
  73.                     BezierKnot knot = new BezierKnot();
  74.                     knot.Position = position;
  75.                    
  76.                     spline.Add(knot, TangentMode.Continuous);
  77.                 }
  78.                
  79.                 //Automatically recalculate tangents
  80.                 spline.SetTangentMode(new SplineRange(0, spline.Count), TangentMode.AutoSmooth);
  81.                 spline.Closed = source.Splines[i].Closed;
  82.                
  83.                 destination.AddSpline(spline);
  84.             }
  85.         }
  86.     }
  87. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement