void OnFlexUpdate(FlexContainer.ParticleData _particleData) { // Fill a local copy of the particles: _particleData.GetParticles(m_actor.indices[0], m_actor.indexCount, m_particles); if (firstRun) { firstRun = false; // only run this once: Debug.Log("Creating Mapping from Particles to Bones based on closest Vertex of the original mesh!"); // TODO: re-check full algorithm below... Vector3[] cachedMeshVertices = referenceAnimSkin.sharedMesh.vertices; foreach (var i in m_particles) { Vector3 restPos = new Vector3(); restPos.x = i.x; restPos.y = i.y; restPos.z = i.z; particleRestPositions.Add(restPos); particlePositions.Add(restPos); int nearestIndexforParticle = GetNearestVertIndex(restPos, cachedMeshVertices); Vector3 VertOffset = restPos - cachedMeshVertices[nearestIndexforParticle]; VertOffsetVectors.Add(VertOffset); nearestVertexIndexForParticle.Add(nearestIndexforParticle); } SetBoneWeights(cachedMeshVertices, nearestVertexIndexForParticle); } else // no update on firstRun! (that assumes that the animation starts from the rest position) { UpdateParticlePositions(_particleData); } }
// Update is called once per frame public override void OnFlexUpdate(FlexContainer.ParticleData _particleData) { //base.OnFlexUpdate(_particleData); if (m_actor && m_actor.container) { m_actor.container.AddFluidIndices(m_actor.indices, m_actor.indexCount); } if (Application.IsPlaying(this)) { Vector4[] particles = new Vector4[10000]; //_particleData.GetParticles(0, 9999, particles); _particleData.GetRestParticles(0, 9999, particles); Array.Sort <Vector4>(particles, new Comparison <Vector4>( (i1, i2) => Vector4.SqrMagnitude(i2).CompareTo(Vector4.SqrMagnitude(i1)))); //RMMemoryManager rmm = Camera.main.GetComponent<RMMemoryManager>(); //List<RMPrimitive> prims = rmm.RM_Prims; RayMarcher rayMarcher = Camera.main.GetComponent <RayMarcher>(); List <RMObj> renderList = rayMarcher.RenderList; Vector4 force; for (int i = 0; i < 28; ++i) { force = particles[i]; force += new Vector4(0.0f, -9.81f, 0.0f, 0.0f); renderList[i].transform.position += new Vector3(force.x, force.y, force.z) * Time.deltaTime; } } }
public void UpdateParticlePositions(FlexContainer.ParticleData _particleData) { // "Zero out" all particle postions first for (int i = 0; i < particlePositions.Count; i++) { particlePositions[i] = Vector3.zero; } // For each bone, check all particles it should affect and add the effect to that particlePosition: foreach (WeightList wList in particleBoneWeights) { foreach (ParticleBoneWeight pbw in wList.weights) { // use the current transform of the bone to add its contribution to the new particle position: Transform t = referenceAnimSkin.bones[wList.boneIndex]; // Adding the VertOffsetVector moves it from the original vertex to the particle particlePositions[pbw.particleIndex] += t.localToWorldMatrix.MultiplyPoint3x4(pbw.localPosition) * pbw.weight + VertOffsetVectors[pbw.particleIndex]; } } // We now have the particlePositions as they should be based on the animation, // BUT at the position of the reference animation's root bone in world space. // First move it back to local space relative to its root bone. // And then we should have to move it back to world space relative to this GameObject, // but for some reason that is not needed - but it breaks when this GameObject is rotated // (didn't test scaling). There must be something in the Flex setup that moves the points? : for (int i = 0; i < particlePositions.Count; i++) { particlePositions[i] = referenceAnimSkin.rootBone.transform.InverseTransformPoint(particlePositions[i]); //particlePositions[i] = this.transform.TransformPoint(particlePositions[i]); } // Now we should have the target particlePositions if (particlePositions.Count == 0) // this check shouldn't be needed now without uFlex, but leaving it in { return; } // Now for each particle, calculate how far it is from its intended (animation-)position: Vector3 _tempVector3; for (int particleIndex = 0; particleIndex < m_particles.Length; particleIndex++) { // casting a Vector4 to a Vector3 automatically discards the w component: _tempVector3 = particlePositions[particleIndex] - (Vector3)m_particles[particleIndex]; particleDisplacementVector[particleIndex].x = _tempVector3.x; particleDisplacementVector[particleIndex].y = _tempVector3.y; particleDisplacementVector[particleIndex].z = _tempVector3.z; } // Now apply an appropriate velocity change to nudge the particle into the right direction: // Get/Set all velocities at the same time, as this is the most performant method: _particleData.GetVelocities(m_actor.indices[0], m_actor.indexCount, m_velocities); for (int i = 0; i < particleDisplacementVector.Length; i++) { // Note: we replicate roughly what ApplyImpulses in Actor would do, i.e. scale by weight: // impulse divided by particle mass (which is 1/w): m_velocities[i] += particleDisplacementVector[i] * m_particles[i].w; } _particleData.SetVelocities(m_actor.indices[0], m_actor.indexCount, m_velocities); }
private void OnFlexUpdate(FlexContainer.ParticleData particleData) { if (!Application.isPlaying) { return; } if (container && container.solver) { UpdateWind(); } }
protected override void OnFlexUpdate(FlexContainer.ParticleData _particleData) { if (Application.isPlaying && m_referencePoints != null && m_referencePoints.Length >= 3) { Vector3 p0 = _particleData.GetParticle(m_referencePoints[0]); Vector3 p1 = _particleData.GetParticle(m_referencePoints[1]); Vector3 p2 = _particleData.GetParticle(m_referencePoints[2]); Vector3 clothZ = Vector3.Cross(p1 - p0, p2 - p0).normalized, clothY = Vector3.Cross(clothZ, p1 - p0).normalized; Quaternion globalRotation = Quaternion.LookRotation(clothZ, clothY) * Quaternion.Inverse(m_localRotation); Vector3 globalPosition = (p0 + p1 + p2) / 3 - globalRotation * m_localPosition; transform.position = globalPosition; transform.rotation = globalRotation; transform.hasChanged = false; } base.OnFlexUpdate(_particleData); if (hasSetFixed) { _particleData.SetParticle(indices[itopleft], new Vector4(topleft.x, topleft.y, topleft.z, 0)); _particleData.SetParticle(indices[itopright], new Vector4(topright.x, topright.y, topright.z, 0)); } else { topleft = _particleData.GetParticle(indices[0]); topright = _particleData.GetParticle(indices[0]); itopleft = 0; itopright = 0; for (int i = 1; i < indices.Length; i++) { Vector3 now = _particleData.GetParticle(indices[i]); Vector3 now2topleft = topleft - now; Vector3 now2topright = topright - now; if (now2topleft.y <= 0 && now2topleft.x >= 0) { topleft = now; itopleft = i; } if (now2topright.y <= 0 && now2topright.x <= 0) { topright = now; itopright = i; } } hasSetFixed = true; } }
protected override void OnFlexUpdate(FlexContainer.ParticleData _particleData) { base.OnFlexUpdate(_particleData); /* * if (Application.isPlaying) * { * Flex.Buffer buffer = Flex.AllocBuffer(FlexContainer.library, m_actor.container.maxParticles, sizeof(float) * 4, Flex.BufferType.Host); * Flex.SetDiffuseParticles(m_actor.container.solver, buffer, buffer, m_actor.indexCount); * * foreach (var index in m_actor.indices) * { * float sqrSpeed = _particleData.GetVelocity(index).sqrMagnitude; * if (sqrSpeed >= sqrFoamSpeed) * { * Vector3 pos = _particleData.GetParticle(index); * Instantiate(foam, pos, Quaternion.identity, transform); * } * } * } */ }
/** * This will only run once by unregistering itself (until ReLock is called). */ void OnFlexUpdate(FlexContainer.ParticleData _particleData) { m_actor.onFlexUpdate -= OnFlexUpdate; // only run once! m_actor.asset.ClearFixedParticles(); _particleData.GetParticles(m_actor.indices[0], m_actor.indexCount, m_particles); // find all particles that are inside one of the colliders, and add it to fixedParticles: Collider[] to_be_locked_colls = GetComponents <Collider>(); float particleRadius = m_actor.asset.particleSpacing; // not sure if this is the radius or the diameter for (int i = 0; i < m_particles.Length; i++) { Collider[] overlapped_colls = Physics.OverlapSphere(m_particles[i], particleRadius); foreach (Collider ovrlp_c in overlapped_colls) { if (Array.IndexOf <Collider>(to_be_locked_colls, ovrlp_c) > -1) { m_actor.asset.FixedParticle(i, true); break; // no need to check other colliders for this particle now } } } m_actor.asset.Rebuild(); }