升级obi
This commit is contained in:
21
Assets/Obi/Scripts/Common/Utils/Attributes/LayerField.cs
Normal file
21
Assets/Obi/Scripts/Common/Utils/Attributes/LayerField.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
||||
namespace Obi{
|
||||
|
||||
[AttributeUsage(AttributeTargets.Field)]
|
||||
public class LayerField : MultiPropertyAttribute
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
property.intValue = EditorGUI.LayerField(position, label, property.intValue);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 12c0ac28542b14de6a887a6a9067d86d
|
||||
timeCreated: 1487351379
|
||||
licenseType: Store
|
||||
guid: 636fa558efd1441fdbf787bdda34c53a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
@@ -16,7 +16,7 @@ namespace Obi{
|
||||
|
||||
public virtual void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
EditorGUI.PropertyField(position,property,label);
|
||||
EditorGUI.PropertyField(position,property,label,true);
|
||||
}
|
||||
|
||||
internal virtual void OnPreGUI(Rect position, SerializedProperty property){}
|
||||
@@ -53,8 +53,9 @@ namespace Obi{
|
||||
if (!attr.IsVisible(property))
|
||||
return -EditorGUIUtility.standardVerticalSpacing;
|
||||
|
||||
// In case no attribute returns a modified height, return the property's default one:
|
||||
float height = base.GetPropertyHeight(property, label);
|
||||
// In case no attribute returns a modified height, return the property's default one:
|
||||
float height = EditorGUI.GetPropertyHeight(property, label, true);
|
||||
//base.GetPropertyHeight(property, label);
|
||||
|
||||
// Check if any of the attributes wants to modify height:
|
||||
foreach (object atr in mAttribute.stored)
|
||||
|
||||
@@ -48,15 +48,18 @@ namespace Obi{
|
||||
// If any changes were detected, call the property setter:
|
||||
if (EditorGUI.EndChangeCheck() && propertyFieldInfo != null)
|
||||
{
|
||||
|
||||
// Record object state for undo:
|
||||
Undo.RecordObject(property.serializedObject.targetObject, "Inspector");
|
||||
|
||||
// Call property setter:
|
||||
propertyFieldInfo.SetValue(target,value,null);
|
||||
foreach (var t in property.serializedObject.targetObjects)
|
||||
{
|
||||
// Record object state for undo:
|
||||
Undo.RecordObject(t, "Inspector");
|
||||
|
||||
// Record prefab modification:
|
||||
PrefabUtility.RecordPrefabInstancePropertyModifications(property.serializedObject.targetObject);
|
||||
// Call property setter:
|
||||
propertyFieldInfo.SetValue(t, value, null);
|
||||
SetPropertyValue(property, propertyFieldInfo.PropertyType, value);
|
||||
|
||||
// Record prefab modification:
|
||||
PrefabUtility.RecordPrefabInstancePropertyModifications(t);
|
||||
}
|
||||
}
|
||||
EditorGUI.EndProperty();
|
||||
|
||||
@@ -68,18 +71,18 @@ namespace Obi{
|
||||
|
||||
private object GetSource(SerializedProperty property)
|
||||
{
|
||||
object target = property.serializedObject.targetObject;
|
||||
object trgt = property.serializedObject.targetObject;
|
||||
string[] data = property.propertyPath.Split('.');
|
||||
|
||||
if (data.Length == 1)
|
||||
return target;
|
||||
return trgt;
|
||||
else{
|
||||
for (int i = 0; i < data.Length-1;++i){
|
||||
target = target.GetType().GetField(data[i]).GetValue(target);
|
||||
trgt = trgt.GetType().GetField(data[i]).GetValue(trgt);
|
||||
}
|
||||
}
|
||||
|
||||
return target;
|
||||
return trgt;
|
||||
}
|
||||
|
||||
private object DrawProperty(Rect position, SerializedPropertyType propertyType, Type type, object value, GUIContent label)
|
||||
@@ -120,7 +123,46 @@ namespace Obi{
|
||||
throw new NotImplementedException("Unimplemented propertyType "+propertyType+".");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void SetPropertyValue(SerializedProperty property, Type type, object value)
|
||||
{
|
||||
switch (property.propertyType)
|
||||
{
|
||||
case SerializedPropertyType.Integer:
|
||||
property.intValue = (int)value; break;
|
||||
case SerializedPropertyType.Boolean:
|
||||
property.boolValue = (bool)value; break;
|
||||
case SerializedPropertyType.Float:
|
||||
property.floatValue = (float)value; break;
|
||||
case SerializedPropertyType.String:
|
||||
property.stringValue = (string)value; break;
|
||||
case SerializedPropertyType.Color:
|
||||
property.colorValue = (Color)value; break;
|
||||
case SerializedPropertyType.ObjectReference:
|
||||
property.objectReferenceValue = (UnityEngine.Object)value; break;
|
||||
case SerializedPropertyType.ExposedReference:
|
||||
property.exposedReferenceValue = (UnityEngine.Object)value; break;
|
||||
case SerializedPropertyType.LayerMask:
|
||||
property.intValue = (int)value; break;
|
||||
case SerializedPropertyType.Enum:
|
||||
property.enumValueIndex = (int)value; break;
|
||||
case SerializedPropertyType.Vector2:
|
||||
property.vector2Value = (Vector2)value; break;
|
||||
case SerializedPropertyType.Vector3:
|
||||
property.vector3Value = (Vector3)value; break;
|
||||
case SerializedPropertyType.Vector4:
|
||||
property.vector4Value = (Vector4)value; break;
|
||||
case SerializedPropertyType.Rect:
|
||||
property.rectValue = (Rect)value; break;
|
||||
case SerializedPropertyType.AnimationCurve:
|
||||
property.animationCurveValue = (AnimationCurve)value; break;
|
||||
case SerializedPropertyType.Bounds:
|
||||
property.boundsValue = (Bounds)value; break;
|
||||
default:
|
||||
throw new NotImplementedException("Unimplemented propertyType " + property.propertyType + ".");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -14,6 +14,7 @@ namespace Obi{
|
||||
|
||||
private MethodInfo eventMethodInfo = null;
|
||||
private FieldInfo fieldInfo = null;
|
||||
private PropertyInfo propertyInfo = null;
|
||||
|
||||
public VisibleIf(string methodName, bool negate = false)
|
||||
{
|
||||
@@ -39,13 +40,19 @@ namespace Obi{
|
||||
// If we could not find a method with that name, look for a field:
|
||||
if (eventMethodInfo == null && fieldInfo == null)
|
||||
fieldInfo = eventOwnerType.GetField(eventName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
|
||||
if (eventMethodInfo != null)
|
||||
|
||||
// or maybe a property
|
||||
if (eventMethodInfo == null && fieldInfo == null && propertyInfo == null)
|
||||
propertyInfo = eventOwnerType.GetProperty(eventName, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
|
||||
if (eventMethodInfo != null)
|
||||
return (bool)eventMethodInfo.Invoke(property.serializedObject.targetObject, null);
|
||||
else if (fieldInfo != null)
|
||||
return (bool)fieldInfo.GetValue(property.serializedObject.targetObject);
|
||||
else
|
||||
Debug.LogWarning(string.Format("VisibleIf: Unable to find method or field {0} in {1}", eventName, eventOwnerType));
|
||||
else if (propertyInfo != null)
|
||||
return (bool)propertyInfo.GetValue(property.serializedObject.targetObject);
|
||||
else
|
||||
Debug.LogWarning(string.Format("VisibleIf: Unable to find method, field or property {0} in {1}", eventName, eventOwnerType));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ public class CoroutineJob{
|
||||
private bool stop;
|
||||
private Exception e;
|
||||
|
||||
public int asyncThreshold = 0; //Time in milliseconds that must pass before job switches to async mode. By default, the job is asynchronous from the start.
|
||||
public int asyncThreshold = 250; //Time in milliseconds that must pass before job switches to async mode. By default, the job is asynchronous from the start.
|
||||
|
||||
private void Init(){
|
||||
isDone = false;
|
||||
|
||||
@@ -6,38 +6,31 @@ using System.Collections;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public class EditorCoroutine
|
||||
{
|
||||
|
||||
public class EditorCoroutine
|
||||
{
|
||||
public static bool ShowCoroutineProgressBar(string title, IEnumerator coroutine)
|
||||
{
|
||||
|
||||
public static void ShowCoroutineProgressBar(string title, ref IEnumerator coroutine){
|
||||
bool cancelled = false;
|
||||
|
||||
#if (UNITY_EDITOR)
|
||||
if (coroutine != null){
|
||||
|
||||
while (coroutine.MoveNext() && !cancelled)
|
||||
{
|
||||
var progressInfo = coroutine.Current as CoroutineJob.ProgressInfo;
|
||||
cancelled |= EditorUtility.DisplayCancelableProgressBar(title, progressInfo.userReadableInfo, progressInfo.progress);
|
||||
}
|
||||
|
||||
// once finished, set coroutine to null and clear progress bar.
|
||||
coroutine = null;
|
||||
EditorUtility.ClearProgressBar();
|
||||
|
||||
}
|
||||
#endif
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
#if (UNITY_EDITOR)
|
||||
if (coroutine != null){
|
||||
|
||||
CoroutineJob.ProgressInfo progressInfo;
|
||||
|
||||
do{
|
||||
if (!coroutine.MoveNext())
|
||||
progressInfo = null;
|
||||
else
|
||||
progressInfo = coroutine.Current as CoroutineJob.ProgressInfo;
|
||||
|
||||
if (progressInfo != null && EditorUtility.DisplayCancelableProgressBar(title, progressInfo.userReadableInfo, progressInfo.progress)){
|
||||
progressInfo = null;
|
||||
}
|
||||
}while (progressInfo != null);
|
||||
|
||||
// once finished, clear progress bar and set coroutine to null.
|
||||
coroutine = null;
|
||||
|
||||
// Unity bug here: https://issuetracker.unity3d.com/issues/unity-throws-nullreferenceexception-or-endlayoutgroup-errors-when-editorutility-dot-clearprogressbar-is-called
|
||||
EditorUtility.ClearProgressBar();
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
using UnityEngine;
|
||||
using System;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public class ObiAmbientForceZone : ObiExternalForce
|
||||
{
|
||||
|
||||
public override void ApplyForcesToActor(ObiActor actor)
|
||||
{
|
||||
|
||||
Matrix4x4 l2sTransform = actor.solver.transform.worldToLocalMatrix * transform.localToWorldMatrix;
|
||||
|
||||
Vector4 force = l2sTransform.MultiplyVector(Vector3.forward * (intensity + GetTurbulence(turbulence)));
|
||||
|
||||
if (actor.usesCustomExternalForces)
|
||||
{
|
||||
for (int i = 0; i < actor.activeParticleCount; ++i)
|
||||
actor.solver.wind[actor.solverIndices[i]] += force;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < actor.activeParticleCount; ++i)
|
||||
actor.solver.externalForces[actor.solverIndices[i]] += force;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnDrawGizmosSelected()
|
||||
{
|
||||
|
||||
Gizmos.matrix = transform.localToWorldMatrix;
|
||||
Gizmos.color = new Color(0,0.7f,1,1);
|
||||
|
||||
// arrow body:
|
||||
ObiUtils.DrawArrowGizmo(0.5f + GetTurbulence(1),0.2f,0.3f,0.2f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
using UnityEngine;
|
||||
using System;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public abstract class ObiExternalForce : MonoBehaviour
|
||||
{
|
||||
|
||||
public float intensity = 0;
|
||||
public float turbulence = 0;
|
||||
public float turbulenceFrequency = 1;
|
||||
public float turbulenceSeed = 0;
|
||||
public ObiSolver[] affectedSolvers;
|
||||
|
||||
public void OnEnable()
|
||||
{
|
||||
foreach (ObiSolver solver in affectedSolvers)
|
||||
{
|
||||
if (solver != null)
|
||||
solver.OnBeginStep += Solver_OnStepBegin;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnDisable()
|
||||
{
|
||||
foreach (ObiSolver solver in affectedSolvers)
|
||||
{
|
||||
if (solver != null)
|
||||
solver.OnBeginStep -= Solver_OnStepBegin;
|
||||
}
|
||||
}
|
||||
|
||||
void Solver_OnStepBegin(ObiSolver solver, float stepTime)
|
||||
{
|
||||
foreach (ObiActor actor in solver.actors)
|
||||
{
|
||||
if (actor != null)
|
||||
ApplyForcesToActor(actor);
|
||||
}
|
||||
}
|
||||
|
||||
protected float GetTurbulence(float turbulenceIntensity){
|
||||
return Mathf.PerlinNoise(Time.fixedTime * turbulenceFrequency,turbulenceSeed) * turbulenceIntensity;
|
||||
}
|
||||
|
||||
public abstract void ApplyForcesToActor(ObiActor actor);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
137
Assets/Obi/Scripts/Common/Utils/Forces/ObiForceZone.cs
Normal file
137
Assets/Obi/Scripts/Common/Utils/Forces/ObiForceZone.cs
Normal file
@@ -0,0 +1,137 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[ExecuteInEditMode]
|
||||
[RequireComponent(typeof(ObiCollider))]
|
||||
public class ObiForceZone : MonoBehaviour
|
||||
{
|
||||
[SerializeProperty("sourceCollider")]
|
||||
[SerializeField] private ObiCollider m_SourceCollider;
|
||||
|
||||
protected ObiForceZoneHandle forcezoneHandle;
|
||||
|
||||
/// <summary>
|
||||
/// The ObiCollider this ObiForceZone should affect.
|
||||
/// </summary>
|
||||
/// This is automatically set when you first create the ObiForceZone component, but you can override it afterwards.
|
||||
public ObiCollider SourceCollider
|
||||
{
|
||||
set
|
||||
{
|
||||
if (value != null && value.gameObject != this.gameObject)
|
||||
{
|
||||
Debug.LogError("The ObiCollider component must reside in the same GameObject as ObiForceZone.");
|
||||
return;
|
||||
}
|
||||
|
||||
RemoveCollider();
|
||||
m_SourceCollider = value;
|
||||
AddCollider();
|
||||
|
||||
}
|
||||
get { return m_SourceCollider; }
|
||||
}
|
||||
|
||||
public ObiForceZoneHandle Handle
|
||||
{
|
||||
get
|
||||
{
|
||||
// don't check forcezoneHandle.isValid:
|
||||
// CreateForceZone may defer creation, so we get a non-null, but invalid handle.
|
||||
// If calling handle again right away before it becomes valid, it will call CreateForceZone again and create a second handle to the same zone.
|
||||
if (forcezoneHandle == null)
|
||||
{
|
||||
var world = ObiColliderWorld.GetInstance();
|
||||
|
||||
// create the material:
|
||||
forcezoneHandle = world.CreateForceZone();
|
||||
forcezoneHandle.owner = this;
|
||||
}
|
||||
return forcezoneHandle;
|
||||
}
|
||||
}
|
||||
|
||||
public ForceZone.ZoneType type;
|
||||
public ForceZone.ForceMode mode;
|
||||
public float intensity;
|
||||
|
||||
[Header("Damping")]
|
||||
public ForceZone.DampingDirection dampingDir;
|
||||
public float damping = 0;
|
||||
|
||||
[Header("Falloff")]
|
||||
public float minDistance;
|
||||
public float maxDistance;
|
||||
[Min(0)]
|
||||
public float falloffPower = 1;
|
||||
|
||||
[Header("Tint")]
|
||||
public Color color = Color.clear;
|
||||
|
||||
[Header("Pulse")]
|
||||
public float pulseIntensity;
|
||||
public float pulseFrequency;
|
||||
public float pulseSeed;
|
||||
|
||||
protected float intensityVariation;
|
||||
|
||||
public void OnEnable()
|
||||
{
|
||||
forcezoneHandle = ObiColliderWorld.GetInstance().CreateForceZone();
|
||||
forcezoneHandle.owner = this;
|
||||
FindSourceCollider();
|
||||
}
|
||||
|
||||
public void OnDisable()
|
||||
{
|
||||
RemoveCollider();
|
||||
ObiColliderWorld.GetInstance().DestroyForceZone(forcezoneHandle);
|
||||
}
|
||||
|
||||
private void FindSourceCollider()
|
||||
{
|
||||
if (SourceCollider == null)
|
||||
SourceCollider = GetComponent<ObiCollider>();
|
||||
else
|
||||
AddCollider();
|
||||
}
|
||||
|
||||
private void AddCollider()
|
||||
{
|
||||
if (m_SourceCollider != null)
|
||||
m_SourceCollider.ForceZone = this;
|
||||
}
|
||||
|
||||
private void RemoveCollider()
|
||||
{
|
||||
if (m_SourceCollider != null)
|
||||
m_SourceCollider.ForceZone = null;
|
||||
}
|
||||
|
||||
public virtual void UpdateIfNeeded()
|
||||
{
|
||||
if (!Handle.isValid)
|
||||
return;
|
||||
|
||||
var fc = ObiColliderWorld.GetInstance().forceZones[Handle.index];
|
||||
fc.type = type;
|
||||
fc.mode = mode;
|
||||
fc.intensity = intensity + intensityVariation;
|
||||
fc.minDistance = minDistance;
|
||||
fc.maxDistance = maxDistance;
|
||||
fc.falloffPower = falloffPower;
|
||||
fc.damping = damping;
|
||||
fc.dampingDir = dampingDir;
|
||||
fc.color = color;
|
||||
ObiColliderWorld.GetInstance().forceZones[Handle.index] = fc;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (Application.isPlaying)
|
||||
intensityVariation = Mathf.PerlinNoise(Time.time * pulseFrequency, pulseSeed) * pulseIntensity;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f05961933f21f46a683fc5d5beec4061
|
||||
guid: 4978a525b6164476d96f5d28d8b309f8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -1,63 +0,0 @@
|
||||
using UnityEngine;
|
||||
using System;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public class ObiSphericalForceZone : ObiExternalForce
|
||||
{
|
||||
|
||||
public float radius = 5;
|
||||
public bool radial = true;
|
||||
|
||||
public override void ApplyForcesToActor(ObiActor actor)
|
||||
{
|
||||
|
||||
float sqrRadius = radius * radius;
|
||||
float finalIntensity = intensity + GetTurbulence(turbulence);
|
||||
|
||||
Matrix4x4 l2sTransform = actor.solver.transform.worldToLocalMatrix * transform.localToWorldMatrix;
|
||||
|
||||
Vector4 center = l2sTransform.MultiplyPoint3x4(Vector4.zero);
|
||||
Vector4 forward = l2sTransform.MultiplyVector(Vector3.forward);
|
||||
|
||||
// Calculate force intensity for each actor particle:
|
||||
for (int i = 0; i < actor.activeParticleCount; ++i){
|
||||
|
||||
Vector4 distanceVector = actor.solver.positions[actor.solverIndices[i]] - center;
|
||||
|
||||
float sqrMag = distanceVector.sqrMagnitude;
|
||||
float falloff = Mathf.Clamp01((sqrRadius - sqrMag) / sqrRadius);
|
||||
|
||||
Vector4 force;
|
||||
if (radial)
|
||||
force = distanceVector/(Mathf.Sqrt(sqrMag) + float.Epsilon) * falloff * finalIntensity;
|
||||
else
|
||||
force = forward * falloff * finalIntensity;
|
||||
|
||||
if (actor.usesCustomExternalForces)
|
||||
actor.solver.wind[actor.solverIndices[i]] += force;
|
||||
else
|
||||
actor.solver.externalForces[actor.solverIndices[i]] += force;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void OnDrawGizmosSelected()
|
||||
{
|
||||
Gizmos.matrix = transform.localToWorldMatrix;
|
||||
Gizmos.color = new Color(0,0.7f,1,1);
|
||||
Gizmos.DrawWireSphere(Vector3.zero,radius);
|
||||
|
||||
float turb = GetTurbulence(1);
|
||||
|
||||
if (!radial){
|
||||
ObiUtils.DrawArrowGizmo(radius + turb,radius*0.2f,radius*0.3f,radius*0.2f);
|
||||
}else{
|
||||
Gizmos.DrawLine(new Vector3(0,0,-radius*0.5f)*turb,new Vector3(0,0,radius*0.5f)*turb);
|
||||
Gizmos.DrawLine(new Vector3(0,-radius*0.5f,0)*turb,new Vector3(0,radius*0.5f,0)*turb);
|
||||
Gizmos.DrawLine(new Vector3(-radius*0.5f,0,0)*turb,new Vector3(radius*0.5f,0,0)*turb);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using Unity.Collections;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
@@ -24,11 +25,11 @@ namespace Obi
|
||||
|
||||
public int Compare(Oni.Contact x, Oni.Contact y)
|
||||
{
|
||||
return CompareByRef(ref x, ref y, solver);
|
||||
return CompareByRef(x, y, solver);
|
||||
}
|
||||
}
|
||||
|
||||
private static int CompareByRef(ref Oni.Contact a, ref Oni.Contact b, ObiSolver solver)
|
||||
private static int CompareByRef(Oni.Contact a, Oni.Contact b, ObiSolver solver)
|
||||
{
|
||||
if (a.bodyB == b.bodyB)
|
||||
{
|
||||
@@ -64,7 +65,7 @@ namespace Obi
|
||||
solver.OnCollision -= Solver_OnCollision;
|
||||
}
|
||||
|
||||
private int FilterOutDistantContacts(Oni.Contact[] data, int count)
|
||||
private int FilterOutDistantContacts(ObiNativeContactList data, int count)
|
||||
{
|
||||
int filteredCount = count;
|
||||
|
||||
@@ -72,12 +73,12 @@ namespace Obi
|
||||
// moving the ones above the threshold to the end of the array:
|
||||
for (int i = count - 1; i >= 0; --i)
|
||||
if (data[i].distance > distanceThreshold)
|
||||
ObiUtils.Swap(ref data[i], ref data[--filteredCount]);
|
||||
data.Swap(i, --filteredCount);
|
||||
|
||||
return filteredCount;
|
||||
}
|
||||
|
||||
private int RemoveDuplicates(Oni.Contact[] data, int count)
|
||||
private int RemoveDuplicates(ObiNativeContactList data, int count)
|
||||
{
|
||||
if (count == 0)
|
||||
return 0;
|
||||
@@ -86,13 +87,13 @@ namespace Obi
|
||||
// replacing duplicates by the first contact that's different:
|
||||
int i = 0, r = 0;
|
||||
while (++i != count)
|
||||
if (CompareByRef(ref data[i], ref data[r], solver) != 0 && ++r != i)
|
||||
if (CompareByRef(data[i], data[r], solver) != 0 && ++r != i)
|
||||
data[r] = data[i];
|
||||
|
||||
return ++r;
|
||||
}
|
||||
|
||||
private void InvokeCallbacks(Oni.Contact[] data, int count)
|
||||
private void InvokeCallbacks(ObiNativeContactList data, int count)
|
||||
{
|
||||
int a = 0, b = 0;
|
||||
int lengthA = count, lengthB = prevCount;
|
||||
@@ -101,7 +102,7 @@ namespace Obi
|
||||
while (a < lengthA && b < lengthB)
|
||||
{
|
||||
// compare both contacts:
|
||||
int compare = CompareByRef(ref data[a], ref prevData[b], solver);
|
||||
int compare = CompareByRef(data[a], prevData[b], solver);
|
||||
|
||||
// call the appropiate event depending on the comparison result:
|
||||
if (compare < 0)
|
||||
@@ -122,30 +123,26 @@ namespace Obi
|
||||
onContactExit.Invoke(solver, prevData[b++]);
|
||||
}
|
||||
|
||||
void Solver_OnCollision(object sender, ObiSolver.ObiCollisionEventArgs args)
|
||||
void Solver_OnCollision(object sender, ObiNativeContactList contacts)
|
||||
{
|
||||
// here we access the internal backing array (Data) directly,
|
||||
// instead of using the accessor property. This slightly improves performance.
|
||||
// note: the backing array length is the lists' capacity, so we
|
||||
// need to use args.contacts.Count to get the actual number of contacts.
|
||||
|
||||
// skip all contacts above the distance threshold by moving them to the end of the array:
|
||||
int filteredCount = FilterOutDistantContacts(args.contacts.Data, args.contacts.Count);
|
||||
int filteredCount = FilterOutDistantContacts(contacts, contacts.count);
|
||||
|
||||
// sort the remaining contacts by collider, then by actor:
|
||||
Array.Sort(args.contacts.Data, 0, filteredCount, comparer);
|
||||
contacts.AsNativeArray().Slice(0,filteredCount).Sort(comparer);
|
||||
|
||||
// remove duplicates:
|
||||
filteredCount = RemoveDuplicates(args.contacts.Data, filteredCount);
|
||||
filteredCount = RemoveDuplicates(contacts, filteredCount);
|
||||
|
||||
// zip trough the current and previous contact lists once, invoking events when appropiate.
|
||||
InvokeCallbacks(args.contacts.Data, filteredCount);
|
||||
InvokeCallbacks(contacts, filteredCount);
|
||||
|
||||
// store current contact list/count for next frame.
|
||||
// could get better performance by double buffering instead of copying:
|
||||
if (filteredCount > prevData.Length)
|
||||
Array.Resize(ref prevData, filteredCount);
|
||||
Array.Copy(args.contacts.Data, prevData, filteredCount);
|
||||
|
||||
contacts.CopyTo(prevData, 0, filteredCount);
|
||||
|
||||
prevCount = filteredCount;
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ public class ObiContactGrabber : MonoBehaviour
|
||||
}
|
||||
}
|
||||
|
||||
private Dictionary<ObiSolver, ObiSolver.ObiCollisionEventArgs> collisionEvents = new Dictionary<ObiSolver, ObiSolver.ObiCollisionEventArgs>(); /**< store the current collision event*/
|
||||
private Dictionary<ObiSolver, ObiNativeContactList> collisionEvents = new Dictionary<ObiSolver, ObiNativeContactList>(); /**< store the current collision event*/
|
||||
private ObiCollider localCollider; /**< the collider on this gameObject.*/
|
||||
private HashSet<GrabbedParticle> grabbedParticles = new HashSet<GrabbedParticle>(); /**< set to store all currently grabbed particles.*/
|
||||
private HashSet<ObiActor> grabbedActors = new HashSet<ObiActor>(); /**< set of softbodies grabbed during this step.*/
|
||||
@@ -69,7 +69,7 @@ public class ObiContactGrabber : MonoBehaviour
|
||||
solver.OnCollision -= Solver_OnCollision;
|
||||
}
|
||||
|
||||
private void Solver_OnCollision(object sender, Obi.ObiSolver.ObiCollisionEventArgs e)
|
||||
private void Solver_OnCollision(object sender, ObiNativeContactList e)
|
||||
{
|
||||
collisionEvents[(ObiSolver)sender] = e;
|
||||
}
|
||||
@@ -122,10 +122,10 @@ public class ObiContactGrabber : MonoBehaviour
|
||||
{
|
||||
foreach (ObiSolver solver in solvers)
|
||||
{
|
||||
ObiSolver.ObiCollisionEventArgs collisionEvent;
|
||||
ObiNativeContactList collisionEvent;
|
||||
if (collisionEvents.TryGetValue(solver, out collisionEvent))
|
||||
{
|
||||
foreach (Oni.Contact contact in collisionEvent.contacts)
|
||||
foreach (Oni.Contact contact in collisionEvent)
|
||||
{
|
||||
// this one is an actual collision:
|
||||
if (contact.distance < 0.01f)
|
||||
|
||||
39
Assets/Obi/Scripts/Common/Utils/ObiFoamEmitter.cs
Normal file
39
Assets/Obi/Scripts/Common/Utils/ObiFoamEmitter.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
using UnityEngine;
|
||||
using System;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
|
||||
[AddComponentMenu("Physics/Obi/Obi Foam Emitter", 1000)]
|
||||
[ExecuteInEditMode]
|
||||
[RequireComponent(typeof(ObiActor))]
|
||||
[DisallowMultipleComponent]
|
||||
public class ObiFoamEmitter : ObiFoamGenerator
|
||||
{
|
||||
public enum ShapeType
|
||||
{
|
||||
Cylinder = 0,
|
||||
Box = 1
|
||||
}
|
||||
|
||||
[Header("Emission shape")]
|
||||
public ShapeType shape;
|
||||
public Transform shapeTransform;
|
||||
public Vector3 shapeSize = Vector3.one;
|
||||
|
||||
private float emissionAccumulator = 0;
|
||||
|
||||
public int GetParticleNumberToEmit(float deltaTime)
|
||||
{
|
||||
emissionAccumulator += foamGenerationRate * deltaTime;
|
||||
int particles = (int)emissionAccumulator;
|
||||
emissionAccumulator -= particles;
|
||||
return particles;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
emissionAccumulator = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8f33b658b41e945e0bae1d3f0af0830e
|
||||
guid: 3a2bd12c1cc9c45428b37635331065db
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 092f06332c018434b8c8ea86164ef4fd, type: 3}
|
||||
icon: {fileID: 2800000, guid: b7cec6e680e3a479ca03a89eccd4e052, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
101
Assets/Obi/Scripts/Common/Utils/ObiFoamGenerator.cs
Normal file
101
Assets/Obi/Scripts/Common/Utils/ObiFoamGenerator.cs
Normal file
@@ -0,0 +1,101 @@
|
||||
using UnityEngine;
|
||||
using System;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
/**
|
||||
* Foam generators create diffuse particles in areas where certain conditions meet (high velocity constrasts, high vorticity, low density, high normal values, etc.). These particles
|
||||
* are then advected trough the fluid velocity field.
|
||||
*/
|
||||
|
||||
[AddComponentMenu("Physics/Obi/Obi Foam Generator", 1000)]
|
||||
[ExecuteInEditMode]
|
||||
[RequireComponent(typeof(ObiActor))]
|
||||
[DisallowMultipleComponent]
|
||||
public class ObiFoamGenerator : MonoBehaviour, ObiActorRenderer<ObiFoamGenerator>
|
||||
{
|
||||
public ObiActor actor { get; private set; }
|
||||
|
||||
[Header("Foam spawning")]
|
||||
public float foamGenerationRate = 100;
|
||||
public float foamPotential = 50;
|
||||
|
||||
[Range(0,1)]
|
||||
public float foamPotentialDiffusion = 0.95f;
|
||||
public Vector2 velocityRange = new Vector2(2, 4);
|
||||
public Vector2 vorticityRange = new Vector2(4, 8);
|
||||
|
||||
[Header("Foam properties")]
|
||||
public Light volumeLight;
|
||||
public Color color = new Color(1,1,1,0.25f);
|
||||
public float size = 0.02f;
|
||||
[Range(0,1)]
|
||||
public float sizeRandom = 0.2f;
|
||||
public float lifetime = 5;
|
||||
[Range(0, 1)]
|
||||
public float lifetimeRandom = 0.2f;
|
||||
|
||||
public float buoyancy = 0.5f;
|
||||
|
||||
[Range(0, 1)]
|
||||
public float drag = 0.5f;
|
||||
|
||||
[Range(0, 1)]
|
||||
public float atmosphericDrag = 0.5f;
|
||||
|
||||
[Range(1, 50)]
|
||||
public float airAging = 2;
|
||||
|
||||
[Range(0, 1)]
|
||||
public float isosurface = 0.02f;
|
||||
|
||||
[Header("Density Control (Compute only)")]
|
||||
[Range(0, 1)]
|
||||
public float pressure = 1;
|
||||
[Range(0, 1)]
|
||||
public float density = 0.3f;
|
||||
[Range(1, 4)]
|
||||
public float smoothingRadius = 2.5f;
|
||||
[Range(0, 1)]
|
||||
public float viscosity = 0.5f;
|
||||
[Min(0)]
|
||||
public float surfaceTension = 2;
|
||||
|
||||
public void Awake()
|
||||
{
|
||||
actor = GetComponent<ObiActor>();
|
||||
}
|
||||
|
||||
public void OnEnable()
|
||||
{
|
||||
((ObiActorRenderer<ObiFoamGenerator>)this).EnableRenderer();
|
||||
}
|
||||
|
||||
public void OnDisable()
|
||||
{
|
||||
((ObiActorRenderer<ObiFoamGenerator>)this).DisableRenderer();
|
||||
}
|
||||
|
||||
public void OnValidate()
|
||||
{
|
||||
((ObiActorRenderer<ObiFoamGenerator>)this).SetRendererDirty(Oni.RenderingSystemType.FoamParticles);
|
||||
}
|
||||
|
||||
RenderSystem<ObiFoamGenerator> ObiRenderer<ObiFoamGenerator>.CreateRenderSystem(ObiSolver solver)
|
||||
{
|
||||
switch (solver.backendType)
|
||||
{
|
||||
|
||||
#if (OBI_BURST && OBI_MATHEMATICS && OBI_COLLECTIONS)
|
||||
case ObiSolver.BackendType.Burst: return new BurstFoamRenderSystem(solver);
|
||||
#endif
|
||||
case ObiSolver.BackendType.Compute:
|
||||
default:
|
||||
|
||||
if (SystemInfo.supportsComputeShaders)
|
||||
return new ComputeFoamRenderSystem(solver);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Obi/Scripts/Common/Utils/ObiFoamGenerator.cs.meta
Normal file
11
Assets/Obi/Scripts/Common/Utils/ObiFoamGenerator.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 87b741a43af4845478fd8eff354a1510
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: b7cec6e680e3a479ca03a89eccd4e052, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
50
Assets/Obi/Scripts/Common/Utils/ObiIntegration.cs
Normal file
50
Assets/Obi/Scripts/Common/Utils/ObiIntegration.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using UnityEngine;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
public static class ObiIntegration
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vector4 IntegrateLinear(Vector4 position, Vector4 velocity, float dt)
|
||||
{
|
||||
return position + velocity * dt;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vector4 DifferentiateLinear(Vector4 position, Vector4 prevPosition, float dt)
|
||||
{
|
||||
return (position - prevPosition) / dt;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Quaternion AngularVelocityToSpinQuaternion(Quaternion rotation, Vector4 angularVelocity, float dt)
|
||||
{
|
||||
var delta = new Quaternion(angularVelocity.x,
|
||||
angularVelocity.y,
|
||||
angularVelocity.z, 0);
|
||||
|
||||
var rot = delta * rotation;
|
||||
var v = new Vector4(rot.x, rot.y, rot.z, rot.w) * 0.5f * dt;
|
||||
return new Quaternion(v.x, v.y, v.z, v.w);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Quaternion IntegrateAngular(Quaternion rotation, Vector4 angularVelocity, float dt)
|
||||
{
|
||||
var spin = AngularVelocityToSpinQuaternion(rotation, angularVelocity, dt);
|
||||
rotation.x += spin.x;
|
||||
rotation.y += spin.y;
|
||||
rotation.z += spin.z;
|
||||
rotation.w += spin.w;
|
||||
return rotation.normalized;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vector4 DifferentiateAngular(Quaternion rotation, Quaternion prevRotation, float dt)
|
||||
{
|
||||
var delta = rotation * Quaternion.Inverse(prevRotation);
|
||||
return new Vector4(delta.x, delta.y, delta.z, 0) * 2.0f / dt;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4978a525b6164476d96f5d28d8b309f8
|
||||
timeCreated: 1480349422
|
||||
licenseType: Store
|
||||
guid: dbcd2b1cce6ff448ebca664dd6c55e2d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
@@ -1,508 +1,70 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[AddComponentMenu("Physics/Obi/Obi Particle Attachment", 820)]
|
||||
[RequireComponent(typeof(ObiActor))]
|
||||
[ExecuteInEditMode]
|
||||
public class ObiParticleAttachment : MonoBehaviour
|
||||
{
|
||||
public enum AttachmentType
|
||||
{
|
||||
Static,
|
||||
Dynamic
|
||||
}
|
||||
|
||||
[SerializeField] [HideInInspector] private ObiActor m_Actor;
|
||||
[SerializeField] [HideInInspector] private Transform m_Target;
|
||||
|
||||
[SerializeField] [HideInInspector] private ObiParticleGroup m_ParticleGroup;
|
||||
[SerializeField] [HideInInspector] private AttachmentType m_AttachmentType = AttachmentType.Static;
|
||||
[SerializeField] [HideInInspector] private bool m_ConstrainOrientation = false;
|
||||
[SerializeField] [HideInInspector] private float m_Compliance = 0;
|
||||
[SerializeField] [HideInInspector] [Delayed] private float m_BreakThreshold = float.PositiveInfinity;
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
[NonSerialized] private ObiPinConstraintsBatch pinBatch;
|
||||
[NonSerialized] private ObiColliderBase attachedCollider;
|
||||
[NonSerialized] private int attachedColliderHandleIndex;
|
||||
{
|
||||
[AddComponentMenu("Physics/Obi/Obi Particle Attachment", 820)]
|
||||
[NonSerialized] private int[] m_SolverIndices;
|
||||
[NonSerialized] private Vector3[] m_PositionOffsets = null;
|
||||
[NonSerialized] private Quaternion[] m_OrientationOffsets = null;
|
||||
[RequireComponent(typeof(ObiActor))]
|
||||
[ExecuteInEditMode]
|
||||
/// <summary>
|
||||
/// The actor this attachment is added to.
|
||||
/// </summary>
|
||||
public ObiActor actor
|
||||
{
|
||||
get { return m_Actor; }
|
||||
}
|
||||
public class ObiParticleAttachment : MonoBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// The target transform that the <see cref="particleGroup"/> should be attached to.
|
||||
/// </summary>
|
||||
public Transform target
|
||||
{
|
||||
get { return m_Target; }
|
||||
set
|
||||
{
|
||||
if (value != m_Target)
|
||||
{
|
||||
m_Target = value;
|
||||
Bind();
|
||||
}
|
||||
}
|
||||
}
|
||||
public enum AttachmentType
|
||||
{
|
||||
/// <summary>
|
||||
/// The particle group that should be attached to the <see cref="target"/>.
|
||||
/// </summary>
|
||||
public ObiParticleGroup particleGroup
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_ParticleGroup;
|
||||
}
|
||||
Static,
|
||||
Dynamic
|
||||
set
|
||||
{
|
||||
if (value != m_ParticleGroup)
|
||||
{
|
||||
m_ParticleGroup = value;
|
||||
Bind();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether this attachment is currently bound or not.
|
||||
/// </summary>
|
||||
public bool isBound
|
||||
{
|
||||
get { return m_Target != null && m_SolverIndices != null && m_PositionOffsets != null; }
|
||||
}
|
||||
[SerializeField] [HideInInspector] private ObiActor m_Actor;
|
||||
[SerializeField] [HideInInspector] private Transform m_Target;
|
||||
/// <summary>
|
||||
/// Type of attachment, can be either static or dynamic.
|
||||
/// </summary>
|
||||
public AttachmentType attachmentType
|
||||
{
|
||||
get { return m_AttachmentType; }
|
||||
set
|
||||
{
|
||||
if (value != m_AttachmentType)
|
||||
{
|
||||
DisableAttachment(m_AttachmentType);
|
||||
m_AttachmentType = value;
|
||||
EnableAttachment(m_AttachmentType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField] [HideInInspector] private ObiParticleGroup m_ParticleGroup;
|
||||
/// <summary>
|
||||
/// Should this attachment constraint particle orientations too?
|
||||
/// </summary>
|
||||
public bool constrainOrientation
|
||||
{
|
||||
get { return m_ConstrainOrientation; }
|
||||
set
|
||||
{
|
||||
if (value != m_ConstrainOrientation)
|
||||
{
|
||||
DisableAttachment(m_AttachmentType);
|
||||
m_ConstrainOrientation = value;
|
||||
EnableAttachment(m_AttachmentType);
|
||||
}
|
||||
}
|
||||
}
|
||||
[SerializeField] [HideInInspector] private AttachmentType m_AttachmentType = AttachmentType.Static;
|
||||
[SerializeField] [HideInInspector] private bool m_ConstrainOrientation = false;
|
||||
[SerializeField] [HideInInspector] private bool m_Projection = false;
|
||||
[SerializeField] [HideInInspector] private float m_Compliance = 0;
|
||||
/// <summary>
|
||||
/// Constraint compliance, in case this attachment is dynamic.
|
||||
/// </summary>
|
||||
/// High compliance values will increase the attachment's elasticity.
|
||||
public float compliance
|
||||
{
|
||||
get { return m_Compliance; }
|
||||
set
|
||||
{
|
||||
if (!Mathf.Approximately(value, m_Compliance))
|
||||
{
|
||||
m_Compliance = value;
|
||||
if (m_AttachmentType == AttachmentType.Dynamic && pinBatch != null)
|
||||
{
|
||||
for (int i = 0; i < m_SolverIndices.Length; ++i)
|
||||
pinBatch.stiffnesses[i * 2] = m_Compliance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Force thershold above which the attachment should break.
|
||||
/// </summary>
|
||||
/// Only affects dynamic attachments, as static attachments do not work with forces.
|
||||
public float breakThreshold
|
||||
{
|
||||
get { return m_BreakThreshold; }
|
||||
set
|
||||
{
|
||||
if (!Mathf.Approximately(value, m_BreakThreshold))
|
||||
{
|
||||
m_BreakThreshold = value;
|
||||
if (m_AttachmentType == AttachmentType.Dynamic && pinBatch != null)
|
||||
{
|
||||
for (int i = 0; i < m_SolverIndices.Length; ++i)
|
||||
pinBatch.breakThresholds[i] = m_BreakThreshold;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
m_Actor = GetComponent<ObiActor>();
|
||||
m_Actor.OnBlueprintLoaded += Actor_OnBlueprintLoaded;
|
||||
m_Actor.OnPrepareStep += Actor_OnPrepareStep;
|
||||
m_Actor.OnEndStep += Actor_OnEndStep;
|
||||
|
||||
if (m_Actor.solver != null)
|
||||
Actor_OnBlueprintLoaded(m_Actor, m_Actor.sourceBlueprint);
|
||||
|
||||
EnableAttachment(m_AttachmentType);
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
DisableAttachment(m_AttachmentType);
|
||||
|
||||
m_Actor.OnBlueprintLoaded -= Actor_OnBlueprintLoaded;
|
||||
m_Actor.OnPrepareStep -= Actor_OnPrepareStep;
|
||||
m_Actor.OnEndStep -= Actor_OnEndStep;
|
||||
}
|
||||
|
||||
private void OnValidate()
|
||||
{
|
||||
m_Actor = GetComponent<ObiActor>();
|
||||
|
||||
// private variables are serialized during script reloading, to keep their value. Must mark them explicitly as non-serialized.
|
||||
[NonSerialized] private ObiPinConstraintsBatch pinBatch;
|
||||
DisableAttachment(AttachmentType.Static);
|
||||
DisableAttachment(AttachmentType.Dynamic);
|
||||
EnableAttachment(m_AttachmentType);
|
||||
}
|
||||
[NonSerialized] private ObiColliderBase attachedCollider;
|
||||
[NonSerialized] private int attachedColliderHandleIndex;
|
||||
void Actor_OnBlueprintLoaded(ObiActor act, ObiActorBlueprint blueprint)
|
||||
{
|
||||
Bind();
|
||||
}
|
||||
|
||||
void Actor_OnPrepareStep(ObiActor act, float stepTime)
|
||||
{
|
||||
|
||||
[NonSerialized] private int[] m_SolverIndices;
|
||||
[NonSerialized] private Vector3[] m_PositionOffsets = null;
|
||||
}
|
||||
[NonSerialized] private Quaternion[] m_OrientationOffsets = null;
|
||||
private void Actor_OnEndStep(ObiActor act, float stepTime)
|
||||
{
|
||||
// dynamic attachments must be tested at the end of the step, once constraint forces have been calculated.
|
||||
|
||||
BreakDynamicAttachment(stepTime);
|
||||
}
|
||||
|
||||
private void Bind()
|
||||
{
|
||||
/// <summary>
|
||||
/// The actor this attachment is added to.
|
||||
DisableAttachment(m_AttachmentType);
|
||||
|
||||
if (m_Target != null && m_ParticleGroup != null && m_Actor.isLoaded)
|
||||
{
|
||||
Matrix4x4 bindMatrix = m_Target.worldToLocalMatrix * m_Actor.solver.transform.localToWorldMatrix;
|
||||
|
||||
m_SolverIndices = new int[m_ParticleGroup.Count];
|
||||
m_PositionOffsets = new Vector3[m_ParticleGroup.Count];
|
||||
m_OrientationOffsets = new Quaternion[m_ParticleGroup.Count];
|
||||
|
||||
for (int i = 0; i < m_ParticleGroup.Count; ++i)
|
||||
{
|
||||
int particleIndex = m_ParticleGroup.particleIndices[i];
|
||||
if (particleIndex >= 0 && particleIndex < m_Actor.solverIndices.Length)
|
||||
{
|
||||
m_SolverIndices[i] = m_Actor.solverIndices[particleIndex];
|
||||
m_PositionOffsets[i] = bindMatrix.MultiplyPoint3x4(m_Actor.solver.positions[m_SolverIndices[i]]);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("The particle group \'" + m_ParticleGroup.name + "\' references a particle that does not exist in the actor \'" + m_Actor.name + "\'.");
|
||||
m_SolverIndices = null;
|
||||
m_PositionOffsets = null;
|
||||
m_OrientationOffsets = null;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_Actor.usesOrientedParticles)
|
||||
{
|
||||
Quaternion bindOrientation = bindMatrix.rotation;
|
||||
|
||||
for (int i = 0; i < m_ParticleGroup.Count; ++i)
|
||||
{
|
||||
int particleIndex = m_ParticleGroup.particleIndices[i];
|
||||
if (particleIndex >= 0 && particleIndex < m_Actor.solverIndices.Length)
|
||||
m_OrientationOffsets[i] = bindOrientation * m_Actor.solver.orientations[m_SolverIndices[i]];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_PositionOffsets = null;
|
||||
m_OrientationOffsets = null;
|
||||
}
|
||||
|
||||
EnableAttachment(m_AttachmentType);
|
||||
}
|
||||
|
||||
|
||||
private void EnableAttachment(AttachmentType type)
|
||||
{
|
||||
|
||||
if (enabled && m_Actor.isLoaded && isBound)
|
||||
{
|
||||
var solver = m_Actor.solver;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case AttachmentType.Dynamic:
|
||||
|
||||
var pins = m_Actor.GetConstraintsByType(Oni.ConstraintType.Pin) as ObiPinConstraintsData;
|
||||
attachedCollider = m_Target.GetComponent<ObiColliderBase>();
|
||||
|
||||
if (pins != null && attachedCollider != null && pinBatch == null)
|
||||
{
|
||||
/// </summary>
|
||||
public ObiActor actor
|
||||
pinBatch = new ObiPinConstraintsBatch(pins);
|
||||
for (int i = 0; i < m_SolverIndices.Length; ++i)
|
||||
{
|
||||
pinBatch.AddConstraint(m_SolverIndices[i],
|
||||
attachedCollider,
|
||||
m_PositionOffsets[i],
|
||||
m_OrientationOffsets[i],
|
||||
m_Compliance,
|
||||
constrainOrientation ? 0 : 10000,
|
||||
m_BreakThreshold);
|
||||
|
||||
pinBatch.activeConstraintCount++;
|
||||
}
|
||||
{
|
||||
get { return m_Actor; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The target transform that the <see cref="particleGroup"/> should be attached to.
|
||||
attachedColliderHandleIndex = -1;
|
||||
if (attachedCollider.Handle != null)
|
||||
attachedColliderHandleIndex = attachedCollider.Handle.index;
|
||||
|
||||
m_Actor.SetConstraintsDirty(Oni.ConstraintType.Pin);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case AttachmentType.Static:
|
||||
|
||||
for (int i = 0; i < m_SolverIndices.Length; ++i)
|
||||
if (m_SolverIndices[i] >= 0 && m_SolverIndices[i] < solver.invMasses.count)
|
||||
solver.invMasses[m_SolverIndices[i]] = 0;
|
||||
|
||||
if (m_Actor.usesOrientedParticles && m_ConstrainOrientation)
|
||||
{
|
||||
for (int i = 0; i < m_SolverIndices.Length; ++i)
|
||||
if (m_SolverIndices[i] >= 0 && m_SolverIndices[i] < solver.invRotationalMasses.count)
|
||||
solver.invRotationalMasses[m_SolverIndices[i]] = 0;
|
||||
}
|
||||
|
||||
m_Actor.UpdateParticleProperties();
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void DisableAttachment(AttachmentType type)
|
||||
{
|
||||
if (isBound)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case AttachmentType.Dynamic:
|
||||
|
||||
if (pinBatch != null)
|
||||
{
|
||||
var pins = m_Actor.GetConstraintsByType(Oni.ConstraintType.Pin) as ObiConstraints<ObiPinConstraintsBatch>;
|
||||
if (pins != null)
|
||||
{
|
||||
pins.RemoveBatch(pinBatch);
|
||||
if (actor.isLoaded)
|
||||
m_Actor.SetConstraintsDirty(Oni.ConstraintType.Pin);
|
||||
}
|
||||
|
||||
attachedCollider = null;
|
||||
pinBatch = null;
|
||||
attachedColliderHandleIndex = -1;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case AttachmentType.Static:
|
||||
|
||||
var solver = m_Actor.solver;
|
||||
var blueprint = m_Actor.sourceBlueprint;
|
||||
|
||||
for (int i = 0; i < m_SolverIndices.Length; ++i)
|
||||
{
|
||||
int solverIndex = m_SolverIndices[i];
|
||||
if (solverIndex >= 0 && solverIndex < solver.invMasses.count)
|
||||
solver.invMasses[solverIndex] = blueprint.invMasses[i];
|
||||
}
|
||||
|
||||
if (m_Actor.usesOrientedParticles)
|
||||
{
|
||||
for (int i = 0; i < m_SolverIndices.Length; ++i)
|
||||
{
|
||||
int solverIndex = m_SolverIndices[i];
|
||||
if (solverIndex >= 0 && solverIndex < solver.invRotationalMasses.count)
|
||||
solver.invRotationalMasses[solverIndex] = blueprint.invRotationalMasses[i];
|
||||
}
|
||||
}
|
||||
|
||||
m_Actor.UpdateParticleProperties();
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateAttachment()
|
||||
{
|
||||
|
||||
if (enabled && m_Actor.isLoaded && isBound)
|
||||
{
|
||||
var solver = m_Actor.solver;
|
||||
|
||||
switch (m_AttachmentType)
|
||||
{
|
||||
case AttachmentType.Dynamic:
|
||||
/// </summary>
|
||||
public Transform target
|
||||
{
|
||||
get { return m_Target; }
|
||||
set
|
||||
attachedCollider.Handle.index != attachedColliderHandleIndex)
|
||||
{
|
||||
attachedColliderHandleIndex = attachedCollider.Handle.index;
|
||||
m_Actor.SetConstraintsDirty(Oni.ConstraintType.Pin);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case AttachmentType.Static:
|
||||
|
||||
var blueprint = m_Actor.sourceBlueprint;
|
||||
bool targetActive = m_Target.gameObject.activeInHierarchy;
|
||||
{
|
||||
if (value != m_Target)
|
||||
{
|
||||
m_Target = value;
|
||||
Bind();
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < m_SolverIndices.Length; ++i)
|
||||
{
|
||||
int solverIndex = m_SolverIndices[i];
|
||||
|
||||
if (solverIndex >= 0 && solverIndex < solver.invMasses.count)
|
||||
{
|
||||
if (targetActive)
|
||||
{
|
||||
solver.invMasses[solverIndex] = 0;
|
||||
solver.velocities[solverIndex] = Vector3.zero;
|
||||
solver.startPositions[solverIndex] = solver.positions[solverIndex] = attachmentMatrix.MultiplyPoint3x4(m_PositionOffsets[i]);
|
||||
}else
|
||||
solver.invMasses[solverIndex] = blueprint.invMasses[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (m_Actor.usesOrientedParticles && m_ConstrainOrientation)
|
||||
{
|
||||
Quaternion attachmentRotation = attachmentMatrix.rotation;
|
||||
|
||||
for (int i = 0; i < m_SolverIndices.Length; ++i)
|
||||
{
|
||||
int solverIndex = m_SolverIndices[i];
|
||||
|
||||
if (solverIndex >= 0 && solverIndex < solver.invRotationalMasses.count)
|
||||
{
|
||||
if (targetActive)
|
||||
{
|
||||
solver.invRotationalMasses[solverIndex] = 0;
|
||||
solver.angularVelocities[solverIndex] = Vector3.zero;
|
||||
solver.startOrientations[solverIndex] = solver.orientations[solverIndex] = attachmentRotation * m_OrientationOffsets[i];
|
||||
}
|
||||
else
|
||||
solver.invRotationalMasses[solverIndex] = blueprint.invRotationalMasses[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void BreakDynamicAttachment(float stepTime)
|
||||
{
|
||||
|
||||
if (enabled && m_AttachmentType == AttachmentType.Dynamic && m_Actor.isLoaded && isBound)
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
var solver = m_Actor.solver;
|
||||
|
||||
var actorConstraints = m_Actor.GetConstraintsByType(Oni.ConstraintType.Pin) as ObiConstraints<ObiPinConstraintsBatch>;
|
||||
var solverConstraints = solver.GetConstraintsByType(Oni.ConstraintType.Pin) as ObiConstraints<ObiPinConstraintsBatch>;
|
||||
|
||||
bool dirty = false;
|
||||
if (actorConstraints != null && pinBatch != null)
|
||||
{
|
||||
int pinBatchIndex = actorConstraints.batches.IndexOf(pinBatch);
|
||||
if (pinBatchIndex >= 0 && pinBatchIndex < actor.solverBatchOffsets[(int)Oni.ConstraintType.Pin].Count)
|
||||
{
|
||||
int offset = actor.solverBatchOffsets[(int)Oni.ConstraintType.Pin][pinBatchIndex];
|
||||
var solverBatch = solverConstraints.batches[pinBatchIndex];
|
||||
|
||||
float sqrTime = stepTime * stepTime;
|
||||
for (int i = 0; i < pinBatch.activeConstraintCount; i++)
|
||||
{
|
||||
/// The particle group that should be attached to the <see cref="target"/>.
|
||||
/// </summary>
|
||||
public ObiParticleGroup particleGroup
|
||||
{
|
||||
if (pinBatch.pinBodies[i] != attachedCollider.Handle)
|
||||
{
|
||||
pinBatch.pinBodies[i] = attachedCollider.Handle;
|
||||
dirty = true;
|
||||
}
|
||||
get
|
||||
{
|
||||
return m_ParticleGroup;
|
||||
if (-solverBatch.lambdas[(offset + i) * 4 + 3] / sqrTime > pinBatch.breakThresholds[i])
|
||||
{
|
||||
pinBatch.DeactivateConstraint(i);
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
set
|
||||
if (dirty)
|
||||
m_Actor.SetConstraintsDirty(Oni.ConstraintType.Pin);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
@@ -22,23 +22,24 @@ namespace Obi
|
||||
picker.OnParticlePicked.AddListener(Picker_OnParticleDragged);
|
||||
picker.OnParticleDragged.AddListener(Picker_OnParticleDragged);
|
||||
picker.OnParticleReleased.AddListener(Picker_OnParticleReleased);
|
||||
|
||||
picker.solver.OnSimulationStart += Solver_OnEndSimulation;
|
||||
}
|
||||
|
||||
void OnDisable()
|
||||
{
|
||||
picker.solver.OnSimulationStart -= Solver_OnEndSimulation;
|
||||
|
||||
picker.OnParticlePicked.RemoveListener(Picker_OnParticleDragged);
|
||||
picker.OnParticleDragged.RemoveListener(Picker_OnParticleDragged);
|
||||
picker.OnParticleReleased.RemoveListener(Picker_OnParticleReleased);
|
||||
lineRenderer.positionCount = 0;
|
||||
}
|
||||
|
||||
void FixedUpdate()
|
||||
private void Solver_OnEndSimulation(ObiSolver solver, float timeToSimulate, float substepTime)
|
||||
{
|
||||
ObiSolver solver = picker.solver;
|
||||
|
||||
if (solver != null && pickArgs != null)
|
||||
{
|
||||
|
||||
// Calculate picking position in solver space:
|
||||
Vector4 targetPosition = solver.transform.InverseTransformPoint(pickArgs.worldPosition);
|
||||
|
||||
@@ -52,7 +53,6 @@ namespace Obi
|
||||
Vector4 velocity = solver.velocities[pickArgs.particleIndex];
|
||||
solver.externalForces[pickArgs.particleIndex] = ((targetPosition - position) * springStiffness - velocity * springDamping) / invMass;
|
||||
|
||||
|
||||
if (drawSpring)
|
||||
{
|
||||
lineRenderer.positionCount = 2;
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
|
||||
[RequireComponent(typeof(ObiSolver))]
|
||||
public class ObiParticleGridDebugger : MonoBehaviour
|
||||
{
|
||||
|
||||
ObiSolver solver;
|
||||
ObiNativeAabbList cells;
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
solver = GetComponent<ObiSolver>();
|
||||
cells = new ObiNativeAabbList();
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
cells.Dispose();
|
||||
}
|
||||
|
||||
void LateUpdate ()
|
||||
{
|
||||
cells.count = solver.implementation.GetParticleGridSize();
|
||||
solver.implementation.GetParticleGrid(cells);
|
||||
}
|
||||
|
||||
void OnDrawGizmos()
|
||||
{
|
||||
|
||||
if (cells != null)
|
||||
{
|
||||
Gizmos.color = Color.yellow;
|
||||
for(int i = 0; i < cells.count; ++i)
|
||||
Gizmos.DrawWireCube(cells[i].center, cells[i].size);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -63,13 +63,13 @@ namespace Obi
|
||||
Matrix4x4 solver2World = solver.transform.localToWorldMatrix;
|
||||
|
||||
// Find the closest particle hit by the ray:
|
||||
for (int i = 0; i < solver.renderablePositions.count; ++i)
|
||||
for (int i = 0; i < solver.positions.count; ++i)
|
||||
{
|
||||
|
||||
Vector3 worldPos = solver2World.MultiplyPoint3x4(solver.renderablePositions[i]);
|
||||
Vector3 worldPos = solver2World.MultiplyPoint3x4(solver.positions[i]);
|
||||
|
||||
float mu;
|
||||
Vector3 projected = ObiUtils.ProjectPointLine(worldPos, ray.origin, ray.origin + ray.direction, out mu, false);
|
||||
Vector3 projected = ObiUtils.ProjectPointLine(ray.origin, ray.origin + ray.direction, worldPos, out mu, false);
|
||||
float distanceToRay = Vector3.SqrMagnitude(worldPos - projected);
|
||||
|
||||
// Disregard particles behind the camera:
|
||||
@@ -88,7 +88,7 @@ namespace Obi
|
||||
if (pickedParticleIndex >= 0)
|
||||
{
|
||||
|
||||
pickedParticleDepth = Camera.main.transform.InverseTransformVector(solver2World.MultiplyPoint3x4(solver.renderablePositions[pickedParticleIndex]) - Camera.main.transform.position).z;
|
||||
pickedParticleDepth = Camera.main.transform.InverseTransformVector(solver2World.MultiplyPoint3x4(solver.positions[pickedParticleIndex]) - Camera.main.transform.position).z;
|
||||
|
||||
if (OnParticlePicked != null)
|
||||
{
|
||||
|
||||
@@ -1,215 +0,0 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Obi
|
||||
{
|
||||
[DisallowMultipleComponent]
|
||||
public class ObiProfiler : MonoBehaviour
|
||||
{
|
||||
[Header("Appearance")]
|
||||
public GUISkin skin;
|
||||
public Color threadColor = Color.white;
|
||||
public Color taskColor = new Color(0.1f, 1, 0.2f);
|
||||
public Color parallelTaskColor = new Color(1,0.8f,0.2f);
|
||||
//public Color idleColor = new Color(0.7f,0.7f,0.7f);
|
||||
public Color renderTaskColor = new Color(0.2f, 0.7f, 1.0f);
|
||||
public Color defaultTaskColor = new Color(1, 0.5f, 0.2f);
|
||||
|
||||
[Header("Visualization")]
|
||||
public bool showPercentages = false;
|
||||
public int profileThrottle = 30;
|
||||
|
||||
private Oni.ProfileInfo[] info;
|
||||
private double frameStart;
|
||||
private double frameEnd;
|
||||
private int frameCounter = 0;
|
||||
private int yPos = 25;
|
||||
private bool profiling = false;
|
||||
|
||||
private float zoom = 1;
|
||||
private Vector2 scrollPosition = Vector2.zero;
|
||||
|
||||
private static ObiProfiler _instance;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (_instance != null && _instance != this)
|
||||
DestroyImmediate(this);
|
||||
else{
|
||||
_instance = this;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnDestroy(){
|
||||
#if (OBI_ONI_SUPPORTED)
|
||||
_instance = null;
|
||||
Oni.EnableProfiler(false);
|
||||
#endif
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
#if (OBI_ONI_SUPPORTED)
|
||||
if (_instance != null && _instance.profiling)
|
||||
Oni.EnableProfiler(true);
|
||||
#endif
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
#if (OBI_ONI_SUPPORTED)
|
||||
if (_instance != null)
|
||||
Oni.EnableProfiler(false);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void EnableProfiler()
|
||||
{
|
||||
#if (OBI_ONI_SUPPORTED)
|
||||
if (_instance != null)
|
||||
{
|
||||
_instance.profiling = true;
|
||||
if (_instance.isActiveAndEnabled)
|
||||
Oni.EnableProfiler(true);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void DisableProfiler()
|
||||
{
|
||||
#if (OBI_ONI_SUPPORTED)
|
||||
if (_instance != null)
|
||||
{
|
||||
_instance.profiling = false;
|
||||
Oni.EnableProfiler(false);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void BeginSample(string name, byte type)
|
||||
{
|
||||
#if (OBI_ONI_SUPPORTED)
|
||||
if (_instance != null)
|
||||
Oni.BeginSample(name, type);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void EndSample()
|
||||
{
|
||||
#if (OBI_ONI_SUPPORTED)
|
||||
if (_instance != null)
|
||||
Oni.EndSample();
|
||||
#endif
|
||||
}
|
||||
|
||||
private void UpdateProfilerInfo(){
|
||||
#if (OBI_ONI_SUPPORTED)
|
||||
frameCounter--;
|
||||
if (frameCounter <= 0)
|
||||
{
|
||||
int count = Oni.GetProfilingInfoCount();
|
||||
info = new Oni.ProfileInfo[count];
|
||||
Oni.GetProfilingInfo(info,count);
|
||||
|
||||
frameCounter = profileThrottle;
|
||||
|
||||
// Calculate frame duration:
|
||||
frameStart = double.MaxValue;
|
||||
frameEnd = double.MinValue;
|
||||
foreach (Oni.ProfileInfo i in info){
|
||||
frameStart = Math.Min(frameStart,i.start);
|
||||
frameEnd = Math.Max(frameEnd,i.end);
|
||||
}
|
||||
}
|
||||
|
||||
Oni.ClearProfiler();
|
||||
#endif
|
||||
}
|
||||
|
||||
public void OnGUI()
|
||||
{
|
||||
#if (OBI_ONI_SUPPORTED)
|
||||
if (Event.current.type == EventType.Layout)
|
||||
UpdateProfilerInfo();
|
||||
|
||||
if (info == null)
|
||||
return;
|
||||
|
||||
GUI.skin = skin;
|
||||
int toolbarHeight = 20;
|
||||
int threadHeight = 20;
|
||||
int scrollViewWidth = (int)(Screen.width / zoom);
|
||||
|
||||
double frameDuration = frameEnd - frameStart;
|
||||
|
||||
// Toolbar:
|
||||
GUI.BeginGroup(new Rect(0,0,Screen.width,toolbarHeight),"","Box");
|
||||
|
||||
GUI.Label(new Rect(5,0,50,toolbarHeight),"Zoom:");
|
||||
zoom = GUI.HorizontalSlider(new Rect(50,5,100,toolbarHeight),zoom,0.005f,1);
|
||||
GUI.Label(new Rect(Screen.width - 100,0,100,toolbarHeight),(frameDuration/1000.0f).ToString("0.###") + " ms/frame");
|
||||
|
||||
GUI.EndGroup();
|
||||
|
||||
// Timeline view:
|
||||
scrollPosition = GUI.BeginScrollView(new Rect(0, toolbarHeight, Screen.width, Screen.height-20), scrollPosition,
|
||||
new Rect(0, 0, scrollViewWidth, yPos+30)); // height depends on amount of threads.
|
||||
|
||||
GUI.color = threadColor;
|
||||
GUI.Label(new Rect(5,0,200,20),"Thread 1");
|
||||
GUI.Box(new Rect(0, 0, scrollViewWidth, 40),"","Thread");
|
||||
|
||||
yPos = 25;
|
||||
uint currentThreadId = 0;
|
||||
uint currentLevel = 0;
|
||||
foreach (Oni.ProfileInfo i in info)
|
||||
{
|
||||
uint threadId = (i.info & (uint)Oni.ProfileMask.ThreadIdMask) >> 16;
|
||||
uint level = (i.info & (uint)Oni.ProfileMask.StackLevelMask) >> 8;
|
||||
uint type = i.info & (uint)Oni.ProfileMask.TypeMask;
|
||||
|
||||
if (currentThreadId != threadId){
|
||||
yPos += threadHeight+1;
|
||||
GUI.color = threadColor;
|
||||
GUI.Label(new Rect(5,yPos+5,200,20),"Thread "+(threadId+1));
|
||||
GUI.Box(new Rect(0, yPos+5, scrollViewWidth, 40),"","Thread");
|
||||
yPos += 30;
|
||||
}else if (currentLevel != level){
|
||||
yPos += threadHeight+1;
|
||||
}
|
||||
|
||||
currentLevel = level;
|
||||
currentThreadId = threadId;
|
||||
|
||||
switch(type){
|
||||
case 0: GUI.color = taskColor; break;
|
||||
//case 1: GUI.color = idleColor; break;
|
||||
case 2: GUI.color = parallelTaskColor; break;
|
||||
case 3: GUI.color = renderTaskColor; break;
|
||||
default: GUI.color = defaultTaskColor; break;
|
||||
}
|
||||
|
||||
// task duration:
|
||||
int taskStart = (int) ((i.start - frameStart) / frameDuration * (Screen.width-10) / zoom);
|
||||
int taskEnd = (int) ((i.end - frameStart) / frameDuration * (Screen.width-10) / zoom);
|
||||
int taskDuration = taskEnd-taskStart;
|
||||
|
||||
string name;
|
||||
if (showPercentages)
|
||||
{
|
||||
double pctg = (i.end-i.start)/frameDuration*100;
|
||||
name = i.name + " ("+pctg.ToString("0.#")+"%)";
|
||||
}
|
||||
else{
|
||||
double ms = (i.end-i.start)/1000.0f;
|
||||
name = i.name + " ("+ms.ToString("0.###")+"ms)";
|
||||
}
|
||||
|
||||
GUI.Box(new Rect(taskStart, yPos, taskDuration-1, threadHeight),name,"Task");
|
||||
}
|
||||
GUI.EndScrollView();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 62e83a599724f45a4aa337d74764e572
|
||||
timeCreated: 1482252100
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- skin: {fileID: 11400000, guid: b90d3c214c99743b0865fc0e0d1f1a15, type: 2}
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 1c322d61eeb3640408ee1119729d5c21, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -34,9 +34,9 @@ namespace Obi
|
||||
[SerializeField] [HideInInspector] private ObiActor actor1 = null; /**< one of the actors used by the stitcher.*/
|
||||
[SerializeField] [HideInInspector] private ObiActor actor2 = null; /**< the second actor used by the stitcher.*/
|
||||
|
||||
[HideInInspector] public ObiNativeIntList particleIndices = new ObiNativeIntList();
|
||||
[HideInInspector] public ObiNativeFloatList stiffnesses = new ObiNativeFloatList();
|
||||
[HideInInspector] public ObiNativeFloatList lambdas = new ObiNativeFloatList();
|
||||
[HideInInspector] public ObiNativeIntList particleIndices;
|
||||
[HideInInspector] public ObiNativeFloatList stiffnesses;
|
||||
[HideInInspector] public ObiNativeFloatList lambdas;
|
||||
|
||||
//private IntPtr batch;
|
||||
private IStitchConstraintsBatchImpl m_BatchImpl;
|
||||
@@ -176,6 +176,10 @@ namespace Obi
|
||||
|
||||
inSolver = true;
|
||||
|
||||
particleIndices = new ObiNativeIntList();
|
||||
stiffnesses = new ObiNativeFloatList();
|
||||
lambdas = new ObiNativeFloatList();
|
||||
|
||||
// create a constraint batch (CreateStitchConstraints() in burst returns a singleton):
|
||||
m_BatchImpl = solver.implementation.CreateConstraintsBatch(Oni.ConstraintType.Stitch) as IStitchConstraintsBatchImpl;
|
||||
|
||||
@@ -195,6 +199,10 @@ namespace Obi
|
||||
// Oni.RemoveBatch(actor1.solver.OniSolver, batch);
|
||||
if (inSolver && m_BatchImpl != null)
|
||||
{
|
||||
lambdas.Dispose();
|
||||
particleIndices.Dispose();
|
||||
stiffnesses.Dispose();
|
||||
|
||||
solver.implementation.DestroyConstraintsBatch(m_BatchImpl as IStitchConstraintsBatchImpl);
|
||||
m_BatchImpl.Destroy();
|
||||
m_BatchImpl = null;
|
||||
@@ -227,7 +235,6 @@ namespace Obi
|
||||
m_BatchImpl.SetStitchConstraints(particleIndices, stiffnesses, lambdas, stitches.Count);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user