17-02-2020, 07:36 AM
(This post was last modified: 17-02-2020, 07:45 AM by GrimCaplan.)
I'm attempting to put together a simple script based off ObiParticlePicker that supports multiple touches. The multiple touches is working fine. The issue I'm having is that when I select a particle index, I do not seem to understand how to modify the particle's position.
I'm attempting to add a value to the y-level of a renderable position in order to increase its height. I know the axis in which I need to affect depends on the rotation and position of the cloth.
I have also done some debugging and confirmed that an index is in-fact being selected.
The reason for this is because I don't really want the effect that the particle dragger produces. When moving the finger around the screen it attempts to hold on to that particle even if I swipe to the other side of the screen whereas my desired functionality is the elevation and/or depression of particles under the finger. I know I could simply adapt the OnParticleDragged and treat all movement as a sequence of OnParticlePicked and then OnParticleReleased, but my goal is not just functioning but actually increasing my understanding of the system. I'll probably be using it a lot in the future. Directly effecting the elevation also seems less 'hackish' than hooking the two events in series.
Also if it would be helpful you can use the multi-touch for the "courtesy" code because that does actually work. I promise I'm not a terrible developer, Obi has just been hard for me to absorb.
I'm attempting to add a value to the y-level of a renderable position in order to increase its height. I know the axis in which I need to affect depends on the rotation and position of the cloth.
I have also done some debugging and confirmed that an index is in-fact being selected.
The reason for this is because I don't really want the effect that the particle dragger produces. When moving the finger around the screen it attempts to hold on to that particle even if I swipe to the other side of the screen whereas my desired functionality is the elevation and/or depression of particles under the finger. I know I could simply adapt the OnParticleDragged and treat all movement as a sequence of OnParticlePicked and then OnParticleReleased, but my goal is not just functioning but actually increasing my understanding of the system. I'll probably be using it a lot in the future. Directly effecting the elevation also seems less 'hackish' than hooking the two events in series.
Also if it would be helpful you can use the multi-touch for the "courtesy" code because that does actually work. I promise I'm not a terrible developer, Obi has just been hard for me to absorb.
Code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Obi;
public class SlimeSolverManager : MonoBehaviour
{
[SerializeField]
ObiSolver m_Solver;
[SerializeField]
float m_TouchRadius;
[SerializeField]
float m_TouchDistortionLevel = 1;
private int[] m_PickedParticleIndices;
private float pickedParticleDepth = 0;
private void OnEnable()
{
Debug.Assert(m_Solver != null, "Slime Solver Manager Missing Obi Solver Component Reference!");
}
// Update is called once per frame
void LateUpdate()
{
if (m_Solver)
{
if (Input.touchCount > 0)
m_PickedParticleIndices = new int[Input.touchCount];
foreach (Touch touch in Input.touches)
{
m_PickedParticleIndices[touch.fingerId] = -1;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
float closestMu = float.MaxValue;
float closestDistance = float.MaxValue;
// Find the closest particle hit by the ray:
for (int i = 0; i < m_Solver.renderablePositions.count; ++i)
{
float mu;
Vector3 projected = ObiUtils.ProjectPointLine
(m_Solver.renderablePositions[i], ray.origin, ray.origin + ray.direction, out mu, false);
float distanceToRay = Vector3.SqrMagnitude
((Vector3)m_Solver.renderablePositions[i] - projected);
mu = Mathf.Max(0, mu);
float radius = m_Solver.principalRadii[i][0] * m_TouchRadius;
if (distanceToRay <= radius * radius && distanceToRay < closestDistance && mu < closestMu)
{
closestMu = mu;
closestDistance = distanceToRay;
m_PickedParticleIndices[touch.fingerId] = i;
}
}
if (m_PickedParticleIndices[touch.fingerId] >= 0)
{
pickedParticleDepth = Camera.main.transform.InverseTransformVector((Vector3)m_Solver.renderablePositions
[m_PickedParticleIndices[touch.fingerId]] - Camera.main.transform.position).z;
Vector3 worldPosition = Camera.main.ScreenToWorldPoint
(new Vector3(Input.mousePosition.x, Input.mousePosition.y, pickedParticleDepth));
float x = m_Solver.renderablePositions[m_PickedParticleIndices[touch.fingerId]].x;
float y = m_Solver.renderablePositions[m_PickedParticleIndices[touch.fingerId]].y;
float z = m_Solver.renderablePositions[m_PickedParticleIndices[touch.fingerId]].z;
float w = m_Solver.renderablePositions[m_PickedParticleIndices[touch.fingerId]].w;
m_Solver.renderablePositions
[m_PickedParticleIndices[touch.fingerId]] =
new Vector4(x, y + m_TouchDistortionLevel, z, w);
}
}
}
}
}
I know the declaration of four floats is a little lazy but at this point I'm simply trying to get results. I'll opt later.