ThrowBall/Assets/Plugins/RayFire/Scripts/Classes/Rigid/RFPhysic.cs

972 lines
36 KiB
C#

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Serialization;
using Object = UnityEngine.Object;
namespace RayFire
{
[Serializable]
public class RFPhysic
{
[FormerlySerializedAs ("materialType")] public MaterialType mt;
[FormerlySerializedAs ("material")] public PhysicMaterial ma;
[FormerlySerializedAs ("massBy")] public MassType mb;
[FormerlySerializedAs ("mass")] public float ms;
[FormerlySerializedAs ("colliderType")] public RFColliderType ct;
[FormerlySerializedAs ("planarCheck")] public bool pc;
[FormerlySerializedAs ("ignoreNear")] public bool ine;
[FormerlySerializedAs ("useGravity")] public bool gr;
[FormerlySerializedAs ("solverIterations")] public int si;
public float st; // Sleeping threshold
[FormerlySerializedAs ("dampening")] public float dm;
[FormerlySerializedAs ("rigidBody")] public Rigidbody rb;
[FormerlySerializedAs ("meshCollider")] public Collider mc;
[FormerlySerializedAs ("clusterColliders")] public List<Collider> cc;
[FormerlySerializedAs ("ignoreList")] public List<int> ign;
// TODO set no serialized
public bool exclude;
public int solidity;
public bool destructible;
[NonSerialized] public bool rec;
[NonSerialized] public bool velCache;
[NonSerialized] public Vector3 velocity;
[NonSerialized] public Vector3 initScale;
[NonSerialized] public Vector3 initPosition;
[NonSerialized] public Quaternion initRotation;
[NonSerialized] public Vector3 localPosition;
/// /////////////////////////////////////////////////////////
/// Constructor
/// /////////////////////////////////////////////////////////
// Constructor
public RFPhysic()
{
InitValues();
LocalReset();
}
// Pool Reset
void InitValues()
{
mt = MaterialType.Concrete;
ma = null;
mb = MassType.MaterialDensity;
ms = 1f;
ct = RFColliderType.Mesh;
pc = true;
ine = false;
gr = true;
si = 6;
st = 0.005f;
dm = 0.7f;
solidity = 1;
ign = null;
initScale = Vector3.one;
initPosition = Vector3.zero;
initRotation = Quaternion.identity;
localPosition = Vector3.zero;
}
// Reset
public void LocalReset()
{
rec = false;
exclude = false;
velocity = Vector3.zero;
}
// Pool Reset
public void GlobalReset()
{
InitValues();
LocalReset();
cc = null;
destructible = false;
// Reset components
if (rb != null)
{
rb.velocity = Vector3.zero;
}
if (mc != null)
{
if (mc is MeshCollider collider)
{
collider.convex = false;
collider.sharedMesh = null;
collider.sharedMaterial = null;
}
}
}
// Copy from
public void CopyFrom(RFPhysic physics)
{
mt = physics.mt;
ma = physics.ma;
mb = physics.mb;
ms = physics.ms;
ct = physics.ct;
pc = physics.pc;
ine = false;
gr = physics.gr;
si = physics.si;
st = physics.st;
dm = physics.dm;
ign = null;
LocalReset();
}
// Save init transform. Birth tm for activation check and reset
public void SaveInitTransform(Transform tm)
{
initScale = tm.localScale;
initPosition = tm.position;
initRotation = tm.rotation;
localPosition = tm.localPosition;
}
// Save init transform. Birth tm for activation check and reset
public void LoadInitTransform(Transform tm)
{
tm.localScale = initScale;
tm.position = initPosition;
tm.rotation = initRotation;
}
/// /////////////////////////////////////////////////////////
/// Simulation Type
/// /////////////////////////////////////////////////////////
// Set simulation type properties
public static void SetSimulationType(Rigidbody rb, SimType simulationType, ObjectType objectType, bool useGravity, int solver, float sleep = 0.005f)
{
if (simulationType == SimType.Static)
return;
// Properties
rb.interpolation = RayfireMan.inst.interpolation;
rb.solverIterations = solver;
rb.solverVelocityIterations = solver;
rb.sleepThreshold = sleep;
// Dynamic
if (simulationType == SimType.Dynamic)
{
SetDynamic (rb, useGravity);
SetCollisionDetection (rb, objectType);
}
// Sleeping
else if (simulationType == SimType.Sleeping)
{
SetSleeping (rb, useGravity);
SetCollisionDetection (rb, objectType);
}
// Inactive
else if (simulationType == SimType.Inactive)
{
SetInactive (rb);
SetCollisionDetection (rb, objectType);
}
// Kinematic
else if (simulationType == SimType.Kinematic)
SetKinematic(rb, useGravity);
}
// Set as dynamic
static void SetDynamic(Rigidbody rb, bool useGravity)
{
rb.isKinematic = false;
rb.useGravity = useGravity;
}
// Set as sleeping
static void SetSleeping(Rigidbody rb, bool useGravity)
{
rb.isKinematic = false;
rb.useGravity = useGravity;
rb.Sleep();
}
// Set as inactive
static void SetInactive(Rigidbody rb)
{
rb.isKinematic = false;
rb.useGravity = false;
rb.drag = 100f;
rb.angularDrag = 100f;
rb.Sleep();
}
// Set as Kinematic
static void SetKinematic(Rigidbody rb, bool useGravity)
{
rb.collisionDetectionMode = CollisionDetectionMode.ContinuousSpeculative;
rb.isKinematic = true;
rb.useGravity = useGravity;
}
// Collision detection
static void SetCollisionDetection(Rigidbody rb, ObjectType objectType)
{
if (objectType == ObjectType.NestedCluster || objectType == ObjectType.ConnectedCluster)
rb.collisionDetectionMode = RayfireMan.inst.clusterCollision;
else
rb.collisionDetectionMode = RayfireMan.inst.meshCollision;
}
/// /////////////////////////////////////////////////////////
/// Density
/// /////////////////////////////////////////////////////////
// Set density. After collider defined.
public static void SetDensity(RayfireRigid scr)
{
// Default mass from inspector
float m = scr.physics.ms;
// Mass by rigid body
if (scr.physics.mb == MassType.RigidBodyComponent)
{
// Return if has rigidbody component with defined mass
if (scr.physics.rb != null)
return;
// Set to by density if has no rigid component
scr.physics.mb = MassType.MaterialDensity;
}
// Get mass by density
if (scr.physics.mb == MassType.MaterialDensity)
{
scr.physics.rb.SetDensity(RayfireMan.inst.materialPresets.Density(scr.physics.mt));
m = scr.physics.rb.mass;
}
// Check for min/max mass
m = MassLimit (m);
// Update mass in inspector
scr.physics.rb.mass = m;
}
// Set density. After collider defined.
public static void SetDensity(RFShard shard, RFPhysic physics, float density)
{
// Set mass if it was already defined before
if (shard.m > 0)
{
shard.rb.mass = shard.m;
// TODO STOP??? Check if mass need to be updated and reset it to 0
}
// Default mass from inspector
float m = physics.ms;
// Set mass by density
if (physics.mb == MassType.MaterialDensity)
{
shard.rb.SetDensity (density);
m = shard.rb.mass;
}
// Set mass by rb component. Stop
else if (physics.mb == MassType.RigidBodyComponent)
return;
// Check for min/max mass
m = MassLimit (m);
// set mass in shard properties
shard.m = m;
// Update mass in rigidbody
shard.rb.mass = m;
}
// Limit mass with min max range
static float MassLimit(float m)
{
if (RayfireMan.inst.minimumMass > 0)
if (m < RayfireMan.inst.minimumMass)
return RayfireMan.inst.minimumMass;
if (RayfireMan.inst.maximumMass > 0)
if (m > RayfireMan.inst.maximumMass)
return RayfireMan.inst.maximumMass;
return m;
}
// Set mass by mass value accordingly to parent
public static void SetMassByParent(RFPhysic target, float targetSize, float parentMass, float parentSize)
{
target.ms = parentMass * (targetSize / parentSize) * 0.7f;
target.rb.mass = target.ms;
}
/// /////////////////////////////////////////////////////////
/// Drag
/// /////////////////////////////////////////////////////////
// Set drag properties
public static void SetDrag(RayfireRigid scr)
{
if (scr.simTp != SimType.Inactive)
{
scr.physics.rb.drag = RayfireMan.inst.materialPresets.Drag(scr.physics.mt);
scr.physics.rb.angularDrag = RayfireMan.inst.materialPresets.AngularDrag(scr.physics.mt);
}
else
{
scr.physics.rb.drag = 100f;
scr.physics.rb.angularDrag = 100f;
}
}
// Set drag properties
public static void SetDrag(RFShard shard, float drag, float dragAngular)
{
if (shard.sm != SimType.Inactive)
{
shard.rb.drag = drag;
shard.rb.angularDrag = dragAngular;
}
else
{
shard.rb.drag = 100f;
shard.rb.angularDrag = 100f;
}
}
/// /////////////////////////////////////////////////////////
/// Rigid body
/// /////////////////////////////////////////////////////////
// Set velocity
public static void SetFragmentsVelocity (RayfireRigid scr)
{
// TODO different for clusters, get rigid body center of mass
// Current velocity
if (scr.mshDemol.ch.wasUsed == true && scr.mshDemol.ch.skp == false)
{
for (int i = 0; i < scr.fragments.Count; i++)
if (scr.fragments[i] != null)
scr.fragments[i].physics.rb.velocity = scr.physics.rb.GetPointVelocity (scr.fragments[i].tsf.position) * scr.physics.dm;
}
// Previous frame velocity
else
{
Vector3 baseVelocity = scr.physics.velocity * scr.physics.dm;
for (int i = 0; i < scr.fragments.Count; i++)
if (scr.fragments[i] != null)
if (scr.fragments[i].physics.rb != null && scr.fragments[i].physics.rb.isKinematic == false)
scr.fragments[i].physics.rb.velocity = baseVelocity;
}
}
/// /////////////////////////////////////////////////////////
/// Mesh Collider
/// /////////////////////////////////////////////////////////
// Set fragments collider
public static void SetFragmentCollider(RayfireRigid scr, Mesh mesh)
{
// Custom collider
scr.physics.ct = scr.mshDemol.prp.col;
// Size filter check
if (scr.mshDemol.prp.szF > 0)
if (mesh.bounds.size.magnitude < scr.mshDemol.prp.szF)
scr.physics.ct = RFColliderType.None;
// Skip collider
SetRigidCollider (scr, mesh);
}
// Set fragments collider
public static void SetRigidCollider (RayfireRigid scr, Mesh mesh = null)
{
// Skip collider
if (scr.physics.ct == RFColliderType.None)
return;
// Discard collider if just trigger
if (scr.physics.mc != null && scr.physics.mc.isTrigger == true)
scr.physics.mc = null;
// Size check
if (RayfireMan.inst != null && RayfireMan.inst.colliderSize > 0)
if (scr.mRnd.bounds.size.magnitude < RayfireMan.inst.colliderSize)
return;
// No collider. Add own
if (scr.physics.mc == null)
{
// Mesh collider
if (scr.physics.ct == RFColliderType.Mesh)
{
// Low vert check
if (scr.mFlt.sharedMesh.vertexCount <= 3)
return;
// Optional coplanar check
if (scr.physics.pc == true && scr.mFlt.sharedMesh.vertexCount < RayfireMan.coplanarVertLimit)
{
if (RFShatterAdvanced.IsCoplanar (scr.mFlt.sharedMesh, RFShatterAdvanced.planarThreshold) == true)
{
RayfireMan.Log ("RayFire Rigid: " + scr.name + " had planar low poly mesh. Object can't get Mesh Collider.", scr.gameObject);
scr.physics.ct = RFColliderType.None;
return;
}
}
// Add Mesh collider
MeshCollider mCol = scr.gameObject.AddComponent<MeshCollider>();
mCol.cookingOptions = RayfireMan.cookingOptionsStatic;
// Set mesh
if (mesh != null)
mCol.sharedMesh = mesh;
// Set convex
if (scr.simTp != SimType.Static)
mCol.convex = true;
scr.physics.mc = mCol;
}
// Box.Sphere collider
else if (scr.physics.ct == RFColliderType.Box)
scr.physics.mc = scr.gameObject.AddComponent<BoxCollider>();
else if (scr.physics.ct == RFColliderType.Sphere)
scr.physics.mc = scr.gameObject.AddComponent<SphereCollider>();
}
}
// Set fragments collider
public static void SetRigidRootCollider (RayfireRigidRoot root, RFPhysic physics, RFShard shard)
{
// Get collider
shard.col = shard.tm.GetComponent<Collider>();
// Skip collider
if (physics.ct == RFColliderType.None)
return;
// No collider. Add own
if (shard.col == null)
{
// Mesh collider
if (physics.ct == RFColliderType.Mesh)
{
// Add Mesh collider
MeshCollider col = shard.tm.gameObject.AddComponent<MeshCollider>();
col.cookingOptions = RayfireMan.cookingOptionsStatic;
col.sharedMesh = shard.mf.sharedMesh;
col.convex = true;
shard.col = col;
}
// Box / Sphere collider
else if (physics.ct == RFColliderType.Box)
shard.col = shard.tm.gameObject.AddComponent<BoxCollider>();
else if (physics.ct == RFColliderType.Sphere)
shard.col = shard.tm.gameObject.AddComponent<SphereCollider>();
// Collect applied collider to destroy at setup reset
root.collidersList.Add (shard.col);
}
}
// Set collider for mesh root fragments in editor setup
public static void SetupMeshRootColliders(RayfireRigid scr)
{
Collider col;
scr.physics.cc = new List<Collider>(scr.fragments.Count);
for (int i = 0; i < scr.fragments.Count; i++)
{
// Collect own colliders
col = scr.fragments[i].GetComponent<Collider>();
if (col != null)
scr.physics.cc.Add (col);
// Add Collider
SetRigidCollider (scr.fragments[i]);
}
}
/// /////////////////////////////////////////////////////////
/// Add Connected/Nested Cluster Colliders
/// /////////////////////////////////////////////////////////
// Create mesh colliders for every input mesh TODO input cluster to control all nest roots for correct colliders
public static void SetClusterCollidersByShards (RayfireRigid scr)
{
// Check colliders list
CollidersRemoveNull (scr);
// Already clusterized
if (scr.physics.HasClusterColliders == true)
return;
// Colliders list
if (scr.physics.cc == null)
scr.physics.cc = new List<Collider>();
// Connected/Nested colliders
if (scr.objTp == ObjectType.ConnectedCluster)
SetShardColliders (scr, scr.clsDemol.cluster);
else if (scr.objTp == ObjectType.NestedCluster)
SetDeepShardColliders (scr, scr.clsDemol.cluster);
}
// Null check and remove
static void CollidersRemoveNull(RayfireRigid scr)
{
if (scr.physics.HasClusterColliders == true)
for (int i = scr.physics.cc.Count - 1; i >= 0; i--)
if (scr.physics.cc[i] == null)
scr.physics.cc.RemoveAt (i);
}
// Check children for mesh or cluster root until all children will not be checked
static void SetShardColliders (RayfireRigid scr, RFCluster cluster)
{
// Mesh collider
if (scr.physics.ct == RFColliderType.Mesh)
{
for (int i = 0; i < cluster.shards.Count; i++)
{
// Get mesh filter and collider TODO set collider by type
MeshCollider meshCol = cluster.shards[i].tm.GetComponent<MeshCollider>();
if (meshCol == null)
{
meshCol = cluster.shards[i].mf.gameObject.AddComponent<MeshCollider>();
meshCol.sharedMesh = cluster.shards[i].mf.sharedMesh;
}
meshCol.convex = true;
// Set shard collider and collect
cluster.shards[i].col = meshCol;
scr.physics.cc.Add (meshCol);
}
}
// Box.Sphere collider
else if (scr.physics.ct == RFColliderType.Box)
{
for (int i = 0; i < cluster.shards.Count; i++)
{
// Set shard collider and collect
cluster.shards[i].col = cluster.shards[i].mf.gameObject.AddComponent<BoxCollider>();
scr.physics.cc.Add (cluster.shards[i].col);
}
}
else if (scr.physics.ct == RFColliderType.Sphere)
{
for (int i = 0; i < cluster.shards.Count; i++)
{
cluster.shards[i].col = cluster.shards[i].mf.gameObject.AddComponent<SphereCollider>();
scr.physics.cc.Add (cluster.shards[i].col);
}
}
}
// Check children for mesh or cluster root until all children will not be checked
static void SetDeepShardColliders (RayfireRigid scr, RFCluster cluster)
{
// Set shard colliders
SetShardColliders (scr, cluster);
// Set child cluster colliders
if (cluster.HasChildClusters == true)
for (int i = 0; i < cluster.childClusters.Count; i++)
SetDeepShardColliders (scr, cluster.childClusters[i]);
}
/// /////////////////////////////////////////////////////////
/// Cluster Colliders
/// /////////////////////////////////////////////////////////
// Set cluster colliders by shards
public static void CollectClusterColliders (RayfireRigid scr, RFCluster cluster)
{
// Reset original cluster colliders list
if (scr.physics.cc == null)
scr.physics.cc = new List<Collider>(cluster.shards.Count);
else
scr.physics.cc.Clear();
// Collect all shards colliders
CollectDeepColliders (scr, cluster);
}
// Check children for mesh or cluster root until all children will not be checked
static void CollectDeepColliders (RayfireRigid scr, RFCluster cluster)
{
// Collect shards colliders
for (int i = 0; i < cluster.shards.Count; i++)
scr.physics.cc.Add (cluster.shards[i].col);
// Set child cluster colliders
if (scr.objTp == ObjectType.NestedCluster)
if (cluster.HasChildClusters == true)
for (int i = 0; i < cluster.childClusters.Count; i++)
CollectDeepColliders (scr, cluster.childClusters[i]);
}
/// /////////////////////////////////////////////////////////
/// Collider material
/// /////////////////////////////////////////////////////////
// Set collider material
public static void SetColliderMaterial(RayfireRigid scr)
{
// Set physics material if not defined by user
if (scr.physics.ma == null)
scr.physics.ma = scr.physics.PhysMaterial;
// Set mesh collider material and stop
if (scr.physics.mc != null)
{
scr.physics.mc.sharedMaterial = scr.physics.ma;
return;
}
// Set cluster colliders material
if (scr.physics.HasClusterColliders == true)
for (int i = 0; i < scr.physics.cc.Count; i++)
scr.physics.cc[i].sharedMaterial = scr.physics.ma;
}
// Set shard collider material
public static void SetColliderMaterial(RFPhysic physics, RFShard shard)
{
if (shard.col != null)
shard.col.sharedMaterial = physics.ma;
}
/// /////////////////////////////////////////////////////////
/// Collider properties
/// /////////////////////////////////////////////////////////
// Set collider convex state
public static void SetColliderConvex(RayfireRigid scr)
{
if (scr.physics.mc != null)
{
// Not Mesh collider
if (scr.physics.mc is MeshCollider == false)
return;
// Turn on convex for non kinematic
MeshCollider mCol = (MeshCollider)scr.physics.mc;
if (scr.physics.rb.isKinematic == false)
mCol.convex = true;
}
}
// EDITOR clear colliders
public static void DestroyColliders(RayfireRigid scr)
{
if (scr.physics.HasClusterColliders == true)
for (int i = scr.physics.cc.Count - 1; i >= 0; i--)
if (scr.physics.cc[i] != null)
Object.DestroyImmediate (scr.physics.cc[i], true);
}
/// /////////////////////////////////////////////////////////
/// RigidRoot
/// /////////////////////////////////////////////////////////
// Set rigidbody simType, mass, drag, solver iterations
public static void SetPhysics(RayfireRigidRoot root)
{
// Set physics properties for rigidRoot shards
SetPhysics (root.rigidRootShards, root.physics);
// Set physics properties for meshRoot shards
for (int i = 0; i < root.meshRootShards.Count; i++)
SetPhysics (root.meshRootShards[i], root.meshRootShards[i].rigid.physics);
}
// Set shard Rigidbody and set physics properties. Uses for RigidRoot shards
public static void SetPhysics(List<RFShard> shards, RFPhysic physic)
{
// Set phys props
float density = RayfireMan.inst.materialPresets.Density (physic.mt);
float drag = RayfireMan.inst.materialPresets.Drag (physic.mt);
float dragAngular = RayfireMan.inst.materialPresets.AngularDrag (physic.mt);
// Add Collider and Rigid body if has no Rigid component
for (int i = 0; i < shards.Count; i++)
{
// Get rigidbody
shards[i].rb = shards[i].tm.gameObject.GetComponent<Rigidbody>();
// Set Rigid body
if (shards[i].rb == null)
shards[i].rb = shards[i].tm.gameObject.AddComponent<Rigidbody>();
// Set simulation
SetSimulationType (shards[i].rb, shards[i].sm, ObjectType.Mesh, physic.gr, physic.si, physic.st);
// Set density. After collider defined
SetDensity (shards[i], physic, density);
// Set drag properties
SetDrag (shards[i], drag, dragAngular);
}
}
// Set shard Rigidbody and set physics properties. Uses for RigidRoot -> MeshRoot shards
public static void SetPhysics(RFShard shard, RFPhysic physic)
{
// Get rigidbody
shard.rb = shard.tm.gameObject.GetComponent<Rigidbody>();
// Set Rigid body
if (shard.rb == null)
shard.rb = shard.tm.gameObject.AddComponent<Rigidbody>();
// Set simulation
SetSimulationType (shard.rb, shard.sm, ObjectType.Mesh, physic.gr, physic.si, physic.st);
// Set density. After collider defined
SetDensity (shard, physic, RayfireMan.inst.materialPresets.Density (physic.mt));
// Set drag properties
SetDrag (shard, RayfireMan.inst.materialPresets.Drag (physic.mt), RayfireMan.inst.materialPresets.AngularDrag (physic.mt));
}
/// /////////////////////////////////////////////////////////
/// Ignore colliders
/// /////////////////////////////////////////////////////////
// Pair structure
struct RFIgnorePair
{
int a;
int b;
public RFIgnorePair(int A, int B)
{
a = A;
b = B;
}
}
// Set ignore list
public static void SetIgnoreColliders(RFPhysic physics, List<RayfireRigid> rigids)
{
//float f1 = Time.realtimeSinceStartup;
// Ignore colliders enabled
if (physics.ine == true)
{
// Get ignore list if has no
if (physics.HasIgnore == false)
{
// Set bounds for Editor Setup
if (Application.isPlaying == false)
{
for (int i = 0; i < rigids.Count; i++)
{
if (rigids[i].mRnd == null)
rigids[i].mRnd = rigids[i].gameObject.GetComponent<MeshRenderer>();
if (rigids[i].mRnd != null)
rigids[i].limitations.bound = rigids[i].mRnd.bounds;
}
}
// Collect bounds to check overlap
Bounds[] bounds = new Bounds[rigids.Count];
for (int i = 0; i < rigids.Count; i++)
bounds[i] = rigids[i].limitations.bound;
// Get ignore list
physics.ign = Application.isPlaying == true
? GetIgnoreListFast (bounds)
: GetIgnoreListShort (bounds);
}
// Set physics ignore pairs. Runtime only
if (Application.isPlaying == true)
IgnoreNeibCollision (rigids, physics.ign);
}
// Nullify if runtime
if (Application.isPlaying == true)
physics.ign = null;
//Debug.Log (Time.realtimeSinceStartup - f1);
}
// Set ignore list
public static void SetIgnoreColliders(RFPhysic physics, List<RFShard> shards)
{
// Ignore colliders enabled
if (physics.ine == true)
{
// Get ignore list if has no
if (physics.HasIgnore == false)
SetIgnoreListShards (physics, shards);
// Set physics ignore pairs
if (Application.isPlaying == true)
IgnoreNeibCollision (shards, physics.ign);
}
// Nullify if runtime
if (Application.isPlaying == true)
physics.ign = null;
}
// Ignore collision for overlapped shards
public static void SetIgnoreListShards(RFPhysic physics, List<RFShard> shards)
{
// Collect bounds to check overlap
Bounds[] bounds = new Bounds[shards.Count];
for (int i = 0; i < shards.Count; i++)
bounds[i] = shards[i].bnd;
// Get ignore list
physics.ign = Application.isPlaying == true
? GetIgnoreListFast (bounds)
: GetIgnoreListShort (bounds);
}
// Ignore collision for overlapped shards
public static List<int> GetIgnoreListFast(Bounds[] bounds)
{
// Get prune list
List<int> pruneList = new List<int>();
for (int s = 0; s < bounds.Length; s++)
{
for (int n = 0; n < bounds.Length; n++)
{
if (s != n)
{
// Check bound intersection
if (bounds[s].Intersects (bounds[n]) == true)
{
pruneList.Add (s);
pruneList.Add (n);
}
}
}
}
return pruneList;
}
// Ignore collision for overlapped shards
public static List<int> GetIgnoreListShort(Bounds[] bounds)
{
RFIgnorePair pair;
HashSet<RFIgnorePair> ignorePairsHash = new HashSet<RFIgnorePair>();
// Get prune list
List<int> pruneList = new List<int>();
for (int s = 0; s < bounds.Length; s++)
{
for (int n = 0; n < bounds.Length; n++)
{
if (s != n)
{
// Check bound intersection
if (bounds[s].Intersects (bounds[n]) == true)
{
// Create pair
pair = new RFIgnorePair (s, n);
// Has no such pair yet
if (ignorePairsHash.Contains (pair) == false)
{
pruneList.Add (s);
pruneList.Add (n);
ignorePairsHash.Add (pair);
ignorePairsHash.Add (new RFIgnorePair (n, s));
}
}
}
}
}
return pruneList;
}
// Ignore collision for overlapped shards
public static void IgnoreNeibCollision(List<RayfireRigid> rigids, List<int> pr)
{
for (int s = 0; s < pr.Count / 2; s++)
if (rigids[pr[s * 2 + 0]].physics.mc != null && rigids[pr[s * 2 + 1]].physics.mc != null)
Physics.IgnoreCollision (rigids[pr[s * 2 + 0]].physics.mc, rigids[pr[s * 2 + 1]].physics.mc, true);
}
// Ignore collision for overlapped shards
public static void IgnoreNeibCollision(List<RFShard> shards, List<int> pr)
{
for (int s = 0; s < pr.Count / 2; s++)
if (shards[pr[s * 2 + 0]].col != null && shards[pr[s * 2 + 1]].col != null)
Physics.IgnoreCollision (shards[pr[s * 2 + 0]].col, shards[pr[s * 2 + 1]].col, true);
}
/// /////////////////////////////////////////////////////////
/// Getters
/// /////////////////////////////////////////////////////////
public bool HasIgnore { get { return ign != null && ign.Count > 0; } }
public bool Destructible { get { return RayfireMan.inst.materialPresets.Destructible(mt); } }
public int Solidity { get { return RayfireMan.inst.materialPresets.Solidity(mt); } }
// Get Destructible state
public bool HasClusterColliders
{
get
{
if (cc != null && cc.Count > 0)
return true;
return false;
}
}
// Get physic material
public PhysicMaterial PhysMaterial
{
get
{
// Return predefine material
if (ma != null)
return ma;
// Crete new material
return RFMaterialPresets.PhysicMaterial(mt);
}
}
// Bake getter properties
public static void BakeProperties(RFPhysic physics)
{
// Set material solidity and destructible
physics.solidity = physics.Solidity;
physics.destructible = physics.Destructible;
// Set physics material if not defined by user
if (physics.ma == null)
physics.ma = physics.PhysMaterial;
}
}
}