public void MoveAngle(Guid pairId, float angleDegrees) { AutoSplatAngleTexturePair pair = GetPair(pairId); if (!pair.AngleDegrees.Equals(angleDegrees)) { AutoSplatAngleTexturePair clone = null; if (pair.IsCriticalAngle) { clone = new AutoSplatAngleTexturePair(pair); // We won't need to 'infinitesimally bump' the new angle because // we already tested to establish that the values are not equal. } else { // Guarenteed to be neither first nor last because it's not critical int pairIndex = GetIndex(pairId); float prevAngle = m_AngleSortedPairs[pairIndex - 1].AngleDegrees; float nextAngle = m_AngleSortedPairs[pairIndex + 1].AngleDegrees; if (angleDegrees < prevAngle || angleDegrees > nextAngle) { // Only Add and Remove should change the sorting order throw new ConstraintException( "MoveAngle would change ordering of pairs;" + "only Add and Remove should change the sorting order."); } // If the move would make the angle coincide exactly with one of // its neighbors, back it off a teensie-weensie bit. const float infinitesimal = 0.0001f; if (angleDegrees.Equals(prevAngle)) { angleDegrees += infinitesimal; } else if (angleDegrees.Equals(nextAngle)) { angleDegrees -= infinitesimal; } } float oldAngle = pair.AngleDegrees; pair.AngleDegrees = angleDegrees; FireAngleMoved(pairId, oldAngle, angleDegrees); if (null != clone) { // So we are splitting one of the critical pairs. By waiting until // after we've moved the original pair to add the clone, we assure // the sorting order stays the same for pre-existing pairs. The // Outside World cares about this order. InternalAddAngleTexturePair(clone); } } }
public AutoSplatAngleTexturePair AddAngleTexturePair(float angleDegrees, int textureIndex) { AutoSplatAngleTexturePair pair = new AutoSplatAngleTexturePair(angleDegrees, textureIndex); InternalAddAngleTexturePair(pair); return(pair); }
/// <summary> /// This is like an 'add' operation, but you need to restore the id of the /// pair literally because further operations in the undo stack will refer /// to the pair by id. /// </summary> /// <param name="angleDegrees">angle of the slope</param> /// <param name="textureIndex">texture associated with the slope</param> /// <param name="id">unique id by which the slope is accessed</param> /// <returns></returns> public AutoSplatAngleTexturePair UndoRemoveAngleTexturePair(float angleDegrees, int textureIndex, Guid id) { AutoSplatAngleTexturePair pair = new AutoSplatAngleTexturePair(angleDegrees, textureIndex, id); InternalAddAngleTexturePair(pair); return(pair); }
void InternalRemoveAngleTexturePair(AutoSplatAngleTexturePair pair) { // You are not allowed to remove critical pairs! We have a design // constraint that there are always a horizontal and a vertical pair. // // This is not as constraining as it might sound. Assume the 'remove' // request is the outcome of a GUI action--like dragging to the trash. // Even if you attempt to remove a critical pair, the act of moving it // to the trash hotspot will move it away from the critical position, // which in turn causes a new pair to be inserted to replace it in the // critical position. You could do it all day if that's how you like // to spend your time. if (!pair.IsCriticalAngle) { m_IdToPairMap.Remove(pair.Id); m_AngleSortedPairs.Remove(pair); FireAngleTexturePairRemoved(pair); } }
public float[] GetAutoSplatSampleNormalized(float angleDegrees) { AutoSplatAngleTexturePair lowerPair = null; AutoSplatAngleTexturePair higherPair = null; // We assume the pairs are sorted in increasing order by angle foreach (AutoSplatAngleTexturePair pair in m_AngleSortedPairs) { if (pair.AngleDegrees == angleDegrees) { lowerPair = pair; higherPair = pair; break; } if (pair.AngleDegrees < angleDegrees) { lowerPair = pair; continue; } if (pair.AngleDegrees > angleDegrees) { higherPair = pair; // We should have both the lower & upper bounds now, so break; break; } } if (lowerPair == null) { Debug.Assert(lowerPair != null, "Unable to find lower angle when getting autosplat sample. Angle=" + angleDegrees + " Range=" + this); } if (higherPair == null) { Debug.Assert(higherPair != null, "Unable to find higher angle when getting autosplat sample. Angle=" + angleDegrees + " Range=" + this); } // Compute the gradiant weighting for the lower & higher angled textures float lowerWeight; float higherWeight; float angleDiff = higherPair.AngleDegrees - lowerPair.AngleDegrees; if (angleDiff == 0 || lowerPair.TextureIndex == higherPair.TextureIndex) { lowerWeight = 0f; higherWeight = 1f; } else { // How close is the angle to the higher/lower angle? Normalize // that distance from 0..1 and use that as the gradient weights higherWeight = (angleDegrees - lowerPair.AngleDegrees) / angleDiff; lowerWeight = 1f - higherWeight; } float[] normalizedSample = new float[AlphaSplatTerrainConfig.MAX_LAYER_TEXTURES]; // It's important that we set higher second because // if lower & higher angle are equal the same, we // set the higherWeight to 1f above and want to make // sure it's set that way here. normalizedSample[lowerPair.TextureIndex] = lowerWeight; normalizedSample[higherPair.TextureIndex] = higherWeight; return(normalizedSample); }