internal void Lerp(SplatWeight lhs, SplatWeight rhs, float alpha, List <int> mask) { // optimize for some common values // unrolling the loop in these smaller cases can improve performances by ~33% if (mask.Count == 4) { values[mask[0]] = Mathf.LerpUnclamped(lhs.values[mask[0]], rhs.values[mask[0]], alpha); values[mask[1]] = Mathf.LerpUnclamped(lhs.values[mask[1]], rhs.values[mask[1]], alpha); values[mask[2]] = Mathf.LerpUnclamped(lhs.values[mask[2]], rhs.values[mask[2]], alpha); values[mask[3]] = Mathf.LerpUnclamped(lhs.values[mask[3]], rhs.values[mask[3]], alpha); } else if (mask.Count == 8) { values[mask[0]] = Mathf.LerpUnclamped(lhs.values[mask[0]], rhs.values[mask[0]], alpha); values[mask[1]] = Mathf.LerpUnclamped(lhs.values[mask[1]], rhs.values[mask[1]], alpha); values[mask[2]] = Mathf.LerpUnclamped(lhs.values[mask[2]], rhs.values[mask[2]], alpha); values[mask[3]] = Mathf.LerpUnclamped(lhs.values[mask[3]], rhs.values[mask[3]], alpha); values[mask[4]] = Mathf.LerpUnclamped(lhs.values[mask[4]], rhs.values[mask[4]], alpha); values[mask[5]] = Mathf.LerpUnclamped(lhs.values[mask[5]], rhs.values[mask[5]], alpha); values[mask[6]] = Mathf.LerpUnclamped(lhs.values[mask[6]], rhs.values[mask[6]], alpha); values[mask[7]] = Mathf.LerpUnclamped(lhs.values[mask[7]], rhs.values[mask[7]], alpha); } else { for (int i = 0; i < mask.Count; i++) { values[mask[i]] = Mathf.LerpUnclamped(lhs.values[mask[i]], rhs.values[mask[i]], alpha); } } }
/// <summary> /// Copy values array to another splatweight. This function doesn't check /// that attribute layouts are matching; must do this yourself. /// </summary> /// <param name="other"></param> internal void CopyTo(SplatWeight other) { for (int i = 0; i < values.Length; i++) { other.values[i] = this.values[i]; } }
/// <summary> /// Lerp weights between lhs and rhs for value at the given index. /// </summary> /// <param name="lhs"></param> /// <param name="rhs"></param> /// <param name="strength"></param> /// <param name="index"></param> internal void LerpWeightOnSingleChannel(SplatSet lhs, SplatWeight rhs, float strength, MeshChannel channel, int index, int baseTexIndex) { if (!channelMap.ContainsKey(channel)) { return; } var channelIndex = channelMap[channel]; for (int i = 0; i < weightCount; i++) { float lerpedValue = Mathf.LerpUnclamped(lhs.weights[channelIndex][i][index], rhs[channel][index], strength); // replace the original value at index with the lerped value var newWeightVector = lhs.weights[channelIndex][i]; newWeightVector[index] = lerpedValue; if (baseTexIndex > -1) { newWeightVector[baseTexIndex] += (lhs.weights[channelIndex][i][index] - newWeightVector[index]); } this.weights[channelIndex][i] = newWeightVector; } }
/// <summary> /// Lerp weights between lhs and rhs /// </summary> /// <param name="lhs"></param> /// <param name="rhs"></param> /// <param name="strength"></param> internal void LerpWeights(SplatSet lhs, SplatWeight rhs, float strength) { for (int i = 0; i < weightCount; i++) { foreach (var cm in channelMap) { this.weights[cm.Value][i] = Vector4.LerpUnclamped(lhs.weights[cm.Value][i], rhs[cm.Key], strength); } } }
/// <summary> /// Get the default weights for each channel (the minimum) /// </summary> /// <returns></returns> internal SplatWeight GetMinWeights() { SplatWeight min = new SplatWeight(channelMap); foreach (AttributeLayout al in attributeLayout) { Vector4 v = min[al.channel]; v[(int)al.index] = al.min; min[al.channel] = v; } return(min); }
/// <summary> /// Deep copy constructor. /// </summary> /// <param name="rhs">The SplatWeight we copy from</param> internal SplatWeight(SplatWeight rhs) { this.map = new Dictionary <MeshChannel, int>(); foreach (var kvp in rhs.map) { this.map.Add(kvp.Key, kvp.Value); } int len = rhs.values.Length; this.values = new float[len]; System.Array.Copy(rhs.values, this.values, len); }
internal void Lerp(SplatWeight lhs, SplatWeight rhs, float alpha) { int len = values.Length; if (len == 4) { values[0] = Mathf.LerpUnclamped(lhs.values[0], rhs.values[0], alpha); values[1] = Mathf.LerpUnclamped(lhs.values[1], rhs.values[1], alpha); values[2] = Mathf.LerpUnclamped(lhs.values[2], rhs.values[2], alpha); values[3] = Mathf.LerpUnclamped(lhs.values[3], rhs.values[3], alpha); } else if (len == 8) { values[0] = Mathf.LerpUnclamped(lhs.values[0], rhs.values[0], alpha); values[1] = Mathf.LerpUnclamped(lhs.values[1], rhs.values[1], alpha); values[2] = Mathf.LerpUnclamped(lhs.values[2], rhs.values[2], alpha); values[3] = Mathf.LerpUnclamped(lhs.values[3], rhs.values[3], alpha); values[4] = Mathf.LerpUnclamped(lhs.values[4], rhs.values[4], alpha); values[5] = Mathf.LerpUnclamped(lhs.values[5], rhs.values[5], alpha); values[6] = Mathf.LerpUnclamped(lhs.values[6], rhs.values[6], alpha); values[7] = Mathf.LerpUnclamped(lhs.values[7], rhs.values[7], alpha); } else if (len == 16) { values[0] = Mathf.LerpUnclamped(lhs.values[0], rhs.values[0], alpha); values[1] = Mathf.LerpUnclamped(lhs.values[1], rhs.values[1], alpha); values[2] = Mathf.LerpUnclamped(lhs.values[2], rhs.values[2], alpha); values[3] = Mathf.LerpUnclamped(lhs.values[3], rhs.values[3], alpha); values[4] = Mathf.LerpUnclamped(lhs.values[4], rhs.values[4], alpha); values[5] = Mathf.LerpUnclamped(lhs.values[5], rhs.values[5], alpha); values[6] = Mathf.LerpUnclamped(lhs.values[6], rhs.values[6], alpha); values[7] = Mathf.LerpUnclamped(lhs.values[7], rhs.values[7], alpha); values[8] = Mathf.LerpUnclamped(lhs.values[8], rhs.values[8], alpha); values[9] = Mathf.LerpUnclamped(lhs.values[9], rhs.values[9], alpha); values[10] = Mathf.LerpUnclamped(lhs.values[10], rhs.values[10], alpha); values[11] = Mathf.LerpUnclamped(lhs.values[11], rhs.values[11], alpha); values[12] = Mathf.LerpUnclamped(lhs.values[12], rhs.values[12], alpha); values[13] = Mathf.LerpUnclamped(lhs.values[13], rhs.values[13], alpha); values[14] = Mathf.LerpUnclamped(lhs.values[14], rhs.values[14], alpha); values[15] = Mathf.LerpUnclamped(lhs.values[15], rhs.values[15], alpha); } else { for (int i = 0; i < lhs.values.Length; i++) { values[i] = Mathf.LerpUnclamped(lhs.values[i], rhs.values[i], alpha); } } }
/// <summary> /// Lerp weights between lhs and rhs for value at the given index. /// </summary> /// <param name="lhs"></param> /// <param name="rhs"></param> /// <param name="strength"></param> /// <param name="index"></param> internal void LerpWeightOnSingleChannel(SplatSet lhs, SplatWeight rhs, float strength, int index) { for (int i = 0; i < weightCount; i++) { foreach (var cm in channelMap) { float lerpedValue = Mathf.LerpUnclamped(lhs.weights[cm.Value][i][index], rhs[cm.Key][index], strength); // replace the original value at index with the lerped value var newWeightVector = lhs.weights[cm.Value][i]; newWeightVector[index] = lerpedValue; this.weights[cm.Value][i] = newWeightVector; } } }
/// <summary> /// Initialize a new SplatSet with vertex count and attribute layout. Attributes should /// match the length of weights applied (one attribute per value). /// Weight values are initialized to zero (unless preAlloc is false, then only the channel /// container array is initialized and arrays aren't allocated) /// </summary> /// <param name="vertexCount"></param> /// <param name="attributes"></param> /// <param name="preAlloc">Allocate and initialize Weight values to 0 ?</param> internal SplatSet(int vertexCount, AttributeLayout[] attributes, bool preAlloc = true) { this.channelMap = SplatWeight.GetChannelMap(attributes); int channels = channelMap.Count; this.attributeLayout = attributes; this.weights = new Vector4[channels][]; this.weightCount = vertexCount; if (preAlloc) { for (int i = 0; i < channels; i++) { this.weights[i] = new Vector4[vertexCount]; } } }