/** * Retrieves the indices of the particles that influece a given vertex. In the weight * field of each influence, the squared distance from the particle to the vertex is provided. */ public List <ParticleInfluence> GetParticleInfluences(Vector3 vertex) { // TODO: try to make it faster. List <ParticleInfluence> allInfluences = new List <ParticleInfluence>(); // Get squared distance to all particles: for (int i = 0; i < proxy.positions.Length; ++i) { ParticleInfluence influence = new ParticleInfluence(); influence.particleIndex = i; influence.bindVector = transform.InverseTransformVector(transform.TransformPoint(vertex) - proxy.GetParticlePosition(i)); influence.weight = influence.bindVector.sqrMagnitude; allInfluences.Add(influence); } // Sort by distance: allInfluences.Sort( delegate(ParticleInfluence x, ParticleInfluence y) { return(x.weight.CompareTo(y.weight)); }); // Return the K nearest: return(allInfluences.GetRange(0, numInfluences)); }
/** * Binds the mesh to the proxy particle actor. */ public void BindToProxy() { initialized = false; initializing = false; if (deformedMesh == null || proxy == null) { return; } initializing = true; influences = new ParticleInfluence[deformedMesh.vertexCount * numInfluences]; bindPoses = new Quaternion[proxy.positions.Length]; // Get particle bind poses: for (int i = 0; i < proxy.positions.Length; ++i) { Quaternion proxyToLocal = Quaternion.Inverse(transform.rotation) * proxy.transform.rotation; bindPoses[i] = Quaternion.Inverse(proxyToLocal * proxy.sharedTopology.referenceOrientation[i]); } Vector3[] vertices = deformedMesh.vertices; //TODO: if the vertex position has already been processed, skip it. use unique positions only. for (int i = 0; i < vertices.Length; ++i) { // Find nearest "numInfluences" proxy particles: List <ParticleInfluence> infs = GetParticleInfluences(vertices[i]); // Calculate weights using shepard's method: float total = 0; for (int j = 0; j < infs.Count; ++j) { ParticleInfluence pi = infs[j]; pi.weight = 1.0f / (float)Math.Pow(Mathf.Sqrt(pi.weight), falloff); infs[j] = pi; total += infs[j].weight; } // Normalize to get final linear weights: for (int j = 0; j < infs.Count; ++j) { ParticleInfluence pi = infs[j]; pi.weight = pi.weight / total; infs[j] = pi; } // Insert this vertex's influence in the array: for (int j = 0; j < numInfluences; ++j) { influences[i * numInfluences + j] = infs[j]; } } initializing = false; initialized = true; }