void ApplyImpulses(FlexContainer.ParticleData _particleData) { if (m_currentAsset && m_instanceHandle) { FlexExt.Instance instance = m_instanceHandle.instance; int[] indices = new int[instance.numParticles]; FlexUtils.FastCopy(instance.particleIndices, indices); foreach (var info in m_impulses) { if (info.impulse.sqrMagnitude < float.Epsilon) { continue; } float mass = 0; foreach (var index in indices) { if (info.particle == -1 || info.particle == index) { Vector4 particle = _particleData.GetParticle(index); mass += 1.0f / particle.w; } } if (mass < float.Epsilon) { continue; } Vector3 velocityChange = info.impulse / mass; foreach (var index in indices) { _particleData.SetVelocity(index, _particleData.GetVelocity(index) + velocityChange); } } } }
protected override void CreateInstance() { base.CreateInstance(); if (handle) { FlexExt.Instance instance = handle.instance; if (instance.numParticles > 0) { if (m_asset.fixedParticles.Length == 0) { int[] refPoints = new int[3] { 0, 1, 2 }; // @@@ Vector4[] particles = m_asset.particles; //FlexUtils.ClothRefPoints(ref particles[0], particles.Length, ref refPoints[0]); // @@@ !!! Too slow m_referencePoints = new int[] { indices[refPoints[0]], indices[refPoints[1]], indices[refPoints[2]] }; Vector3 p0 = particles[refPoints[0]], p1 = particles[refPoints[1]], p2 = particles[refPoints[2]]; m_localPosition = (p0 + p1 + p2) / 3; Vector3 clothZ = Vector3.Cross(p1 - p0, p2 - p0).normalized; Vector3 clothY = Vector3.Cross(clothZ, p1 - p0).normalized; m_localRotation = Quaternion.LookRotation(clothZ, clothY); } } } }
void MoveFixedParticles(FlexContainer.ParticleData _particleData) { if (Application.isPlaying) { if (m_currentAsset && m_currentAsset.fixedParticles.Length > 0 && m_instanceHandle) { FlexExt.Instance instance = m_instanceHandle.instance; Vector4[] particles = m_currentAsset.particles; foreach (var index in m_currentAsset.fixedParticles) { if (index < particles.Length) { Vector4 particle = transform.TransformPoint(particles[index]); particle.w = 0.0f; _particleData.SetParticle(indices[index], particle); } } } } else { if (m_currentAsset && m_instanceHandle) { FlexExt.Instance instance = m_instanceHandle.instance; Vector4[] particles = m_currentAsset.particles; for (int i = 0; i < particles.Length; ++i) { Vector4 particle = transform.TransformPoint(particles[i]); particle.w = _particleData.GetParticle(indices[i]).w; _particleData.SetParticle(indices[i], particle); } } } }
void TeleportParticles(FlexContainer.ParticleData _particleData) { Matrix4x4 offset = Matrix4x4.TRS(m_teleportPosition, Quaternion.identity, Vector3.one) * Matrix4x4.TRS(Vector3.zero, m_teleportRotation, Vector3.one) * Matrix4x4.TRS(Vector3.zero, Quaternion.Inverse(transform.rotation), Vector3.one) * Matrix4x4.TRS(-transform.position, Quaternion.identity, Vector3.one); if (m_currentAsset && m_instanceHandle) { FlexExt.Instance instance = m_instanceHandle.instance; int[] indices = new int[instance.numParticles]; FlexUtils.FastCopy(instance.particleIndices, indices); foreach (var index in indices) { Vector4 particle = _particleData.GetParticle(index); float storeW = particle.w; particle = offset.MultiplyPoint3x4(particle); particle.w = storeW; _particleData.SetParticle(index, particle); _particleData.SetVelocity(index, Vector3.zero); } } transform.position = m_teleportPosition; transform.rotation = m_teleportRotation; transform.hasChanged = false; }
protected virtual void CreateInstance() { if (m_currentContainer && m_currentContainer.handle && m_currentAsset && m_currentAsset.handle) { int group = m_particleGroup < 0 ? ++sm_nextGroup : m_particleGroup; Flex.Phase flags = Flex.Phase.Default; if (m_selfCollide) { flags |= Flex.Phase.SelfCollide; } if (m_selfCollideFilter) { flags |= Flex.Phase.SelfCollideFilter; } if (m_fluid) { flags |= Flex.Phase.Fluid; } m_phase = Flex.MakePhase(group, flags); m_instanceHandle = m_currentContainer.CreateInstance(m_currentAsset.handle, transform.localToWorldMatrix, Vector3.zero, m_phase, m_massScale); if (m_instanceHandle) { FlexExt.Instance instance = m_instanceHandle.instance; m_indices = new int[m_currentAsset.maxParticles]; m_indexCount = instance.numParticles; if (m_indexCount > 0) { FlexUtils.FastCopy(instance.particleIndices, 0, ref m_indices[0], 0, sizeof(int) * m_indexCount); } } } }
protected void SetIndices(int[] _indices, int _count) { m_indexCount = Mathf.Min(_count, m_currentAsset.maxParticles); Array.Copy(_indices, m_indices, m_indexCount); FlexExt.Instance instance = m_instanceHandle.instance; instance.numParticles = m_indexCount; if (m_indexCount > 0) { FlexUtils.FastCopy(ref m_indices[0], 0, instance.particleIndices, 0, sizeof(int) * m_indexCount); } m_instanceHandle.instance = instance; }
//This function is to set the initial velocity of the fluid bool PresetVelocities(FlexContainer.ParticleData _particleData) { Vector3 initVelocity = new Vector3(0, 0, -2.0f); //Change the Vector to adjust the intial velocity FlexExt.Instance instance = m_instanceHandle.instance; int[] indices = new int[instance.numParticles]; FlexUtils.FastCopy(instance.particleIndices, indices); foreach (var index in indices) { _particleData.SetVelocity(index, initVelocity); } return(true); }
protected override void OnFlexUpdate(FlexContainer.ParticleData _particleData) { if (Application.isPlaying && handle) { FlexExt.Instance instance = handle.instance; Vector3 position = Vector3.zero; FlexUtils.FastCopy(instance.shapeTranslations, 0, ref position, 0, 12); Quaternion rotation = Quaternion.identity; FlexUtils.FastCopy(instance.shapeRotations, 0, ref rotation, 0, 16); transform.position = position - rotation * m_asset.shapeCenters[0]; transform.rotation = rotation; transform.hasChanged = false; } base.OnFlexUpdate(_particleData); }
void OnFlexUpdate(FlexContainer.ParticleData _particleData) { if (m_actor && m_actor.handle && m_skinningBones.Length > 0) { FlexExt.Instance instance = m_actor.handle.instance; int boneCount = m_skinningBones.Length; Vector3 bonePosition = Vector3.zero; Quaternion boneRotation = Quaternion.identity; for (int i = 0; i < boneCount; ++i) { FlexUtils.FastCopy(instance.shapeTranslations, sizeof(float) * 3 * i, ref bonePosition, 0, sizeof(float) * 3); m_skinningBones[i].position = bonePosition; FlexUtils.FastCopy(instance.shapeRotations, sizeof(float) * 4 * i, ref boneRotation, 0, sizeof(float) * 4); m_skinningBones[i].rotation = boneRotation; } } }
//This function is to get the velocity of 40 frames //And then call the CalcAcceleration function to calculate the accelerations bool CoutAccelerations(FlexContainer.ParticleData _particleData) { FlexExt.Instance instance = m_instanceHandle.instance; int[] indices = new int[instance.numParticles]; FlexUtils.FastCopy(instance.particleIndices, indices); float totalzVelocity = 0; foreach (var index in indices) { totalzVelocity += _particleData.GetVelocity(index).z; } frameVelocity.Add(totalzVelocity / indices.Length); if (frameVelocity.Count >= 40) //Change the 40 to other numbers to adjust the time of data collections { return(CalcAcceleration()); } else { return(false); } }
public static extern void FastCopy(IntPtr src, int srcOfs, ref FlexExt.Instance dst, int dstOfs, int size);
public static void FastCopy(IntPtr source, ref FlexExt.Instance destination) { FastCopy(source, 0, ref destination, 0, instanceSize); }
public static void FastCopy(ref FlexExt.Instance source, IntPtr destination) { FastCopy(ref source, 0, destination, 0, instanceSize); }
void Create() { m_actor = GetComponentInParent <FlexActor>(); if (m_actor == null) { Debug.LogError("_auxFlexDrawPartcles should be parented to a FlexActor"); Debug.Break(); } if (m_actor && m_actor.handle) { FlexExt.Instance instance = m_actor.handle.instance; int[] indices = new int[instance.numParticles]; if (instance.numParticles > 0) { FlexUtils.FastCopy(instance.particleIndices, indices); } m_mesh = new Mesh(); m_mesh.name = "Flex Particles"; m_mesh.vertices = new Vector3[1]; if (m_actor is FlexSoftActor) { int shapeCount = m_actor.asset.shapeOffsets.Length; m_indexBuffers = new ComputeBuffer[shapeCount]; m_particleMaterials = new Material[shapeCount]; m_mesh.subMeshCount = shapeCount; for (int i = 0; i < shapeCount; ++i) { int start = i == 0 ? 0 : m_actor.asset.shapeOffsets[i - 1]; int count = m_actor.asset.shapeOffsets[i] - start; m_mesh.SetIndices(new int[count], MeshTopology.Points, i); m_indexBuffers[i] = new ComputeBuffer(count, 4); int[] shape = new int[count]; for (int j = 0; j < count; ++j) { shape[j] = indices[m_actor.asset.shapeIndices[start + j]]; } m_indexBuffers[i].SetData(shape); m_particleMaterials[i] = new Material(Shader.Find(PARTICLES_SHADER)); m_particleMaterials[i].hideFlags = HideFlags.HideAndDontSave; } } else { m_mesh.subMeshCount = 1; m_mesh.SetIndices(new int[0], MeshTopology.Points, 0); m_mesh.SetIndices(new int[instance.numParticles], MeshTopology.Points, 0); m_indexBuffers = new ComputeBuffer[1]; if (instance.numParticles > 0) { m_indexBuffers[0] = new ComputeBuffer(instance.numParticles, sizeof(int)); m_indexBuffers[0].SetData(indices); } m_particleMaterials = new Material[1]; m_particleMaterials[0] = new Material(Shader.Find(PARTICLES_SHADER)); m_particleMaterials[0].hideFlags = HideFlags.HideAndDontSave; } m_mesh.bounds = m_actor.bounds; MeshFilter meshFilter = GetComponent <MeshFilter>(); meshFilter.mesh = m_mesh; MeshRenderer meshRenderer = GetComponent <MeshRenderer>(); meshRenderer.materials = m_particleMaterials; meshRenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.On; #if UNITY_EDITOR EditorUtility.SetSelectedRenderState(meshRenderer, EditorSelectedRenderState.Hidden); #endif UpdateMesh(); } }