添加插件
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[CreateAssetMenu(fileName = "rope section", menuName = "Obi/Rope Section", order = 142)]
|
||||
public class ObiRopeSection : ScriptableObject
|
||||
{
|
||||
[HideInInspector] public List<Vector2> vertices;
|
||||
public int snapX = 0;
|
||||
public int snapY = 0;
|
||||
|
||||
public int Segments{
|
||||
get{return vertices.Count-1;}
|
||||
}
|
||||
|
||||
public void OnEnable(){
|
||||
|
||||
if (vertices == null){
|
||||
vertices = new List<Vector2>();
|
||||
CirclePreset(8);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void CirclePreset(int segments){
|
||||
|
||||
vertices.Clear();
|
||||
|
||||
for (int j = 0; j <= segments; ++j){
|
||||
float angle = 2 * Mathf.PI / segments * j;
|
||||
vertices.Add(Mathf.Cos(angle)*Vector2.right + Mathf.Sin(angle)*Vector2.up);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Snaps a float value to the nearest multiple of snapInterval.
|
||||
*/
|
||||
public static int SnapTo(float val, int snapInterval, int threshold){
|
||||
int intVal = (int) val;
|
||||
if (snapInterval <= 0)
|
||||
return intVal;
|
||||
int under = Mathf.FloorToInt(val / snapInterval) * snapInterval;
|
||||
int over = under + snapInterval;
|
||||
if (intVal - under < threshold) return under;
|
||||
if (over - intVal < threshold) return over;
|
||||
return intVal;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ee7737c43f5734f87be9e49d1bbfba78
|
||||
labels:
|
||||
- ObiRope
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: fdb742a900c8d453ea5ce5027e80ad00, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,16 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
// Abstracts rope topolgy as a list of elements.
|
||||
[System.Serializable]
|
||||
public class ObiStructuralElement
|
||||
{
|
||||
public int particle1;
|
||||
public int particle2;
|
||||
public float restLength;
|
||||
public float constraintForce;
|
||||
public float tearResistance;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2aecff76dda4241c5a0c15349e2419d3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Obi/Scripts/RopeAndRod/DataStructures/Path.meta
Normal file
8
Assets/Obi/Scripts/RopeAndRod/DataStructures/Path.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 75e833f2b944640a5934c15fbec8ac00
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5172d3d605ca94f2db0ad73eaecbc4d4
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,12 @@
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[Serializable]
|
||||
public class ObiColorDataChannel : ObiPathDataChannelIdentity<Color>
|
||||
{
|
||||
public ObiColorDataChannel() : base(new ObiColorInterpolator3D()) { }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4078c779a63154dddac14f5a1e65a692
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,10 @@
|
||||
using System;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[Serializable]
|
||||
public class ObiPhaseDataChannel : ObiPathDataChannelIdentity<int>
|
||||
{
|
||||
public ObiPhaseDataChannel() : base(new ObiConstantInterpolator()) { }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9cfdcf019ed7249799993815bfc3c0bd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,12 @@
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[Serializable]
|
||||
public class ObiMassDataChannel : ObiPathDataChannelIdentity<float>
|
||||
{
|
||||
public ObiMassDataChannel() : base(new ObiCatmullRomInterpolator()) { }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e55025008fa8f4bccae82dbaded0f019
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,12 @@
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[Serializable]
|
||||
public class ObiNormalDataChannel : ObiPathDataChannelIdentity<Vector3>
|
||||
{
|
||||
public ObiNormalDataChannel() : base(new ObiCatmullRomInterpolator3D()) { }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4721087e73d0d422ab48ad62a2fd3d3b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,88 @@
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public interface IObiPathDataChannel
|
||||
{
|
||||
int Count { get; }
|
||||
bool Dirty { get; }
|
||||
void Clean();
|
||||
void RemoveAt(int index);
|
||||
}
|
||||
|
||||
public abstract class ObiPathDataChannel<T,U> : IObiPathDataChannel
|
||||
{
|
||||
protected ObiInterpolator<U> interpolator;
|
||||
protected bool dirty = false;
|
||||
public List<T> data = new List<T>();
|
||||
|
||||
public int Count
|
||||
{
|
||||
get { return data.Count; }
|
||||
}
|
||||
|
||||
public bool Dirty
|
||||
{
|
||||
get { return dirty; }
|
||||
}
|
||||
|
||||
public void Clean()
|
||||
{
|
||||
dirty = false;
|
||||
}
|
||||
|
||||
public ObiPathDataChannel(ObiInterpolator<U> interpolator)
|
||||
{
|
||||
this.interpolator = interpolator;
|
||||
}
|
||||
|
||||
public T this[int i]
|
||||
{
|
||||
get { return data[i]; }
|
||||
set { data[i] = value; dirty = true; }
|
||||
}
|
||||
|
||||
public void RemoveAt(int index)
|
||||
{
|
||||
data.RemoveAt(index);
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
public U Evaluate(U v0, U v1, U v2, U v3, float mu)
|
||||
{
|
||||
return interpolator.Evaluate(v0, v1, v2, v3, mu);
|
||||
}
|
||||
public U EvaluateFirstDerivative(U v0, U v1, U v2, U v3, float mu)
|
||||
{
|
||||
return interpolator.EvaluateFirstDerivative(v0, v1, v2, v3, mu);
|
||||
}
|
||||
public U EvaluateSecondDerivative(U v0, U v1, U v2, U v3, float mu)
|
||||
{
|
||||
return interpolator.EvaluateSecondDerivative(v0, v1, v2, v3, mu);
|
||||
}
|
||||
|
||||
public int GetSpanCount(bool closed)
|
||||
{
|
||||
int cps = Count;
|
||||
if (cps < 2)
|
||||
return 0;
|
||||
|
||||
return closed ? cps : cps - 1;
|
||||
}
|
||||
|
||||
public int GetSpanControlPointAtMu(bool closed, float mu, out float spanMu)
|
||||
{
|
||||
|
||||
int spanCount = GetSpanCount(closed);
|
||||
spanMu = mu * spanCount;
|
||||
int i = (mu >= 1f) ? (spanCount - 1) : (int)spanMu;
|
||||
spanMu -= i;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 43ab47ea5c62b45248edce6a9d099626
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,94 @@
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public abstract class ObiPathDataChannelIdentity<T> : ObiPathDataChannel<T,T>
|
||||
{
|
||||
public ObiPathDataChannelIdentity(ObiInterpolator<T> interpolator) : base(interpolator)
|
||||
{
|
||||
}
|
||||
|
||||
public T GetFirstDerivative(int index)
|
||||
{
|
||||
int nextCP = (index + 1) % Count;
|
||||
|
||||
return EvaluateFirstDerivative(this[index],
|
||||
this[index],
|
||||
this[nextCP],
|
||||
this[nextCP], 0);
|
||||
}
|
||||
|
||||
public T GetSecondDerivative(int index)
|
||||
{
|
||||
int nextCP = (index + 1) % Count;
|
||||
|
||||
return EvaluateSecondDerivative(this[index],
|
||||
this[index],
|
||||
this[nextCP],
|
||||
this[nextCP], 0);
|
||||
}
|
||||
|
||||
public T GetAtMu(bool closed, float mu)
|
||||
{
|
||||
int cps = Count;
|
||||
if (cps >= 2)
|
||||
{
|
||||
float p;
|
||||
int i = GetSpanControlPointAtMu(closed, mu, out p);
|
||||
int nextCP = (i + 1) % cps;
|
||||
|
||||
return Evaluate(this[i],
|
||||
this[i],
|
||||
this[nextCP],
|
||||
this[nextCP], p);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException("Cannot get property in path because it has less than 2 control points.");
|
||||
}
|
||||
}
|
||||
|
||||
public T GetFirstDerivativeAtMu(bool closed, float mu)
|
||||
{
|
||||
int cps = Count;
|
||||
if (cps >= 2)
|
||||
{
|
||||
float p;
|
||||
int i = GetSpanControlPointAtMu(closed, mu, out p);
|
||||
int nextCP = (i + 1) % cps;
|
||||
|
||||
return EvaluateFirstDerivative(this[i],
|
||||
this[i],
|
||||
this[nextCP],
|
||||
this[nextCP], p);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException("Cannot get derivative in path because it has less than 2 control points.");
|
||||
}
|
||||
}
|
||||
|
||||
public T GetSecondDerivativeAtMu(bool closed, float mu)
|
||||
{
|
||||
int cps = Count;
|
||||
if (cps >= 2)
|
||||
{
|
||||
float p;
|
||||
int i = GetSpanControlPointAtMu(closed, mu, out p);
|
||||
int nextCP = (i + 1) % cps;
|
||||
|
||||
return EvaluateSecondDerivative(this[i],
|
||||
this[i],
|
||||
this[nextCP],
|
||||
this[nextCP], p);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException("Cannot get second derivative in path because it has less than 2 control points.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 61b5c82c04eb14f1999e94baa1f073bc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,124 @@
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[Serializable]
|
||||
public class ObiPointsDataChannel : ObiPathDataChannel<ObiWingedPoint, Vector3>
|
||||
{
|
||||
|
||||
public ObiPointsDataChannel() : base(new ObiCatmullRomInterpolator3D()) { }
|
||||
|
||||
public Vector3 GetTangent(int index)
|
||||
{
|
||||
int nextCP = (index + 1) % Count;
|
||||
|
||||
var wp1 = this[index];
|
||||
var wp2 = this[nextCP];
|
||||
|
||||
return EvaluateFirstDerivative(wp1.position,
|
||||
wp1.outTangentEndpoint,
|
||||
wp2.inTangentEndpoint,
|
||||
wp2.position, 0);
|
||||
}
|
||||
|
||||
public Vector3 GetAcceleration(int index)
|
||||
{
|
||||
int nextCP = (index + 1) % Count;
|
||||
|
||||
var wp1 = this[index];
|
||||
var wp2 = this[nextCP];
|
||||
|
||||
return EvaluateSecondDerivative(wp1.position,
|
||||
wp1.outTangentEndpoint,
|
||||
wp2.inTangentEndpoint,
|
||||
wp2.position, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns spline position at time mu, with 0<=mu<=1 where 0 is the start of the spline
|
||||
* and 1 is the end.
|
||||
*/
|
||||
public Vector3 GetPositionAtMu(bool closed,float mu)
|
||||
{
|
||||
int cps = Count;
|
||||
if (cps >= 2)
|
||||
{
|
||||
|
||||
float p;
|
||||
int i = GetSpanControlPointAtMu(closed, mu, out p);
|
||||
int nextCP = (i + 1) % cps;
|
||||
|
||||
var wp1 = this[i];
|
||||
var wp2 = this[nextCP];
|
||||
|
||||
return Evaluate(wp1.position,
|
||||
wp1.outTangentEndpoint,
|
||||
wp2.inTangentEndpoint,
|
||||
wp2.position, p);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException("Cannot get position in path because it has zero control points.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns normal tangent vector at time mu, with 0<=mu<=1 where 0 is the start of the spline
|
||||
* and 1 is the end.
|
||||
*/
|
||||
public Vector3 GetTangentAtMu(bool closed, float mu)
|
||||
{
|
||||
|
||||
int cps = Count;
|
||||
if (cps >= 2)
|
||||
{
|
||||
float p;
|
||||
int i = GetSpanControlPointAtMu(closed, mu, out p);
|
||||
int nextCP = (i + 1) % cps;
|
||||
|
||||
var wp1 = this[i];
|
||||
var wp2 = this[nextCP];
|
||||
|
||||
return EvaluateFirstDerivative(wp1.position,
|
||||
wp1.outTangentEndpoint,
|
||||
wp2.inTangentEndpoint,
|
||||
wp2.position, p);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException("Cannot get derivative in path because it has less than 2 control points.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns acceleration at time mu, with 0<=mu<=1 where 0 is the start of the spline
|
||||
* and 1 is the end.
|
||||
*/
|
||||
public Vector3 GetAccelerationAtMu(bool closed, float mu)
|
||||
{
|
||||
|
||||
int cps = Count;
|
||||
if (cps >= 2)
|
||||
{
|
||||
float p;
|
||||
int i = GetSpanControlPointAtMu(closed, mu, out p);
|
||||
int nextCP = (i + 1) % cps;
|
||||
|
||||
var wp1 = this[i];
|
||||
var wp2 = this[nextCP];
|
||||
|
||||
return EvaluateSecondDerivative(wp1.position,
|
||||
wp1.outTangentEndpoint,
|
||||
wp2.inTangentEndpoint,
|
||||
wp2.position, p);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException("Cannot get second derivative in path because it has less than 2 control points.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d710ff448ae4e4a6f9351a678af9a8ac
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,12 @@
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[Serializable]
|
||||
public class ObiRotationalMassDataChannel : ObiPathDataChannelIdentity<float>
|
||||
{
|
||||
public ObiRotationalMassDataChannel() : base(new ObiCatmullRomInterpolator()) { }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 28c38822e5a79441a8177689f83644e8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,12 @@
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[Serializable]
|
||||
public class ObiThicknessDataChannel : ObiPathDataChannelIdentity<float>
|
||||
{
|
||||
public ObiThicknessDataChannel() : base(new ObiCatmullRomInterpolator()) { }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b414fbc6ce2db42299dc01619ed4fc97
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e85cc8f3b96cf4b4c9be1e6af0a0a99b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,49 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public class ObiCatmullRomInterpolator : ObiInterpolator<float>
|
||||
{
|
||||
/**
|
||||
* 1D bezier spline interpolation
|
||||
*/
|
||||
public float Evaluate(float y0, float y1, float y2, float y3, float mu)
|
||||
{
|
||||
|
||||
float imu = 1 - mu;
|
||||
return imu * imu * imu * y0 +
|
||||
3f * imu * imu * mu * y1 +
|
||||
3f * imu * mu * mu * y2 +
|
||||
mu * mu * mu * y3;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 1D catmull rom spline second derivative
|
||||
*/
|
||||
public float EvaluateFirstDerivative(float y0, float y1, float y2, float y3, float mu)
|
||||
{
|
||||
|
||||
float imu = 1 - mu;
|
||||
return 3f * imu * imu * (y1 - y0) +
|
||||
6f * imu * mu * (y2 - y1) +
|
||||
3f * mu * mu * (y3 - y2);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 1D catmull rom spline second derivative
|
||||
*/
|
||||
public float EvaluateSecondDerivative(float y0, float y1, float y2, float y3, float mu)
|
||||
{
|
||||
|
||||
float imu = 1 - mu;
|
||||
return 3f * imu * imu * (y1 - y0) +
|
||||
6f * imu * mu * (y2 - y1) +
|
||||
3f * mu * mu * (y3 - y2);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 93918aac247384d8289d151d77dc4dc2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,46 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public class ObiCatmullRomInterpolator3D : ObiInterpolator<Vector3>
|
||||
{
|
||||
private ObiCatmullRomInterpolator interpolator = new ObiCatmullRomInterpolator();
|
||||
|
||||
/**
|
||||
* 3D spline interpolation
|
||||
*/
|
||||
public Vector3 Evaluate(Vector3 y0, Vector3 y1, Vector3 y2, Vector3 y3, float mu)
|
||||
{
|
||||
|
||||
return new Vector3(interpolator.Evaluate(y0.x, y1.x, y2.x, y3.x, mu),
|
||||
interpolator.Evaluate(y0.y, y1.y, y2.y, y3.y, mu),
|
||||
interpolator.Evaluate(y0.z, y1.z, y2.z, y3.z, mu));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 3D spline first derivative
|
||||
*/
|
||||
public Vector3 EvaluateFirstDerivative(Vector3 y0, Vector3 y1, Vector3 y2, Vector3 y3, float mu)
|
||||
{
|
||||
|
||||
return new Vector3(interpolator.EvaluateFirstDerivative(y0.x, y1.x, y2.x, y3.x, mu),
|
||||
interpolator.EvaluateFirstDerivative(y0.y, y1.y, y2.y, y3.y, mu),
|
||||
interpolator.EvaluateFirstDerivative(y0.z, y1.z, y2.z, y3.z, mu));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 3D spline second derivative
|
||||
*/
|
||||
public Vector3 EvaluateSecondDerivative(Vector3 y0, Vector3 y1, Vector3 y2, Vector3 y3, float mu)
|
||||
{
|
||||
|
||||
return new Vector3(interpolator.EvaluateSecondDerivative(y0.x, y1.x, y2.x, y3.x, mu),
|
||||
interpolator.EvaluateSecondDerivative(y0.y, y1.y, y2.y, y3.y, mu),
|
||||
interpolator.EvaluateSecondDerivative(y0.z, y1.z, y2.z, y3.z, mu));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 845dbd641b61b490bb94d745b6879e97
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,49 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public class ObiColorInterpolator3D : ObiInterpolator<Color>
|
||||
{
|
||||
private ObiCatmullRomInterpolator interpolator = new ObiCatmullRomInterpolator();
|
||||
|
||||
/**
|
||||
* 3D spline interpolation
|
||||
*/
|
||||
public Color Evaluate(Color y0, Color y1, Color y2, Color y3, float mu)
|
||||
{
|
||||
|
||||
return new Color(interpolator.Evaluate(y0.r, y1.r, y2.r, y3.r, mu),
|
||||
interpolator.Evaluate(y0.g, y1.g, y2.g, y3.g, mu),
|
||||
interpolator.Evaluate(y0.b, y1.b, y2.b, y3.b, mu),
|
||||
interpolator.Evaluate(y0.a, y1.a, y2.a, y3.a, mu));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 3D spline first derivative
|
||||
*/
|
||||
public Color EvaluateFirstDerivative(Color y0, Color y1, Color y2, Color y3, float mu)
|
||||
{
|
||||
|
||||
return new Color(interpolator.EvaluateFirstDerivative(y0.r, y1.r, y2.r, y3.r, mu),
|
||||
interpolator.EvaluateFirstDerivative(y0.g, y1.g, y2.g, y3.g, mu),
|
||||
interpolator.EvaluateFirstDerivative(y0.b, y1.b, y2.b, y3.b, mu),
|
||||
interpolator.EvaluateFirstDerivative(y0.a, y1.a, y2.a, y3.a, mu));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 3D spline second derivative
|
||||
*/
|
||||
public Color EvaluateSecondDerivative(Color y0, Color y1, Color y2, Color y3, float mu)
|
||||
{
|
||||
|
||||
return new Color(interpolator.EvaluateSecondDerivative(y0.r, y1.r, y2.r, y3.r, mu),
|
||||
interpolator.EvaluateSecondDerivative(y0.g, y1.g, y2.g, y3.g, mu),
|
||||
interpolator.EvaluateSecondDerivative(y0.b, y1.b, y2.b, y3.b, mu),
|
||||
interpolator.EvaluateSecondDerivative(y0.a, y1.a, y2.a, y3.a, mu));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1c2bda61c040346db8efd82f64c2422e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,33 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public class ObiConstantInterpolator : ObiInterpolator<int>
|
||||
{
|
||||
/**
|
||||
* constant interpolator
|
||||
*/
|
||||
public int Evaluate(int y0, int y1, int y2, int y3, float mu)
|
||||
{
|
||||
return mu < 0.5f ? y1 : y2;
|
||||
}
|
||||
|
||||
/**
|
||||
* derivative of constant value:
|
||||
*/
|
||||
public int EvaluateFirstDerivative(int y0, int y1, int y2, int y3, float mu)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* second derivative of constant value:
|
||||
*/
|
||||
public int EvaluateSecondDerivative(int y0, int y1, int y2, int y3, float mu)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 33f10aef9ed544b14a762a9c6e8bf411
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,13 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
|
||||
public interface ObiInterpolator<T>
|
||||
{
|
||||
T Evaluate(T v0, T v1, T v2, T v3, float mu);
|
||||
T EvaluateFirstDerivative(T v0, T v1, T v2, T v3, float mu);
|
||||
T EvaluateSecondDerivative(T v0, T v1, T v2, T v3, float mu);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: af25f2a4d723548bfafa551b6da56d25
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
408
Assets/Obi/Scripts/RopeAndRod/DataStructures/Path/ObiPath.cs
Normal file
408
Assets/Obi/Scripts/RopeAndRod/DataStructures/Path/ObiPath.cs
Normal file
@@ -0,0 +1,408 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[System.Serializable]
|
||||
public class PathControlPointEvent : UnityEvent<int>
|
||||
{
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class ObiPath
|
||||
{
|
||||
[HideInInspector] [SerializeField] List<string> m_Names = new List<string>();
|
||||
[HideInInspector] [SerializeField] public ObiPointsDataChannel m_Points = new ObiPointsDataChannel();
|
||||
[HideInInspector] [SerializeField] ObiNormalDataChannel m_Normals = new ObiNormalDataChannel();
|
||||
[HideInInspector] [SerializeField] ObiColorDataChannel m_Colors = new ObiColorDataChannel();
|
||||
[HideInInspector] [SerializeField] ObiThicknessDataChannel m_Thickness = new ObiThicknessDataChannel();
|
||||
[HideInInspector] [SerializeField] ObiMassDataChannel m_Masses = new ObiMassDataChannel();
|
||||
[HideInInspector] [SerializeField] ObiRotationalMassDataChannel m_RotationalMasses = new ObiRotationalMassDataChannel();
|
||||
|
||||
[FormerlySerializedAs("m_Phases")]
|
||||
[HideInInspector] [SerializeField] ObiPhaseDataChannel m_Filters = new ObiPhaseDataChannel();
|
||||
|
||||
[HideInInspector] [SerializeField] private bool m_Closed = false;
|
||||
|
||||
protected bool dirty = false;
|
||||
protected const int arcLenghtSamples = 20;
|
||||
[HideInInspector] [SerializeField] protected List<float> m_ArcLengthTable = new List<float>();
|
||||
[HideInInspector] [SerializeField] protected float m_TotalSplineLenght = 0.0f;
|
||||
|
||||
public UnityEvent OnPathChanged = new UnityEvent();
|
||||
public PathControlPointEvent OnControlPointAdded = new PathControlPointEvent();
|
||||
public PathControlPointEvent OnControlPointRemoved = new PathControlPointEvent();
|
||||
public PathControlPointEvent OnControlPointRenamed = new PathControlPointEvent();
|
||||
|
||||
private IEnumerable<IObiPathDataChannel> GetDataChannels()
|
||||
{
|
||||
yield return m_Points;
|
||||
yield return m_Normals;
|
||||
yield return m_Colors;
|
||||
yield return m_Thickness;
|
||||
yield return m_Masses;
|
||||
yield return m_RotationalMasses;
|
||||
yield return m_Filters;
|
||||
}
|
||||
|
||||
public ObiPointsDataChannel points { get { return m_Points; }}
|
||||
public ObiNormalDataChannel normals { get { return m_Normals; } }
|
||||
public ObiColorDataChannel colors { get { return m_Colors; } }
|
||||
public ObiThicknessDataChannel thicknesses { get { return m_Thickness; } }
|
||||
public ObiMassDataChannel masses { get { return m_Masses; } }
|
||||
public ObiRotationalMassDataChannel rotationalMasses { get { return m_RotationalMasses; } }
|
||||
public ObiPhaseDataChannel filters { get { return m_Filters; } }
|
||||
|
||||
public ReadOnlyCollection<float> ArcLengthTable
|
||||
{
|
||||
get { return m_ArcLengthTable.AsReadOnly(); }
|
||||
}
|
||||
|
||||
public float Length
|
||||
{
|
||||
get { return m_TotalSplineLenght; }
|
||||
}
|
||||
|
||||
public int ArcLengthSamples
|
||||
{
|
||||
get { return arcLenghtSamples; }
|
||||
}
|
||||
|
||||
public int ControlPointCount
|
||||
{
|
||||
get { return m_Points.Count;}
|
||||
}
|
||||
|
||||
public bool Closed
|
||||
{
|
||||
get { return m_Closed; }
|
||||
set
|
||||
{
|
||||
if (value != m_Closed)
|
||||
{
|
||||
m_Closed = value;
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int GetSpanCount()
|
||||
{
|
||||
return m_Points.GetSpanCount(m_Closed);
|
||||
}
|
||||
|
||||
public int GetSpanControlPointForMu(float mu, out float spanMu)
|
||||
{
|
||||
return m_Points.GetSpanControlPointAtMu(m_Closed, mu, out spanMu);
|
||||
}
|
||||
|
||||
public int GetClosestControlPointIndex(float mu)
|
||||
{
|
||||
float spanMu;
|
||||
int cp = GetSpanControlPointForMu(mu, out spanMu);
|
||||
|
||||
if (spanMu > 0.5f)
|
||||
return (cp + 1) % ControlPointCount;
|
||||
else
|
||||
return cp % ControlPointCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the curve parameter (mu) at a certain length of the curve, using linear interpolation
|
||||
* of the values cached in arcLengthTable.
|
||||
*/
|
||||
public float GetMuAtLenght(float length)
|
||||
{
|
||||
if (length <= 0) return 0;
|
||||
if (length >= m_TotalSplineLenght) return 1;
|
||||
|
||||
int i;
|
||||
for (i = 1; i < m_ArcLengthTable.Count; ++i)
|
||||
{
|
||||
if (length < m_ArcLengthTable[i]) break;
|
||||
}
|
||||
|
||||
float prevMu = (i - 1) / (float)(m_ArcLengthTable.Count - 1);
|
||||
float nextMu = i / (float)(m_ArcLengthTable.Count - 1);
|
||||
|
||||
float s = (length - m_ArcLengthTable[i - 1]) / (m_ArcLengthTable[i] - m_ArcLengthTable[i - 1]);
|
||||
|
||||
return prevMu + (nextMu - prevMu) * s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recalculates spline arc lenght in world space using Gauss-Lobatto adaptive integration.
|
||||
* @param acc minimum accuray desired (eg 0.00001f)
|
||||
* @param maxevals maximum number of spline evaluations we want to allow per segment.
|
||||
*/
|
||||
public float RecalculateLenght(Matrix4x4 referenceFrame, float acc, int maxevals)
|
||||
{
|
||||
if (referenceFrame == null)
|
||||
{
|
||||
m_TotalSplineLenght = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
m_TotalSplineLenght = 0.0f;
|
||||
m_ArcLengthTable.Clear();
|
||||
m_ArcLengthTable.Add(0);
|
||||
|
||||
float step = 1 / (float)(arcLenghtSamples + 1);
|
||||
int controlPoints = ControlPointCount;
|
||||
|
||||
if (controlPoints >= 2)
|
||||
{
|
||||
|
||||
int spans = GetSpanCount();
|
||||
|
||||
for (int cp = 0; cp < spans; ++cp)
|
||||
{
|
||||
int nextCP = (cp + 1) % controlPoints;
|
||||
var wp1 = m_Points[cp];
|
||||
var wp2 = m_Points[nextCP];
|
||||
|
||||
Vector3 _p = referenceFrame.MultiplyPoint3x4(wp1.position);
|
||||
Vector3 p = referenceFrame.MultiplyPoint3x4(wp1.outTangentEndpoint);
|
||||
Vector3 p_ = referenceFrame.MultiplyPoint3x4(wp2.inTangentEndpoint);
|
||||
Vector3 p__ = referenceFrame.MultiplyPoint3x4(wp2.position);
|
||||
|
||||
for (int i = 0; i <= Mathf.Max(1, arcLenghtSamples); ++i)
|
||||
{
|
||||
|
||||
float a = i * step;
|
||||
float b = (i + 1) * step;
|
||||
|
||||
float segmentLength = GaussLobattoIntegrationStep(_p, p, p_, p__, a, b,
|
||||
m_Points.EvaluateFirstDerivative(_p, p, p_, p__, a).magnitude,
|
||||
m_Points.EvaluateFirstDerivative(_p, p, p_, p__, b).magnitude, 0, maxevals, acc);
|
||||
|
||||
m_TotalSplineLenght += segmentLength;
|
||||
|
||||
m_ArcLengthTable.Add(m_TotalSplineLenght);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("A path needs at least 2 control points to be defined.");
|
||||
}
|
||||
|
||||
return m_TotalSplineLenght;
|
||||
}
|
||||
|
||||
/**
|
||||
* One step of the adaptive integration method using Gauss-Lobatto quadrature.
|
||||
* Takes advantage of the fact that the arc lenght of a vector function is equal to the
|
||||
* integral of the magnitude of first derivative.
|
||||
*/
|
||||
private float GaussLobattoIntegrationStep(Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4,
|
||||
float a, float b,
|
||||
float fa, float fb, int nevals, int maxevals, float acc)
|
||||
{
|
||||
|
||||
if (nevals >= maxevals) return 0;
|
||||
|
||||
// Constants used in the algorithm
|
||||
float alpha = Mathf.Sqrt(2.0f / 3.0f);
|
||||
float beta = 1.0f / Mathf.Sqrt(5.0f);
|
||||
|
||||
// Here the abcissa points and function values for both the 4-point
|
||||
// and the 7-point rule are calculated (the points at the end of
|
||||
// interval come from the function call, i.e., fa and fb. Also note
|
||||
// the 7-point rule re-uses all the points of the 4-point rule.)
|
||||
float h = (b - a) / 2;
|
||||
float m = (a + b) / 2;
|
||||
|
||||
float mll = m - alpha * h;
|
||||
float ml = m - beta * h;
|
||||
float mr = m + beta * h;
|
||||
float mrr = m + alpha * h;
|
||||
nevals += 5;
|
||||
|
||||
float fmll = m_Points.EvaluateFirstDerivative(p1, p2, p3, p4, mll).magnitude;
|
||||
float fml = m_Points.EvaluateFirstDerivative(p1, p2, p3, p4, ml).magnitude;
|
||||
float fm = m_Points.EvaluateFirstDerivative(p1, p2, p3, p4, m).magnitude;
|
||||
float fmr = m_Points.EvaluateFirstDerivative(p1, p2, p3, p4, mr).magnitude;
|
||||
float fmrr = m_Points.EvaluateFirstDerivative(p1, p2, p3, p4, mrr).magnitude;
|
||||
|
||||
// Both the 4-point and 7-point rule integrals are evaluted
|
||||
float integral4 = (h / 6) * (fa + fb + 5 * (fml + fmr));
|
||||
float integral7 = (h / 1470) * (77 * (fa + fb) + 432 * (fmll + fmrr) + 625 * (fml + fmr) + 672 * fm);
|
||||
|
||||
// The difference betwen the 4-point and 7-point integrals is the
|
||||
// estimate of the accuracy
|
||||
|
||||
if ((integral4 - integral7) < acc || mll <= a || b <= mrr)
|
||||
{
|
||||
if (!(m > a && b > m))
|
||||
{
|
||||
Debug.LogError("Spline integration reached an interval with no more machine numbers");
|
||||
}
|
||||
return integral7;
|
||||
}
|
||||
else
|
||||
{
|
||||
return GaussLobattoIntegrationStep(p1, p2, p3, p4, a, mll, fa, fmll, nevals, maxevals, acc)
|
||||
+ GaussLobattoIntegrationStep(p1, p2, p3, p4, mll, ml, fmll, fml, nevals, maxevals, acc)
|
||||
+ GaussLobattoIntegrationStep(p1, p2, p3, p4, ml, m, fml, fm, nevals, maxevals, acc)
|
||||
+ GaussLobattoIntegrationStep(p1, p2, p3, p4, m, mr, fm, fmr, nevals, maxevals, acc)
|
||||
+ GaussLobattoIntegrationStep(p1, p2, p3, p4, mr, mrr, fmr, fmrr, nevals, maxevals, acc)
|
||||
+ GaussLobattoIntegrationStep(p1, p2, p3, p4, mrr, b, fmrr, fb, nevals, maxevals, acc);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void SetName(int index, string name)
|
||||
{
|
||||
m_Names[index] = name;
|
||||
if (OnControlPointRenamed != null)
|
||||
OnControlPointRenamed.Invoke(index);
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
public string GetName(int index)
|
||||
{
|
||||
return m_Names[index];
|
||||
}
|
||||
|
||||
public void AddControlPoint(Vector3 position, Vector3 inTangentVector, Vector3 outTangentVector, Vector3 normal, float mass, float rotationalMass, float thickness, int filter, Color color, string name)
|
||||
{
|
||||
InsertControlPoint(ControlPointCount, position, inTangentVector, outTangentVector, normal, mass, rotationalMass, thickness, filter, color, name);
|
||||
}
|
||||
|
||||
public void InsertControlPoint(int index, Vector3 position, Vector3 inTangentVector, Vector3 outTangentVector, Vector3 normal, float mass, float rotationalMass, float thickness, int filter, Color color, string name)
|
||||
{
|
||||
m_Points.data.Insert(index, new ObiWingedPoint(inTangentVector,position,outTangentVector));
|
||||
m_Colors.data.Insert(index, color);
|
||||
m_Normals.data.Insert(index, normal);
|
||||
m_Thickness.data.Insert(index, thickness);
|
||||
m_Masses.data.Insert(index, mass);
|
||||
m_RotationalMasses.data.Insert(index, rotationalMass);
|
||||
m_Filters.data.Insert(index, filter);
|
||||
m_Names.Insert(index,name);
|
||||
|
||||
if (OnControlPointAdded != null)
|
||||
OnControlPointAdded.Invoke(index);
|
||||
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
public int InsertControlPoint(float mu)
|
||||
{
|
||||
|
||||
int controlPoints = ControlPointCount;
|
||||
if (controlPoints >= 2)
|
||||
{
|
||||
|
||||
if (!System.Single.IsNaN(mu))
|
||||
{
|
||||
|
||||
float p;
|
||||
int i = GetSpanControlPointForMu(mu, out p);
|
||||
|
||||
int next = (i + 1) % controlPoints;
|
||||
|
||||
var wp1 = m_Points[i];
|
||||
var wp2 = m_Points[next];
|
||||
|
||||
Vector3 P0_1 = (1 - p) * wp1.position + p * wp1.outTangentEndpoint;
|
||||
Vector3 P1_2 = (1 - p) * wp1.outTangentEndpoint + p * wp2.inTangentEndpoint;
|
||||
Vector3 P2_3 = (1 - p) * wp2.inTangentEndpoint + p * wp2.position;
|
||||
|
||||
Vector3 P01_12 = (1 - p) * P0_1 + p * P1_2;
|
||||
Vector3 P12_23 = (1 - p) * P1_2 + p * P2_3;
|
||||
|
||||
Vector3 P0112_1223 = (1 - p) * P01_12 + p * P12_23;
|
||||
|
||||
wp1.SetOutTangentEndpoint(P0_1);
|
||||
wp2.SetInTangentEndpoint(P2_3);
|
||||
|
||||
m_Points[i] = wp1;
|
||||
m_Points[next] = wp2;
|
||||
|
||||
Color color = m_Colors.Evaluate(m_Colors[i],
|
||||
m_Colors[i],
|
||||
m_Colors[next],
|
||||
m_Colors[next], p);
|
||||
|
||||
Vector3 normal = m_Normals.Evaluate(m_Normals[i],
|
||||
m_Normals[i],
|
||||
m_Normals[next],
|
||||
m_Normals[next], p);
|
||||
|
||||
float thickness = m_Thickness.Evaluate(m_Thickness[i],
|
||||
m_Thickness[i],
|
||||
m_Thickness[next],
|
||||
m_Thickness[next], p);
|
||||
|
||||
float mass = m_Masses.Evaluate(m_Masses[i],
|
||||
m_Masses[i],
|
||||
m_Masses[next],
|
||||
m_Masses[next], p);
|
||||
|
||||
float rotationalMass = m_RotationalMasses.Evaluate(m_RotationalMasses[i],
|
||||
m_RotationalMasses[i],
|
||||
m_RotationalMasses[next],
|
||||
m_RotationalMasses[next], p);
|
||||
|
||||
int filter = m_Filters.Evaluate(m_Filters[i],
|
||||
m_Filters[i],
|
||||
m_Filters[next],
|
||||
m_Filters[next], p);
|
||||
|
||||
InsertControlPoint(i + 1, P0112_1223, P01_12 - P0112_1223, P12_23 - P0112_1223, normal, mass,rotationalMass, thickness, filter, color, GetName(i));
|
||||
|
||||
return i + 1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
for (int i = ControlPointCount-1; i >= 0; --i)
|
||||
RemoveControlPoint(i);
|
||||
|
||||
m_TotalSplineLenght = 0.0f;
|
||||
m_ArcLengthTable.Clear();
|
||||
m_ArcLengthTable.Add(0);
|
||||
}
|
||||
|
||||
public void RemoveControlPoint(int index)
|
||||
{
|
||||
foreach (var channel in GetDataChannels())
|
||||
channel.RemoveAt(index);
|
||||
|
||||
m_Names.RemoveAt(index);
|
||||
|
||||
if (OnControlPointRemoved != null)
|
||||
OnControlPointRemoved.Invoke(index);
|
||||
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
public void FlushEvents()
|
||||
{
|
||||
bool isDirty = dirty;
|
||||
foreach (var channel in GetDataChannels())
|
||||
{
|
||||
isDirty |= channel.Dirty;
|
||||
channel.Clean();
|
||||
}
|
||||
|
||||
if (OnPathChanged != null && isDirty)
|
||||
{
|
||||
dirty = false;
|
||||
OnPathChanged.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ee1575a4e45ef4a8ebafa0e5e2e51da5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,170 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public struct ObiPathFrame
|
||||
{
|
||||
public enum Axis
|
||||
{
|
||||
X = 0,
|
||||
Y = 1,
|
||||
Z = 2
|
||||
}
|
||||
|
||||
public static ObiPathFrame Identity => new ObiPathFrame(Vector3.zero, Vector3.forward, Vector3.up, Vector3.right, Color.white, 0);
|
||||
|
||||
public Vector3 position;
|
||||
|
||||
public Vector3 tangent;
|
||||
public Vector3 normal;
|
||||
public Vector3 binormal;
|
||||
|
||||
public Vector4 color;
|
||||
public float thickness;
|
||||
|
||||
public ObiPathFrame(Vector3 position, Vector3 tangent, Vector3 normal, Vector3 binormal, Vector4 color, float thickness){
|
||||
this.position = position;
|
||||
this.normal = normal;
|
||||
this.tangent = tangent;
|
||||
this.binormal = binormal;
|
||||
this.color = color;
|
||||
this.thickness = thickness;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
position = Vector3.zero;
|
||||
tangent = Vector3.forward;
|
||||
normal = Vector3.up;
|
||||
binormal = Vector3.right;
|
||||
color = Color.white;
|
||||
thickness = 0;
|
||||
}
|
||||
|
||||
public static ObiPathFrame operator +(ObiPathFrame c1, ObiPathFrame c2)
|
||||
{
|
||||
return new ObiPathFrame(c1.position + c2.position,c1.tangent + c2.tangent,c1.normal + c2.normal,c1.binormal + c2.binormal,c1.color + c2.color, c1.thickness + c2.thickness);
|
||||
}
|
||||
|
||||
public static ObiPathFrame operator *(float f,ObiPathFrame c)
|
||||
{
|
||||
return new ObiPathFrame(c.position * f, c.tangent * f, c.normal * f, c.binormal * f,c.color * f, c.thickness * f);
|
||||
}
|
||||
|
||||
public static void WeightedSum(float w1, float w2, float w3, in ObiPathFrame c1, in ObiPathFrame c2, in ObiPathFrame c3, ref ObiPathFrame sum)
|
||||
{
|
||||
sum.position.x = c1.position.x * w1 + c2.position.x * w2 + c3.position.x * w3;
|
||||
sum.position.y = c1.position.y * w1 + c2.position.y * w2 + c3.position.y * w3;
|
||||
sum.position.z = c1.position.z * w1 + c2.position.z * w2 + c3.position.z * w3;
|
||||
|
||||
sum.tangent.x = c1.tangent.x * w1 + c2.tangent.x * w2 + c3.tangent.x * w3;
|
||||
sum.tangent.y = c1.tangent.y * w1 + c2.tangent.y * w2 + c3.tangent.y * w3;
|
||||
sum.tangent.z = c1.tangent.z * w1 + c2.tangent.z * w2 + c3.tangent.z * w3;
|
||||
|
||||
sum.normal.x = c1.normal.x * w1 + c2.normal.x * w2 + c3.normal.x * w3;
|
||||
sum.normal.y = c1.normal.y * w1 + c2.normal.y * w2 + c3.normal.y * w3;
|
||||
sum.normal.z = c1.normal.z * w1 + c2.normal.z * w2 + c3.normal.z * w3;
|
||||
|
||||
sum.binormal.x = c1.binormal.x * w1 + c2.binormal.x * w2 + c3.binormal.x * w3;
|
||||
sum.binormal.y = c1.binormal.y * w1 + c2.binormal.y * w2 + c3.binormal.y * w3;
|
||||
sum.binormal.z = c1.binormal.z * w1 + c2.binormal.z * w2 + c3.binormal.z * w3;
|
||||
|
||||
sum.color.x = c1.color.x * w1 + c2.color.x * w2 + c3.color.x * w3;
|
||||
sum.color.y = c1.color.y * w1 + c2.color.y * w2 + c3.color.y * w3;
|
||||
sum.color.z = c1.color.z * w1 + c2.color.z * w2 + c3.color.z * w3;
|
||||
sum.color.w = c1.color.w * w1 + c2.color.w * w2 + c3.color.w * w3;
|
||||
|
||||
sum.thickness = c1.thickness * w1 + c2.thickness * w2 + c3.thickness * w3;
|
||||
}
|
||||
|
||||
public void SetTwist(float twist)
|
||||
{
|
||||
Quaternion twistQ = Quaternion.AngleAxis(twist, tangent);
|
||||
normal = twistQ * normal;
|
||||
binormal = twistQ * binormal;
|
||||
}
|
||||
|
||||
public void SetTwistAndTangent(float twist, Vector3 tangent)
|
||||
{
|
||||
this.tangent = tangent;
|
||||
normal = new Vector3(tangent.y, tangent.x, 0).normalized;
|
||||
binormal = Vector3.Cross(normal, tangent);
|
||||
|
||||
Quaternion twistQ = Quaternion.AngleAxis(twist, tangent);
|
||||
normal = twistQ * normal;
|
||||
binormal = twistQ * binormal;
|
||||
}
|
||||
|
||||
public void Transport(ObiPathFrame frame, float twist)
|
||||
{
|
||||
// Calculate delta rotation:
|
||||
Quaternion rotQ = Quaternion.FromToRotation(tangent, frame.tangent);
|
||||
Quaternion twistQ = Quaternion.AngleAxis(twist, frame.tangent);
|
||||
Quaternion finalQ = twistQ * rotQ;
|
||||
|
||||
// Rotate previous frame axes to obtain the new ones:
|
||||
normal = finalQ * normal;
|
||||
binormal = finalQ * binormal;
|
||||
tangent = frame.tangent;
|
||||
position = frame.position;
|
||||
thickness = frame.thickness;
|
||||
color = frame.color;
|
||||
}
|
||||
|
||||
public void Transport(Vector3 newPosition, Vector3 newTangent, float twist)
|
||||
{
|
||||
// Calculate delta rotation:
|
||||
Quaternion rotQ = Quaternion.FromToRotation(tangent, newTangent);
|
||||
Quaternion twistQ = Quaternion.AngleAxis(twist, newTangent);
|
||||
Quaternion finalQ = twistQ * rotQ;
|
||||
|
||||
// Rotate previous frame axes to obtain the new ones:
|
||||
normal = finalQ * normal;
|
||||
binormal = finalQ * binormal;
|
||||
tangent = newTangent;
|
||||
position = newPosition;
|
||||
|
||||
}
|
||||
|
||||
// Transport, hinting the normal.
|
||||
public void Transport(Vector3 newPosition, Vector3 newTangent, Vector3 newNormal, float twist)
|
||||
{
|
||||
normal = Quaternion.AngleAxis(twist, newTangent) * newNormal;
|
||||
tangent = newTangent;
|
||||
binormal = Vector3.Cross(normal, tangent);
|
||||
position = newPosition;
|
||||
}
|
||||
|
||||
public Matrix4x4 ToMatrix(Axis mainAxis)
|
||||
{
|
||||
Matrix4x4 basis = new Matrix4x4();
|
||||
|
||||
int xo = ((int)mainAxis) % 3 * 4;
|
||||
int yo = ((int)mainAxis + 1) % 3 * 4;
|
||||
int zo = ((int)mainAxis + 2) % 3 * 4;
|
||||
|
||||
basis[xo] = tangent[0];
|
||||
basis[xo + 1] = tangent[1];
|
||||
basis[xo + 2] = tangent[2];
|
||||
|
||||
basis[yo] = binormal[0];
|
||||
basis[yo + 1] = binormal[1];
|
||||
basis[yo + 2] = binormal[2];
|
||||
|
||||
basis[zo] = normal[0];
|
||||
basis[zo + 1] = normal[1];
|
||||
basis[zo + 2] = normal[2];
|
||||
|
||||
return basis;
|
||||
}
|
||||
|
||||
public void DebugDraw(float size)
|
||||
{
|
||||
Debug.DrawRay(position, binormal * size, Color.red);
|
||||
Debug.DrawRay(position, normal * size, Color.green);
|
||||
Debug.DrawRay(position, tangent * size, Color.blue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 237e9ecf813f646fd8502768445f4ab6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,101 @@
|
||||
using UnityEngine;
|
||||
using System;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[ExecuteInEditMode]
|
||||
[RequireComponent(typeof(ObiRopeBase))]
|
||||
public class ObiPathSmoother : MonoBehaviour, ObiActorRenderer<ObiPathSmoother>
|
||||
{
|
||||
[Range(0, 1)]
|
||||
[Tooltip("Curvature threshold below which the path will be decimated. A value of 0 won't apply any decimation. As you increase the value, decimation will become more aggresive.")]
|
||||
public float decimation = 0;
|
||||
|
||||
[Range(0, 3)]
|
||||
[Tooltip("Smoothing iterations applied to the path. A smoothing value of 0 won't perform any smoothing at all. Note that smoothing is applied after decimation.")]
|
||||
public uint smoothing = 0;
|
||||
|
||||
[Tooltip("Twist in degrees applied to each sucessive path section.")]
|
||||
public float twist = 0;
|
||||
|
||||
public ObiActor actor { get; private set; }
|
||||
|
||||
[HideInInspector] public int indexInSystem = 0;
|
||||
|
||||
public float SmoothLength
|
||||
{
|
||||
get
|
||||
{
|
||||
if (actor.isLoaded)
|
||||
{
|
||||
var system = actor.solver.GetRenderSystem<ObiPathSmoother>() as ObiPathSmootherRenderSystem;
|
||||
|
||||
if (system != null)
|
||||
return system.GetSmoothLength(indexInSystem);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public float SmoothSections
|
||||
{
|
||||
get {
|
||||
if (actor.isLoaded)
|
||||
{
|
||||
var system = actor.solver.GetRenderSystem<ObiPathSmoother>() as ObiPathSmootherRenderSystem;
|
||||
|
||||
if (system != null)
|
||||
return system.GetSmoothFrameCount(indexInSystem);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnEnable()
|
||||
{
|
||||
actor = GetComponent<ObiActor>();
|
||||
((ObiActorRenderer<ObiPathSmoother>)this).EnableRenderer();
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
((ObiActorRenderer<ObiPathSmoother>)this).DisableRenderer();
|
||||
}
|
||||
|
||||
private void OnValidate()
|
||||
{
|
||||
((ObiActorRenderer<ObiPathSmoother>)this).SetRendererDirty(Oni.RenderingSystemType.AllSmoothedRopes);
|
||||
}
|
||||
|
||||
public ObiPathFrame GetSectionAt(float mu)
|
||||
{
|
||||
if (actor.isLoaded)
|
||||
{
|
||||
var system = actor.solver.GetRenderSystem<ObiPathSmoother>() as ObiPathSmootherRenderSystem;
|
||||
|
||||
if (system != null)
|
||||
return system.GetFrameAt(indexInSystem, mu);
|
||||
}
|
||||
|
||||
return ObiPathFrame.Identity;
|
||||
}
|
||||
|
||||
RenderSystem<ObiPathSmoother> ObiRenderer<ObiPathSmoother>.CreateRenderSystem(ObiSolver solver)
|
||||
{
|
||||
switch (solver.backendType)
|
||||
{
|
||||
|
||||
#if (OBI_BURST && OBI_MATHEMATICS && OBI_COLLECTIONS)
|
||||
case ObiSolver.BackendType.Burst: return new BurstPathSmootherRenderSystem(solver);
|
||||
#endif
|
||||
case ObiSolver.BackendType.Compute:
|
||||
default:
|
||||
|
||||
if (SystemInfo.supportsComputeShaders)
|
||||
return new ComputePathSmootherRenderSystem(solver);
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 958c969cfb16745f192d4d7bd28b7178
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 8791eecf125744cbeadea65319c29d5a, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,100 @@
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[Serializable]
|
||||
public struct ObiWingedPoint
|
||||
{
|
||||
public enum TangentMode
|
||||
{
|
||||
Aligned,
|
||||
Mirrored,
|
||||
Free,
|
||||
}
|
||||
|
||||
public TangentMode tangentMode;
|
||||
public Vector3 inTangent;
|
||||
public Vector3 position;
|
||||
public Vector3 outTangent;
|
||||
|
||||
public Vector3 inTangentEndpoint
|
||||
{
|
||||
get { return position + inTangent; }
|
||||
}
|
||||
|
||||
public Vector3 outTangentEndpoint
|
||||
{
|
||||
get { return position + outTangent; }
|
||||
}
|
||||
|
||||
public ObiWingedPoint(Vector3 inTangent, Vector3 point, Vector3 outTangent)
|
||||
{
|
||||
this.tangentMode = TangentMode.Aligned;
|
||||
this.inTangent = inTangent;
|
||||
this.position = point;
|
||||
this.outTangent = outTangent;
|
||||
}
|
||||
|
||||
public void SetInTangentEndpoint(Vector3 value)
|
||||
{
|
||||
Vector3 newTangent = value - position;
|
||||
|
||||
switch (tangentMode)
|
||||
{
|
||||
case TangentMode.Mirrored: outTangent = -newTangent; break;
|
||||
case TangentMode.Aligned: outTangent = -newTangent.normalized * outTangent.magnitude; break;
|
||||
}
|
||||
|
||||
inTangent = newTangent;
|
||||
}
|
||||
|
||||
public void SetOutTangentEndpoint(Vector3 value)
|
||||
{
|
||||
Vector3 newTangent = value - position;
|
||||
|
||||
switch (tangentMode)
|
||||
{
|
||||
case TangentMode.Mirrored: inTangent = -newTangent; break;
|
||||
case TangentMode.Aligned: inTangent = -newTangent.normalized * inTangent.magnitude; break;
|
||||
}
|
||||
|
||||
outTangent = newTangent;
|
||||
}
|
||||
|
||||
public void SetInTangent(Vector3 value)
|
||||
{
|
||||
Vector3 newTangent = value;
|
||||
|
||||
switch (tangentMode)
|
||||
{
|
||||
case TangentMode.Mirrored: outTangent = -newTangent; break;
|
||||
case TangentMode.Aligned: outTangent = -newTangent.normalized * outTangent.magnitude; break;
|
||||
}
|
||||
|
||||
inTangent = newTangent;
|
||||
}
|
||||
|
||||
public void SetOutTangent(Vector3 value)
|
||||
{
|
||||
Vector3 newTangent = value;
|
||||
|
||||
switch (tangentMode)
|
||||
{
|
||||
case TangentMode.Mirrored: inTangent = -newTangent; break;
|
||||
case TangentMode.Aligned: inTangent = -newTangent.normalized * inTangent.magnitude; break;
|
||||
}
|
||||
|
||||
outTangent = newTangent;
|
||||
}
|
||||
|
||||
public void Transform(Vector3 translation, Quaternion rotation, Vector3 scale)
|
||||
{
|
||||
position += translation;
|
||||
inTangent = rotation * Vector3.Scale(inTangent, scale);
|
||||
outTangent = rotation * Vector3.Scale(outTangent, scale);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 76ee869b5f2e5440ea0a1c8a1e161cde
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user