ObiParticlePicker for any object [might be helpful for everyone] - jbvobling - 27-01-2020
Hello everyone, can anyone help me convert a custom interaction?
I'm experimenting to use a cube as an interaction other than the Input.mousePosition of ObiParticlePicker.cs, but i'm having trouble customizing it.
My idea is, by using a boolean variable as a trigger for grabbing the closest particle of the obi cloth if true and release the grabbing if false, a cube must have its own forward raycasting, than using the input.mousePosition.
I'm currently experimenting how for 3-days, but it seems I'm stuck.
These line of code are the one I am currently having trouble with.
Code: // Drag:
Vector3 mouseDelta = Input.mousePosition - lastMousePos;
if (mouseDelta.magnitude > 0.01f && OnParticleDragged != null)
{
Vector3 worldPosition = Camera.main.ScreenToWorldPoint (new Vector3 (Input.mousePosition.x, Input.mousePosition.y, pickedParticleDepth));
OnParticleDragged.Invoke(new ParticlePickEventArgs(pickedParticleIndex,worldPosition));
}
else if (OnParticleHeld != null)
{
Vector3 worldPosition = Camera.main.ScreenToWorldPoint (new Vector3 (Input.mousePosition.x, Input.mousePosition.y, pickedParticleDepth));
OnParticleHeld.Invoke(new ParticlePickEventArgs(pickedParticleIndex,worldPosition));
}
// Release:
if (Input.GetMouseButtonUp(0))
{
if (OnParticleReleased != null)
{
Vector3 worldPosition = Camera.main.ScreenToWorldPoint (new Vector3 (Input.mousePosition.x, Input.mousePosition.y, pickedParticleDepth));
OnParticleReleased.Invoke(new ParticlePickEventArgs(pickedParticleIndex,worldPosition));
}
pickedParticleIndex = -1;
}
RE: ObiParticlePicker for any object [might be helpful for everyone] - jbvobling - 30-01-2020
Update: this is a sample and it somehow works, but not precise yet as there is a spring thing happening. It would be great if we can make the springing thing disappear.
Code: void FixedUpdate()
{
Ray ray = new Ray(this.transform.position, transform.forward);
if (triggerOnce)
{
Debug.Log("Tigger once");
triggerOnce = false;
RenderOnce();
}
else if (pickedParticleIndex >= 0)
{
float invmass = solver.invMasses[pickedParticleIndex];
Vector4 position = solver.transform.TransformPoint(solver.positions[pickedParticleIndex]);
Vector4 velocity = solver.velocities[pickedParticleIndex];
Vector4 targetposition = this.transform.position;
//// calculate picking position in solver space:
solver.externalForces[pickedParticleIndex] = ((targetposition - position) * springStiffness - velocity * springDamping) / invmass;
}
}
void RenderOnce()
{
Ray ray = new Ray(transform.position, transform.forward);
float closestMu = float.MaxValue;
float closestDistance = float.MaxValue;
for (int i = 0; i < solver.renderablePositions.count; ++i)
{
float mu;
Vector3 projected = ObiUtils.ProjectPointLine(solver.transform.TransformPoint(solver.renderablePositions[i]), ray.origin, ray.origin + ray.direction, out mu, false);
float distanceToRay = Vector3.SqrMagnitude((Vector3)solver.transform.TransformPoint(solver.renderablePositions[i]) - projected);
mu = Mathf.Max(0, mu);
float radius = solver.principalRadii[i][0] * radiusScale;
if (distanceToRay <= radius * radius && distanceToRay < closestDistance && mu < closestMu)
{
closestMu = mu;
closestDistance = distanceToRay;
pickedParticleIndex = i;
}
}
}
RE: ObiParticlePicker for any object [might be helpful for everyone] - josemendez - 30-01-2020
(30-01-2020, 03:36 AM)jbvobling Wrote: Update: this is a sample and it somehow works, but not precise yet as there is a spring thing happening. It would be great if we can make the springing thing disappear.
Code: void FixedUpdate()
{
Ray ray = new Ray(this.transform.position, transform.forward);
if (triggerOnce)
{
Debug.Log("Tigger once");
triggerOnce = false;
RenderOnce();
}
else if (pickedParticleIndex >= 0)
{
float invmass = solver.invMasses[pickedParticleIndex];
Vector4 position = solver.transform.TransformPoint(solver.positions[pickedParticleIndex]);
Vector4 velocity = solver.velocities[pickedParticleIndex];
Vector4 targetposition = this.transform.position;
//// calculate picking position in solver space:
solver.externalForces[pickedParticleIndex] = ((targetposition - position) * springStiffness - velocity * springDamping) / invmass;
}
}
void RenderOnce()
{
Ray ray = new Ray(transform.position, transform.forward);
float closestMu = float.MaxValue;
float closestDistance = float.MaxValue;
for (int i = 0; i < solver.renderablePositions.count; ++i)
{
float mu;
Vector3 projected = ObiUtils.ProjectPointLine(solver.transform.TransformPoint(solver.renderablePositions[i]), ray.origin, ray.origin + ray.direction, out mu, false);
float distanceToRay = Vector3.SqrMagnitude((Vector3)solver.transform.TransformPoint(solver.renderablePositions[i]) - projected);
mu = Mathf.Max(0, mu);
float radius = solver.principalRadii[i][0] * radiusScale;
if (distanceToRay <= radius * radius && distanceToRay < closestDistance && mu < closestMu)
{
closestMu = mu;
closestDistance = distanceToRay;
pickedParticleIndex = i;
}
}
}
Hi,
Instead of calculating a spring force, fix the particle (by setting its inverse mass and velocity to zero) and set the particle position directly. That will completely get rid of the "spring thing":
Quote:solver.velocities[pickedParticleIndex] = Vector4.zero;
solver.invMasses[pickedParticleIndex] = 0;
solver.positions[pickedParticleIndex] = solver.transform.InverseTransformPoint(this.transform.position);
Note that you should revert the inverse mass to whatever it was when you want the particle to start behaving normally again.
RE: ObiParticlePicker for any object [might be helpful for everyone] - jbvobling - 03-02-2020
(30-01-2020, 08:24 AM)josemendez Wrote: Hi,
Instead of calculating a spring force, fix the particle (by setting its inverse mass and velocity to zero) and set the particle position directly. That will completely get rid of the "spring thing":
Note that you should revert the inverse mass to whatever it was when you want the particle to start behaving normally again.
Thank you, it works.
|