09-10-2018, 05:46 PM
(09-10-2018, 02:28 PM)josemendez Wrote: Yep. Instead of using a spring force to move the particle around (which is what the dragger currently does), modify it to set the particle position directly using Oni.SetParticlePositions(). See:
http://obi.virtualmethodstudio.com/tutor...icles.html
Unfortunately it still doesn't change it's behaviour. The cloth point only drags itself as shown here. I want the pickedParticle to be dragged fully with mouse pointer.
The edge particles of this mesh are fixed.
These are my current scripts -
ObiClothPicker.cs -
Code:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Obi{
public class ObiClothPicker : MonoBehaviour {
public class ParticlePickEventArgs : EventArgs
{
public int particleIndex;
public Vector3 worldPosition;
public ParticlePickEventArgs(int particleIndex, Vector3 worldPosition){
this.particleIndex = particleIndex;
this.worldPosition = worldPosition;
}
}
GameObject FingerTrailSphere;
public float FingerRadius = 20;
public event System.EventHandler<ParticlePickEventArgs> OnParticlePicked;
public event System.EventHandler<ParticlePickEventArgs> OnParticleHeld;
public event System.EventHandler<ParticlePickEventArgs> OnParticleDragged;
public event System.EventHandler<ParticlePickEventArgs> OnParticleReleased;
private MeshCollider meshCollider;
private ObiClothBase cloth;
private Mesh currentCollisionMesh;
private Vector3 lastMousePos = Vector3.zero;
private int pickedParticleIndex = -1;
private float pickedParticleDepth = 0;
[HideInInspector]
public float durationsTouch;
Vector3 tpos;
public ObiClothBase Cloth{
get{return cloth;}
}
ObiActor actor;
void Awake(){
cloth = GetComponent<ObiClothBase>();
lastMousePos = Input.mousePosition;
actor = GetComponent<ObiActor>();
FingerTrailSphere = GameObject.Find("FingerFollowTrailObject");
}
void OnEnable(){
// special case for skinned cloth, the collider must be added to the skeleton's root bone:
if (cloth is ObiCloth && ((ObiCloth)cloth).IsSkinned){
SkinnedMeshRenderer sk = cloth.GetComponent<SkinnedMeshRenderer>();
if (sk != null && sk.rootBone != null){
meshCollider = sk.rootBone.gameObject.AddComponent<MeshCollider>();
}
}
// regular cloth:
else{
meshCollider = gameObject.AddComponent<MeshCollider>();
}
// in case we were able to create the mesh collider, set it up:
if (meshCollider != null){
meshCollider.enabled = false;
meshCollider.hideFlags = HideFlags.HideAndDontSave;
}
if (cloth != null)
cloth.Solver.OnFrameBegin += Cloth_Solver_OnFrameBegin;
}
void OnDisable(){
// destroy the managed mesh collider:
GameObject.Destroy(meshCollider);
if (cloth != null)
cloth.Solver.OnFrameBegin -= Cloth_Solver_OnFrameBegin;
}
void Cloth_Solver_OnFrameBegin (object sender, EventArgs e)
{
if (meshCollider == null)
return;
// Click:
/*Touch myTouch = Input.GetTouch(0);
Touch[] myTouches = Input.touches;
for (int i = 0; i < Input.touchCount; i++)
{
Debug.Log(Input.touchCount);
}*/
if (Input.GetMouseButtonDown(0))
{
meshCollider.enabled = true;
GameObject.Destroy(currentCollisionMesh);
currentCollisionMesh = GameObject.Instantiate(cloth.clothMesh);
meshCollider.sharedMesh = currentCollisionMesh;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
tpos = ray.GetPoint(10);
FingerTrailSphere.transform.position = tpos;
RaycastHit hitInfo;
if (meshCollider.Raycast(ray,out hitInfo,100))
{
int[] tris = currentCollisionMesh.triangles;
Vector3[] vertices = currentCollisionMesh.vertices;
// find closest vertex in the triangle we just hit:
int closestVertex = -1;
float minDistance = float.MaxValue;
for (int i = 0; i < 3; ++i)
{
int vertex = tris[hitInfo.triangleIndex*3+i];
float distance = (vertices[vertex] - hitInfo.point).sqrMagnitude;
if (distance < minDistance){
minDistance = distance;
closestVertex = vertex;
}
}
// get particle index:
if (closestVertex >= 0 && closestVertex < cloth.topology.visualMap.Length)
{
pickedParticleIndex = cloth.topology.visualMap[closestVertex];
pickedParticleDepth = Mathf.Abs((cloth.transform.TransformPoint(vertices[closestVertex]) - Camera.main.transform.position).z);
if (OnParticlePicked != null)
{
Vector3 worldPosition = Camera.main.ScreenToWorldPoint (new Vector3 (Input.mousePosition.x, Input.mousePosition.y, pickedParticleDepth));
OnParticlePicked(this,new ParticlePickEventArgs(pickedParticleIndex, worldPosition));
}
}
}
meshCollider.enabled = false;
}
if (Input.GetMouseButton(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
tpos = ray.GetPoint(0);
}
else if (pickedParticleIndex >= 0)
{
// 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));
Vector3 worldPosition = tpos;
OnParticleDragged(this,new ParticlePickEventArgs(pickedParticleIndex,worldPosition));
}
else if (OnParticleHeld != null)
{
Vector3 worldPosition = tpos;
//Vector3 worldPosition = Camera.main.ScreenToWorldPoint (new Vector3 (Input.mousePosition.x, Input.mousePosition.y, pickedParticleDepth));
OnParticleHeld(this,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(this,new ParticlePickEventArgs(pickedParticleIndex,worldPosition));
}
pickedParticleIndex = -1;
}
}
lastMousePos = Input.mousePosition;
}
}
}
ObiClothDragger.cs -
Code:
using System;
using UnityEngine;
using System.Collections;
namespace Obi
{
[RequireComponent(typeof(ObiClothPicker))]
public class ObiClothDragger : MonoBehaviour
{
public float springStiffness = 50;
public float springDamping = 1;
private ObiClothPicker picker;
private ObiClothPicker.ParticlePickEventArgs pickArgs;
[HideInInspector]
public enum TypeOfSlime { Liquid, Sticky, VerySticky};
public TypeOfSlime SlimeTypeSelector;
public float FingerRadius = 50;
public float FingerDepthDurationFactor = 1.5f;
Vector3 tpos;
void OnEnable()
{
picker = GetComponent<ObiClothPicker>();
picker.OnParticlePicked += Picker_OnParticlePicked;
picker.OnParticleDragged += Picker_OnParticleDragged;
picker.OnParticleReleased += Picker_OnParticleReleased;
}
void OnDisable()
{
picker.OnParticlePicked -= Picker_OnParticlePicked;
picker.OnParticleDragged -= Picker_OnParticleDragged;
picker.OnParticleReleased -= Picker_OnParticleReleased;
}
void FixedUpdate ()
{
if (pickArgs != null){
ObiSolver solver = picker.Cloth.Solver;
// Calculate picking position in solver space:
Vector3 targetPosition = pickArgs.worldPosition;
if (solver.simulateInLocalSpace)
targetPosition = solver.transform.InverseTransformPoint(targetPosition);
// Get particle position and velocity:
Vector4[] positions = new Vector4[1];
Vector4[] velocities = new Vector4[1];
int solverIndex = picker.Cloth.particleIndices[pickArgs.particleIndex];
Oni.GetParticlePositions(solver.OniSolver,positions,1,solverIndex);
Oni.GetParticleVelocities(solver.OniSolver,velocities,1,solverIndex);
// Calculate effective inverse mass:
float invMass = picker.Cloth.invMasses[pickArgs.particleIndex] * picker.Cloth.areaContribution[pickArgs.particleIndex];
if (invMass > 0)
{
// Calculate and apply spring force:
//Vector4 force = (((new Vector4(targetPosition[0],-targetPosition[1],targetPosition[2],0) - positions[0]) * springStiffness - velocities[0] * springDamping) / (invMass)) * (picker.durationsTouch/FingerDepthDurationFactor);
//Oni.AddParticleExternalForce(picker.Cloth.Solver.OniSolver,ref force,new int[]{solverIndex},1);
Oni.SetParticlePositions(picker.Cloth.Solver.OniSolver, new Vector4[] { tpos }, 1, pickArgs.particleIndex);
}
}
}
void Picker_OnParticlePicked(object sender, ObiClothPicker.ParticlePickEventArgs e)
{
pickArgs = e;
}
void Picker_OnParticleDragged (object sender, ObiClothPicker.ParticlePickEventArgs e)
{
pickArgs = e;
}
void Update()
{
if (Input.GetMouseButton(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
tpos = ray.GetPoint(10);
if (picker.durationsTouch <= 4)
{
picker.durationsTouch += Time.deltaTime;
}
}
}
void Picker_OnParticleReleased (object sender, ObiClothPicker.ParticlePickEventArgs e)
{
picker.durationsTouch = 0;
Oni.SetParticleVelocities(picker.Cloth.Solver.OniSolver, new Vector4[] { new Vector4(0, 12, 0, 0) }, 1, picker.Cloth.particleIndices[e.particleIndex]);
if (SlimeTypeSelector == TypeOfSlime.Liquid)
{
pickArgs = null;
}
else if (SlimeTypeSelector == TypeOfSlime.Sticky)
{
Oni.SetParticleInverseMasses(picker.Cloth.Solver.OniSolver, new float[] { 0.5f }, 1, picker.Cloth.particleIndices[e.particleIndex]);
//Oni.SetParticleVelocities(picker.Cloth.Solver.OniSolver, new Vector4[] { new Vector4(1,2,1,0) }, 2, picker.Cloth.particleIndices[e.particleIndex]);
picker.Cloth.Solver.RelinquishRenderablePositions();
}
else if (SlimeTypeSelector == TypeOfSlime.VerySticky)
{
Oni.SetParticleInverseMasses(picker.Cloth.Solver.OniSolver, new float[] { 0 }, 1, picker.Cloth.particleIndices[e.particleIndex]);
Oni.SetParticleVelocities(picker.Cloth.Solver.OniSolver, new Vector4[] { Vector4.zero }, 1, picker.Cloth.particleIndices[e.particleIndex]);
picker.Cloth.Solver.RelinquishRenderablePositions();
}
}
}
}