Please, I need help with this code. It’s just collide with quad and I don’t know what to do
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SPHManagerSingleThread : MonoBehaviour
{
private struct SPHParticle
{
public Vector3 position;
public Vector3 velocity;
public Vector3 forcePhysic;
public Vector3 forceHeading;
public float density;
public float pressure;
public int parameterID;
public GameObject go;
public void Init(Vector3 _position, int _parameterID, GameObject _go)
{
position = _position;
parameterID = _parameterID;
go = _go;
velocity = Vector3.zero;
forcePhysic = Vector3.zero;
forceHeading = Vector3.zero;
density = 0.0f;
pressure = 0.0f;
}
}
[System.Serializable]
private struct SPHParameters
{
#pragma warning disable 0649 // This line removes the warning saying that the variable is never assigned to. You can't assign a variable in a struct...
public float particleRadius;
public float smoothingRadius;
public float smoothingRadiusSq;
public float restDensity;
public float gravityMult;
public float particleMass;
public float particleViscosity;
public float particleDrag;
#pragma warning restore 0649
}
private struct SPHCollider
{
public Vector3 position;
public Vector3 right;
public Vector3 up;
public Vector2 scale;
public void Init(Transform _transform)
{
position = _transform.position;
right = _transform.right;
up = _transform.up;
scale = new Vector2(_transform.lossyScale.x / 2f, _transform.lossyScale.y / 2f);
}
}
// Consts
private static Vector3 GRAVITY = new Vector3(0.0f, -9.81f, 0.0f);
private const float GAS_CONST = 2000.0f;
private const float DT = 0.0008f;
private const float BOUND_DAMPING = -0.5f;
// Properties
[Header("Import")]
[SerializeField] private GameObject character0Prefab = null;
[Header("Parameters")]
[SerializeField] private int parameterID = 0;
[SerializeField] private SPHParameters[] parameters = null;
[Header("Properties")]
[SerializeField] private int amount = 250;
[SerializeField] private int rowSize = 16;
// Data
private SPHParticle[] particles;
private void Start()
{
InitSPH();
}
private void Update()
{
ComputeDensityPressure();
ComputeForces();
Integrate();
ComputeColliders();
ApplyPosition();
}
private void InitSPH()
{
particles = new SPHParticle[amount];
for (int i = 0; i < amount; i++)
{
float jitter = (Random.value * 2f - 1f) * parameters[parameterID].particleRadius * 0.1f;
float x = (i % rowSize) + Random.Range(-0.1f, 0.1f);
float y = 2 + (float)((i / rowSize) / rowSize) * 1.1f;
float z = ((i / rowSize) % rowSize) + Random.Range(-0.1f, 0.1f);
GameObject go = Instantiate(character0Prefab);
go.transform.localScale = Vector3.one * parameters[parameterID].particleRadius;
go.transform.position = new Vector3(x + jitter, y, z + jitter);
go.name = "char" + i.ToString();
particles.Init(new Vector3(x, y, z), parameterID, go);
}
}
private static bool Intersect(SPHCollider collider, Vector3 position, float radius, out Vector3 penetrationNormal, out Vector3 penetrationPosition, out float penetrationLength)
{
Vector3 colliderProjection = collider.position - position;
penetrationNormal = Vector3.Cross(collider.right, collider.up);
penetrationLength = Mathf.Abs(Vector3.Dot(colliderProjection, penetrationNormal)) - (radius / 2.0f);
penetrationPosition = collider.position - colliderProjection;
return penetrationLength < 0.0f
&& Mathf.Abs(Vector3.Dot(colliderProjection, collider.right)) < collider.scale.x
&& Mathf.Abs(Vector3.Dot(colliderProjection, collider.up)) < collider.scale.y;
}
private static Vector3 DampVelocity(SPHCollider collider, Vector3 velocity, Vector3 penetrationNormal, float drag)
{
Vector3 newVelocity = Vector3.Dot(velocity, penetrationNormal) * penetrationNormal * BOUND_DAMPING
+ Vector3.Dot(velocity, collider.right) * collider.right * drag
+ Vector3.Dot(velocity, collider.up) * collider.up * drag;
newVelocity = Vector3.Dot(newVelocity, Vector3.forward) * Vector3.forward
+ Vector3.Dot(newVelocity, Vector3.right) * Vector3.right
+ Vector3.Dot(newVelocity, Vector3.up) * Vector3.up;
return newVelocity;
}
private void ComputeColliders()
{
// Get colliders
GameObject[] collidersGO = GameObject.FindGameObjectsWithTag("SPHCollider");
SPHCollider[] colliders = new SPHCollider[collidersGO.Length];
for (int i = 0; i < colliders.Length; i++)
{
colliders.Init(collidersGO.transform);
}
for (int i = 0; i < particles.Length; i++)
{
for (int j = 0; j < colliders.Length; j++)
{
// Check collision
Vector3 penetrationNormal;
Vector3 penetrationPosition;
float penetrationLength;
if (Intersect(colliders[j], particles.position, parameters[particles.parameterID].particleRadius, out penetrationNormal, out penetrationPosition, out penetrationLength))
{
particles.velocity = DampVelocity(colliders[j], particles.velocity, penetrationNormal, 1.0f - parameters[particles.parameterID].particleDrag);
particles.position = penetrationPosition - penetrationNormal * Mathf.Abs(penetrationLength);
}
}
}
}
private void Integrate()
{
for (int i = 0; i < particles.Length; i++)
{
particles.velocity += DT * (particles.forcePhysic) / particles.density;
particles.position += DT * (particles.velocity );
}
}
private void ComputeDensityPressure()
{
for (int i = 0; i < particles.Length; i++)
{
particles.density = 0.0f;
for (int j = 0; j < particles.Length; j++)
{
Vector3 rij = particles[j].position - particles.position;
float r2 = rij.sqrMagnitude;
if (r2 < parameters[particles.parameterID].smoothingRadiusSq)
{
particles.density += parameters[particles.parameterID].particleMass * (315.0f / (64.0f * Mathf.PI * Mathf.Pow(parameters[particles.parameterID].smoothingRadius, 9.0f))) * Mathf.Pow(parameters[particles[i].parameterID].smoothingRadiusSq - r2, 3.0f);
}
}
particles[i].pressure = GAS_CONST * (particles[i].density - parameters[particles[i].parameterID].restDensity);
}
}
private void ComputeForces()
{
for (int i = 0; i < particles.Length; i++)
{
Vector3 forcePressure = Vector3.zero;
Vector3 forceViscosity = Vector3.zero;
// Physics
for (int j = 0; j < particles.Length; j++)
{
if (i == j) continue;
Vector3 rij = particles[j].position - particles[i].position;
float r2 = rij.sqrMagnitude;
float r = Mathf.Sqrt(r2);
if (r < parameters[particles[i].parameterID].smoothingRadius)
{
forcePressure += -rij.normalized * parameters[particles[i].parameterID].particleMass * (particles[i].pressure + particles[j].pressure) / (2.0f * particles[j].density) * (-45.0f / (Mathf.PI * Mathf.Pow(parameters[particles[i].parameterID].smoothingRadius, 6.0f))) * Mathf.Pow(parameters[particles[i].parameterID].smoothingRadius - r, 2.0f);
forceViscosity += parameters[particles[i].parameterID].particleViscosity * parameters[particles[i].parameterID].particleMass * (particles[j].velocity - particles[i].velocity) / particles[j].density * (45.0f / (Mathf.PI * Mathf.Pow(parameters[particles[i].parameterID].smoothingRadius, 6.0f))) * (parameters[particles[i].parameterID].smoothingRadius - r);
}
}
Vector3 forceGravity = GRAVITY * particles[i].density * parameters[particles[i].parameterID].gravityMult;
// Apply
particles[i].forcePhysic = forcePressure + forceViscosity + forceGravity;
}
}
private void ApplyPosition()
{
for (int i = 0; i < particles.Length; i++)
{
particles[i].go.transform.position = particles[i].position;
}
}
}
This code was implemented with quad colliders, how can I implement box collider or mesh collider?? I need to take datas of mesh like artery for example.
6352188–706248–SPHManager.cs (9.14 KB)