Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Help  How to add particles to existing cloth object
#5
(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();
           }
       }

    }
}
Reply


Messages In This Thread
RE: How to add particles to existing cloth object - by arrnav96 - 09-10-2018, 05:46 PM