using System;
|
|
using UnityEngine;
|
|
using System.Collections.Generic;
|
|
using BansheeGz.BGSpline.Curve;
|
|
using Random = UnityEngine.Random;
|
|
|
|
namespace BansheeGz.BGSpline.Example
|
|
{
|
|
// math visual testing (for internal use)
|
|
public class BGTestCurveMath : MonoBehaviour
|
|
{
|
|
[Tooltip("Material to use with LineRenderer")] public Material LineRendererMaterial;
|
|
|
|
[Tooltip("Object to move along a curve")] public MeshRenderer ObjectToMove;
|
|
|
|
private const float Period = 3;
|
|
private const int ObjectsCount = 4;
|
|
private const float ObjectsSpeed = .3f;
|
|
|
|
private TestCurves testCurves;
|
|
|
|
private GUIStyle style;
|
|
|
|
// Use this for initialization
|
|
private void Start()
|
|
{
|
|
testCurves = new TestCurves(GetComponent<BGCurve>(), new BGCurveBaseMath.Config(BGCurveBaseMath.Fields.PositionAndTangent), ObjectToMove, LineRendererMaterial);
|
|
|
|
//Base, OptimizeStraightLines
|
|
testCurves.Add(new CurveData(testCurves, "BGBaseStraightLines", "Base, OptimizeStraightLines = true", transform.position + new Vector3(-4, 1),
|
|
new BGCurveBaseMath.Config(BGCurveBaseMath.Fields.PositionAndTangent) {OptimizeStraightLines = true}, CurveData.MathTypeEnum.Base));
|
|
|
|
//Base, UsePointPositionsToCalcTangents
|
|
testCurves.Add(new CurveData(testCurves, "BGBasePos2Tangents", "Base, UsePointPositionsToCalcTangents = true", transform.position + new Vector3(-4, 4),
|
|
new BGCurveBaseMath.Config(BGCurveBaseMath.Fields.PositionAndTangent) {UsePointPositionsToCalcTangents = true}, CurveData.MathTypeEnum.Base));
|
|
|
|
//Adaptive
|
|
testCurves.Add(new CurveData(testCurves, "BGAdaptive", "Adaptive", transform.position + new Vector3(4, 4),
|
|
new BGCurveAdaptiveMath.ConfigAdaptive(BGCurveBaseMath.Fields.PositionAndTangent) /* { Tolerance = .2f }*/, CurveData.MathTypeEnum.Adaptive));
|
|
|
|
//Formula
|
|
testCurves.Add(new CurveData(testCurves, "BGFormula", "Formula", transform.position + new Vector3(4, 1),
|
|
new BGCurveBaseMath.Config(BGCurveBaseMath.Fields.PositionAndTangent), CurveData.MathTypeEnum.Formula));
|
|
}
|
|
|
|
|
|
// Update is called once per frame
|
|
private void Update()
|
|
{
|
|
testCurves.Update();
|
|
if (Input.GetKeyDown(KeyCode.LeftArrow)) testCurves.MoveLeft();
|
|
if (Input.GetKeyDown(KeyCode.RightArrow)) testCurves.MoveRight();
|
|
}
|
|
|
|
private void OnGUI()
|
|
{
|
|
if (style == null) style = new GUIStyle(GUI.skin.label) {fontSize = 18};
|
|
GUI.Label(new Rect(0, 24, 800, 30), "Left Arrow - move left, Right Arrow - move right", style);
|
|
GUI.Label(new Rect(0, 48, 800, 30), "Comparing with: " + testCurves.CurrentToString(), style);
|
|
}
|
|
|
|
|
|
//==================================== abstract curve's data
|
|
private abstract class CurveDataAbstract
|
|
{
|
|
private readonly List<GameObject> objectsToMove = new List<GameObject>();
|
|
private readonly Material objectToMoveMaterial;
|
|
private readonly LineRenderer lineRenderer;
|
|
public readonly Material LineRendererMaterial;
|
|
protected readonly GameObject GameObject;
|
|
|
|
protected BGCurveBaseMath Math;
|
|
|
|
private BGCurve curve;
|
|
|
|
public BGCurve Curve
|
|
{
|
|
get { return curve; }
|
|
protected set
|
|
{
|
|
curve = value;
|
|
curve.Changed += (sender, args) => UpdateLineRenderer();
|
|
}
|
|
}
|
|
|
|
|
|
protected CurveDataAbstract(GameObject gameObject, Material lineRendererMaterial, Color color)
|
|
{
|
|
GameObject = gameObject;
|
|
LineRendererMaterial = lineRendererMaterial;
|
|
|
|
//change material
|
|
objectToMoveMaterial = Instantiate(lineRendererMaterial);
|
|
objectToMoveMaterial.SetColor("_TintColor", color);
|
|
|
|
|
|
//add lineRenderer
|
|
lineRenderer = gameObject.AddComponent<LineRenderer>();
|
|
lineRenderer.material = lineRendererMaterial;
|
|
#if UNITY_5_5 || UNITY_5_6
|
|
lineRenderer.startWidth = lineRenderer.endWidth = 0.05f;
|
|
lineRenderer.startColor = lineRenderer.endColor = color;
|
|
#else
|
|
lineRenderer.SetWidth(0.05f, 0.05f);
|
|
lineRenderer.SetColors(color, color);
|
|
#endif
|
|
|
|
}
|
|
|
|
//=================== line renderer
|
|
private void UpdateLineRenderer()
|
|
{
|
|
const int count = 100;
|
|
var positions = new Vector3[100];
|
|
const float countMinusOne = count - 1;
|
|
for (var i = 0; i < 100; i++)
|
|
{
|
|
var distanceRatio = i/countMinusOne;
|
|
positions[i] = Math.CalcByDistanceRatio(BGCurveBaseMath.Field.Position, distanceRatio);
|
|
}
|
|
#if UNITY_5_5 || UNITY_5_6
|
|
lineRenderer.numPositions = count;
|
|
#else
|
|
lineRenderer.SetVertexCount(count);
|
|
#endif
|
|
lineRenderer.SetPositions(positions);
|
|
}
|
|
|
|
//=================== objects
|
|
protected void AddObjects(int count, MeshRenderer pattern, Transform parent)
|
|
{
|
|
for (var i = 0; i < count; i++)
|
|
{
|
|
var clone = Instantiate(pattern.gameObject);
|
|
clone.transform.parent = parent;
|
|
AddObject(clone);
|
|
}
|
|
}
|
|
|
|
protected void AddObject(GameObject obj)
|
|
{
|
|
obj.GetComponent<MeshRenderer>().sharedMaterial = objectToMoveMaterial;
|
|
objectsToMove.Add(obj.gameObject);
|
|
}
|
|
|
|
protected void UpdateObjects(List<float> distanceRatios)
|
|
{
|
|
for (var i = 0; i < objectsToMove.Count; i++)
|
|
{
|
|
var position = Math.CalcByDistanceRatio(BGCurveBaseMath.Field.Position, distanceRatios[i]);
|
|
var tangent = Math.CalcByDistanceRatio(BGCurveBaseMath.Field.Tangent, distanceRatios[i]);
|
|
|
|
objectsToMove[i].transform.position = position;
|
|
objectsToMove[i].transform.LookAt(position + tangent);
|
|
}
|
|
}
|
|
|
|
public abstract void Update();
|
|
}
|
|
|
|
//==================================== Reference Curve
|
|
private sealed class TestCurves : CurveDataAbstract
|
|
{
|
|
public readonly List<float> DistanceRatios = new List<float>();
|
|
public readonly MeshRenderer ObjectToMove;
|
|
private readonly List<CurveData> curves = new List<CurveData>();
|
|
|
|
private float startTime = -Period*2;
|
|
private Quaternion fromRotation;
|
|
private Quaternion toRotation;
|
|
private int currentCurveIndex = -1;
|
|
|
|
|
|
public TestCurves(BGCurve curve, BGCurveBaseMath.Config config, MeshRenderer objectToMove, Material lineRendererMaterial)
|
|
: base(curve.gameObject, lineRendererMaterial, Color.green)
|
|
{
|
|
Curve = curve;
|
|
Math = new BGCurveBaseMath(curve, config);
|
|
ObjectToMove = objectToMove;
|
|
|
|
AddObject(objectToMove.gameObject);
|
|
AddObjects(ObjectsCount - 1, objectToMove, curve.transform);
|
|
|
|
const float offset = 1/(float) ObjectsCount;
|
|
for (var i = 0; i < ObjectsCount; i++) DistanceRatios.Add(i*offset);
|
|
}
|
|
|
|
public void MoveRight()
|
|
{
|
|
currentCurveIndex++;
|
|
if (currentCurveIndex == curves.Count) currentCurveIndex = 0;
|
|
}
|
|
|
|
public void MoveLeft()
|
|
{
|
|
currentCurveIndex--;
|
|
if (currentCurveIndex < 0) currentCurveIndex = curves.Count - 1;
|
|
}
|
|
|
|
public override void Update()
|
|
{
|
|
if (Time.time - startTime > Period)
|
|
{
|
|
startTime = Time.time;
|
|
|
|
fromRotation = Curve.transform.rotation;
|
|
toRotation = Quaternion.Euler(Random.Range(0.0f, 360.0f), Random.Range(0.0f, 360.0f), Random.Range(0.0f, 360.0f));
|
|
}
|
|
|
|
var ratio = (Time.time - startTime)/Period;
|
|
Curve.transform.rotation = Quaternion.Lerp(fromRotation, toRotation, ratio);
|
|
for (var i = 0; i < DistanceRatios.Count; i++)
|
|
{
|
|
DistanceRatios[i] += ObjectsSpeed*Time.deltaTime;
|
|
if (DistanceRatios[i] > 1) DistanceRatios[i] = 0;
|
|
}
|
|
UpdateObjects(DistanceRatios);
|
|
|
|
foreach (var data in curves) data.Update();
|
|
}
|
|
|
|
public bool IsCurrent(CurveData curve)
|
|
{
|
|
return currentCurveIndex >= 0 && currentCurveIndex < curves.Count && curves[currentCurveIndex] == curve;
|
|
}
|
|
|
|
public void Add(CurveData curveData)
|
|
{
|
|
curves.Add(curveData);
|
|
}
|
|
|
|
public string CurrentToString()
|
|
{
|
|
return currentCurveIndex < 0 ? "None" : curves[currentCurveIndex].Description;
|
|
}
|
|
}
|
|
|
|
//==================================== Some Curve
|
|
private sealed class CurveData : CurveDataAbstract
|
|
{
|
|
public enum MathTypeEnum
|
|
{
|
|
Base,
|
|
Formula,
|
|
Adaptive
|
|
}
|
|
|
|
private readonly Vector3 origin;
|
|
private readonly TestCurves testCurves;
|
|
private readonly Vector3 originalScale = new Vector3(.7f, .7f, .7f);
|
|
|
|
private readonly string description;
|
|
|
|
public string Description
|
|
{
|
|
get { return description; }
|
|
}
|
|
|
|
public CurveData(TestCurves testCurves, string name, string description, Vector3 position, BGCurveBaseMath.Config config, MathTypeEnum mathType)
|
|
: base(new GameObject(name), testCurves.LineRendererMaterial, Color.magenta)
|
|
{
|
|
this.testCurves = testCurves;
|
|
this.description = description;
|
|
|
|
//game object
|
|
GameObject.transform.position = position;
|
|
origin = position;
|
|
|
|
//curve
|
|
Curve = GameObject.AddComponent<BGCurve>();
|
|
Curve.Closed = testCurves.Curve.Closed;
|
|
|
|
//add points
|
|
for (var i = 0; i < testCurves.Curve.PointsCount; i++)
|
|
{
|
|
var point = testCurves.Curve[i];
|
|
var clonePoint = new BGCurvePoint(Curve, point.PositionLocal, point.ControlType, point.ControlFirstLocal, point.ControlSecondLocal);
|
|
Curve.AddPoint(clonePoint);
|
|
}
|
|
|
|
//init math after points are added
|
|
switch (mathType)
|
|
{
|
|
case MathTypeEnum.Base:
|
|
Math = new BGCurveBaseMath(Curve, config);
|
|
break;
|
|
case MathTypeEnum.Formula:
|
|
#pragma warning disable 0618
|
|
Math = new BGCurveFormulaMath(Curve, config);
|
|
#pragma warning restore 0618
|
|
|
|
break;
|
|
case MathTypeEnum.Adaptive:
|
|
Math = new BGCurveAdaptiveMath(Curve, (BGCurveAdaptiveMath.ConfigAdaptive) config);
|
|
break;
|
|
default:
|
|
throw new ArgumentOutOfRangeException("mathType", mathType, null);
|
|
}
|
|
|
|
AddObjects(ObjectsCount, testCurves.ObjectToMove, GameObject.transform);
|
|
|
|
//scale down
|
|
GameObject.transform.localScale = originalScale;
|
|
}
|
|
|
|
public override void Update()
|
|
{
|
|
var curveTransform = Curve.gameObject.transform;
|
|
|
|
var referenceTransform = testCurves.Curve.transform;
|
|
|
|
curveTransform.rotation = referenceTransform.rotation;
|
|
|
|
var moveTime = 10*Time.deltaTime;
|
|
|
|
var current = testCurves.IsCurrent(this);
|
|
curveTransform.position = Vector3.MoveTowards(curveTransform.position, current ? referenceTransform.position : origin, moveTime);
|
|
curveTransform.localScale = Vector3.MoveTowards(curveTransform.localScale, current ? referenceTransform.transform.localScale : originalScale, moveTime/4);
|
|
|
|
UpdateObjects(testCurves.DistanceRatios);
|
|
}
|
|
}
|
|
}
|
|
}
|