/// <summary> /// Applies the SplineUser modifiers to the provided sample /// </summary> /// <param name="sample"></param> public void ModifySample(SplineSample sample) { offsetModifier.Apply(sample); _rotationModifier.Apply(sample); _colorModifier.Apply(sample); _sizeModifier.Apply(sample); }
public override void Apply(SplineSample result) { if (keys.Count == 0) { return; } base.Apply(result); Quaternion offset = Quaternion.identity, look = result.rotation; for (int i = 0; i < keys.Count; i++) { if (keys[i].useLookTarget && keys[i].target != null) { Quaternion lookDir = Quaternion.LookRotation(keys[i].target.position - result.position); look = Quaternion.Slerp(look, lookDir, keys[i].Evaluate(result.percent)); } else { Quaternion euler = Quaternion.Euler(keys[i].rotation.x, keys[i].rotation.y, keys[i].rotation.z); offset = Quaternion.Slerp(offset, offset * euler, keys[i].Evaluate(result.percent)); } } Quaternion rotation = look * offset; Vector3 invertedNormal = Quaternion.Inverse(result.rotation) * result.normal; result.direction = rotation * Vector3.forward; result.normal = rotation * invertedNormal; }
/// <summary> /// Same as Spline.Evaluate but the results are transformed by the computer's transform /// </summary> /// <param name="from">Start position [0-1]</param> /// <param name="to">Target position [from-1]</param> /// <returns></returns> public void Evaluate(ref SplineSample[] results, double from = 0.0, double to = 1.0) { if (!hasSamples) { results = new SplineSample[0]; return; } Spline.FormatFromTo(ref from, ref to); int fromIndex, toIndex; double lerp; GetSamplingValues(from, out fromIndex, out lerp); GetSamplingValues(to, out toIndex, out lerp); if (lerp > 0.0 && toIndex < Count - 1) { toIndex++; } int clippedIterations = toIndex - fromIndex + 1; if (results == null) { results = new SplineSample[clippedIterations]; } else if (results.Length != clippedIterations) { results = new SplineSample[clippedIterations]; } results[0] = Evaluate(from); results[results.Length - 1] = Evaluate(to); for (int i = 1; i < results.Length - 1; i++) { results[i] = samples[i + fromIndex]; } }
/// <summary> /// Evaluate the spline at the given time and return a SplineSample /// </summary> /// <param name="percent">Percent of evaluation [0-1]</param> public SplineSample Evaluate(double percent) { SplineSample result = new SplineSample(); Evaluate(result, percent); return(result); }
/// <summary> /// Evaluate the spline at the position of a given point and return a SplineSample /// </summary> /// <param name="pointIndex">Point index</param> public SplineSample Evaluate(int pointIndex) { SplineSample result = new SplineSample(); Evaluate(result, GetPointPercent(pointIndex)); return(result); }
public static SplineSample Lerp(SplineSample a, SplineSample b, double t) { SplineSample result = new SplineSample(); Lerp(a, b, t, result); return(result); }
public SplineSample Evaluate(double percent) { SplineSample result = new SplineSample(); Evaluate(UnclipPercent(percent), result); result.percent = DMath.Clamp01(percent); return(result); }
public void CopyFrom(SplineSample input) { position = input.position; direction = input.direction; normal = input.normal; color = input.color; size = input.size; percent = input.percent; }
public SplineSample(SplineSample input) { position = input.position; normal = input.normal; direction = input.direction; color = input.color; size = input.size; percent = input.percent; }
public void CopyFrom(SplineSample input) { position = input.position; forward = input.forward; up = input.up; color = input.color; size = input.size; percent = input.percent; }
public static void Lerp(SplineSample a, SplineSample b, float t, SplineSample target) { target.position = DMath.LerpVector3(a.position, b.position, t); target.forward = Vector3.Slerp(a.forward, b.forward, t); target.up = Vector3.Slerp(a.up, b.up, t); target.color = Color.Lerp(a.color, b.color, t); target.size = Mathf.Lerp(a.size, b.size, t); target.percent = DMath.Lerp(a.percent, b.percent, t); }
public SplineSample(SplineSample input) { position = input.position; up = input.up; forward = input.forward; color = input.color; size = input.size; percent = input.percent; }
public virtual void Project(Vector3 position, SplineSample result, double from = 0.0, double to = 1.0) { if (_spline == null) { return; } sampleCollection.Project(position, _spline.pointCount, result, UnclipPercent(from), UnclipPercent(to)); ClipPercent(ref result.percent); }
public static void Lerp(SplineSample a, SplineSample b, float t, SplineSample target) { target.position = DMath.LerpVector3(a.position, b.position, t); target.direction = Vector3.Slerp(a.direction, b.direction, t); target.normal = Vector3.Slerp(a.normal, b.normal, t); target.color = Color.Lerp(a.color, b.color, t); target.size = Mathf.Lerp(a.size, b.size, t); target.percent = DMath.Lerp(a.percent, b.percent, t); }
public override void Apply(SplineSample result) { if (keys.Count == 0) { return; } for (int i = 0; i < keys.Count; i++) { result.size += keys[i].Evaluate(result.percent) * keys[i].scale.magnitude; } }
public float GetSpeed(SplineSample sample) { float speed = 0f; for (int i = 0; i < keys.Count; i++) { float lerp = keys[i].Evaluate(sample.percent); speed += keys[i].speed * lerp; } return(speed); }
public override void Apply(SplineSample result) { if (keys.Count == 0) { return; } base.Apply(result); Vector2 offset = Evaluate(result.percent); result.position += result.right * offset.x + result.up * offset.y; }
public override void Apply(SplineSample result) { if (keys.Count == 0) { return; } base.Apply(result); for (int i = 0; i < keys.Count; i++) { result.color = keys[i].Blend(result.color, keys[i].Evaluate(result.percent)); } }
public Vector2 GetScale(SplineSample sample) { Vector2 scale = Vector2.one; for (int i = 0; i < keys.Count; i++) { float lerp = keys[i].Evaluate(sample.percent); Vector2 scaleMultiplier = Vector2.Lerp(Vector2.one, keys[i].scale, lerp); scale.x *= scaleMultiplier.x; scale.y *= scaleMultiplier.y; } return(scale); }
void Draw(SplineSample[] points, ref float[,] drawLayer, ref float[,] alphaLayer) { List <SplineSample> selectedPoints = new List <SplineSample>(); Point last = new Point(); //Filter out points that are too close to each other for (int i = 0; i < points.Length; i++) { Point current = ToHeightmapCoords(points[i].position + points[i].up * offset); if (i == 0 || i == points.Length - 1) { last = new Point(current.x, current.y); selectedPoints.Add(points[i]); } else if (Vector2.Distance(new Vector2(current.x, current.y), new Vector2(last.x, last.y)) >= 1.5f) { selectedPoints.Add(points[i]); last = new Point(current.x, current.y); } } if (selectedPoints.Count <= 1) { return; } TerrainPaintPoint[] paintPoints = new TerrainPaintPoint[selectedPoints.Count]; for (int i = 0; i < selectedPoints.Count; i++) { ConvertToPaintPoint(selectedPoints[i], ref paintPoints[i]); } //Paint the points for (int i = 0; i < paintPoints.Length - 1; i++) { promptSave = true; PaintSegment(paintPoints[i], paintPoints[i + 1], ref drawLayer, ref alphaLayer); } SplineSample exResult = selectedPoints[0]; exResult.position += exResult.position - selectedPoints[1].position; TerrainPaintPoint exPoint = null; ConvertToPaintPoint(exResult, ref exPoint); PaintSegment(paintPoints[0], exPoint, ref drawLayer, ref alphaLayer, false, false); exResult = selectedPoints[selectedPoints.Count - 1]; exResult.position += exResult.position - selectedPoints[selectedPoints.Count - 2].position; ConvertToPaintPoint(exResult, ref exPoint); PaintSegment(paintPoints[paintPoints.Length - 1], exPoint, ref drawLayer, ref alphaLayer, false, false); //Extrapolate the ending and the begining }
/// <summary> /// Evaluates the spline segment and writes uniformly spaced results to the array /// </summary> /// <param name="from">Start position [0-1]</param> /// <param name="to">Target position [from-1]</param> /// <returns></returns> public void EvaluateUniform(ref SplineSample[] samples, ref double[] originalSamplePercents, double from = 0.0, double to = 1.0) { if (points.Length == 0) { samples = new SplineSample[0]; return; } from = DMath.Clamp01(from); to = DMath.Clamp(to, from, 1.0); double fromValue = from * (iterations - 1); double toValue = to * (iterations - 1); int clippedIterations = DMath.CeilInt(toValue) - DMath.FloorInt(fromValue) + 1; if (samples == null || samples.Length != clippedIterations) { samples = new SplineSample[clippedIterations]; } if (originalSamplePercents == null || originalSamplePercents.Length != clippedIterations) { originalSamplePercents = new double[clippedIterations]; } for (int i = 0; i < samples.Length; i++) { if (samples[i] == null) { samples[i] = new SplineSample(); } } float lengthStep = CalculateLength(from, to) / (iterations - 1); Evaluate(samples[0], from); samples[0].percent = originalSamplePercents[0] = from; double lastPercent = from; float moved = 0f; for (int i = 1; i < samples.Length - 1; i++) { Evaluate(samples[i], Travel(lastPercent, lengthStep, out moved, Direction.Forward)); lastPercent = samples[i].percent; originalSamplePercents[i] = lastPercent; samples[i].percent = DMath.Lerp(from, to, (double)i / (samples.Length - 1)); } Evaluate(samples[samples.Length - 1], to); samples[samples.Length - 1].percent = originalSamplePercents[originalSamplePercents.Length - 1] = to; }
void PaintHeightMap(Terrain terrain, SplineComputer computer, ref float[,] drawLayer, ref float[,] alphaLayer) { if (heights == null) { GetBase(); } SplineSample[] results = new SplineSample[computer.iterations]; computer.Evaluate(ref results, clipFrom, clipTo); /* * for(int i = 0; i < results.Length; i++) * { * float percent = (float)i/(results.Length-1); * results[i] = computer.Evaluate(percent); * } */ Draw(results, ref drawLayer, ref alphaLayer); }
/// <summary> /// Same as Spline.Evaluate but the result is transformed by the computer's transform /// </summary> /// <param name="result"></param> /// <param name="percent"></param> public void Evaluate(double percent, SplineSample result) { if (!hasSamples) { result = new SplineSample(); return; } int index; double lerp; GetSamplingValues(percent, out index, out lerp); if (lerp > 0.0) { SplineSample.Lerp(samples[index], samples[index + 1], lerp, result); } else { result.CopyFrom(samples[index]); } }
TerrainPaintPoint ConvertToPaintPoint(SplineSample result, ref TerrainPaintPoint paintPoint) { paintPoint = new TerrainPaintPoint(); Vector3 right = -Vector3.Cross(result.forward, result.up).normalized *size * 0.5f * result.size; Vector3 leftPoint = result.position - right + result.up * offset; Vector3 rightPoint = result.position + right + result.up * offset; paintPoint.center = ToHeightmapCoords(result.position + result.up * offset); paintPoint.leftPoint = ToHeightmapCoords(leftPoint); paintPoint.rightPoint = ToHeightmapCoords(rightPoint); paintPoint.leftHeight = ToHeightmapValue(leftPoint.y); paintPoint.rightHeight = ToHeightmapValue(rightPoint.y); paintPoint.floatDiameter = Vector2.Distance(new Vector2(leftPoint.x, leftPoint.z), new Vector2(rightPoint.x, rightPoint.z)); if (paintPoint.leftHeight > maxDrawHeight) { maxDrawHeight = paintPoint.leftHeight; } if (paintPoint.rightHeight > maxDrawHeight) { maxDrawHeight = paintPoint.rightHeight; } return(paintPoint); }
/// <summary> /// Evaluates the spline segment and writes the results to the array /// </summary> /// <param name="from">Start position [0-1]</param> /// <param name="to">Target position [from-1]</param> /// <returns></returns> public void Evaluate(ref SplineSample[] samples, double from = 0.0, double to = 1.0) { if (points.Length == 0) { samples = new SplineSample[0]; return; } from = DMath.Clamp01(from); to = DMath.Clamp(to, from, 1.0); double fromValue = from * (iterations - 1); double toValue = to * (iterations - 1); int clippedIterations = DMath.CeilInt(toValue) - DMath.FloorInt(fromValue) + 1; if (samples == null) { samples = new SplineSample[clippedIterations]; } else if (samples.Length != clippedIterations) { samples = new SplineSample[clippedIterations]; } double percent = from; double ms = moveStep; int index = 0; while (true) { samples[index] = Evaluate(percent); index++; if (index >= samples.Length) { break; } percent = DMath.Move(percent, to, ms); } }
/// <summary> /// Evaluate the splien at the given time and write the result to the "result" object /// </summary> /// <param name="result">The result output</param> /// <param name="percent">Percent of evaluation [0-1]</param> public void Evaluate(SplineSample result, double percent) { if (points.Length == 0) { result = new SplineSample(); return; } percent = DMath.Clamp01(percent); if (closed && points.Length <= 2) { closed = false; } if (points.Length == 1) { result.position = points[0].position; result.up = points[0].normal; result.forward = Vector3.forward; result.size = points[0].size; result.color = points[0].color; result.percent = percent; return; } double doubleIndex = (points.Length - 1) * percent; int pointIndex = Mathf.Clamp(DMath.FloorInt(doubleIndex), 0, points.Length - 2); double getPercent = doubleIndex - pointIndex; Vector3 point = EvaluatePosition(percent); result.position = point; result.percent = percent; if (pointIndex <= points.Length - 2) { SplinePoint nextPoint = points[pointIndex + 1]; if (pointIndex == points.Length - 2 && closed) { nextPoint = points[0]; } float valueInterpolation = (float)getPercent; if (customValueInterpolation != null) { if (customValueInterpolation.length > 0) { valueInterpolation = customValueInterpolation.Evaluate(valueInterpolation); } } float normalInterpolation = (float)getPercent; if (customNormalInterpolation != null) { if (customNormalInterpolation.length > 0) { normalInterpolation = customNormalInterpolation.Evaluate(normalInterpolation); } } result.size = Mathf.Lerp(points[pointIndex].size, nextPoint.size, valueInterpolation); result.color = Color.Lerp(points[pointIndex].color, nextPoint.color, valueInterpolation); result.up = Vector3.Slerp(points[pointIndex].normal, nextPoint.normal, normalInterpolation); } else { if (closed) { result.size = points[0].size; result.color = points[0].color; result.up = points[0].normal; } else { result.size = points[pointIndex].size; result.color = points[pointIndex].color; result.up = points[pointIndex].normal; } } if (type == Type.BSpline) { double step = 1.0 / (iterations - 1); if (percent <= 1.0 - step && percent >= step) { result.forward = EvaluatePosition(percent + step) - EvaluatePosition(percent - step); } else { Vector3 back = Vector3.zero, front = Vector3.zero; if (closed) { if (percent < step) { back = EvaluatePosition(1.0 - (step - percent)); } else { back = EvaluatePosition(percent - step); } if (percent > 1.0 - step) { front = EvaluatePosition(step - (1.0 - percent)); } else { front = EvaluatePosition(percent + step); } result.forward = front - back; } else { back = result.position - EvaluatePosition(percent - step); front = EvaluatePosition(percent + step) - result.position; result.forward = Vector3.Slerp(front, back, back.magnitude / front.magnitude); } } } else { EvaluateTangent(ref result.forward, percent); } result.forward.Normalize(); }
/// <summary> /// Evaluate the splien at the given point and write the result to the "result" object /// </summary> /// <param name="result">The result output</param> /// <param name="pointIndex">Point index</param> public void Evaluate(SplineSample result, int pointIndex) { Evaluate(result, GetPointPercent(pointIndex)); }
/// <summary> /// Same as Spline.Project but the point is transformed by the computer's transform. /// </summary> /// <param name="position">Point in space</param> /// <param name="subdivide">Subdivisions default: 4</param> /// <param name="from">Sample from [0-1] default: 0f</param> /// <param name="to">Sample to [0-1] default: 1f</param> /// <param name="mode">Mode to use the method in. Cached uses the cached samples while Calculate is more accurate but heavier</param> /// <param name="subdivisions">Subdivisions for the Calculate mode. Don't assign if not using Calculated mode.</param> /// <returns></returns> public void Project(Vector3 position, int controlPointCount, SplineSample result, double from = 0.0, double to = 1.0) { if (!hasSamples) { return; } if (Count == 1) { if (result == null) { result = new SplineSample(samples[0]); } else { result.CopyFrom(samples[0]); } return; } Spline.FormatFromTo(ref from, ref to); //First make a very rough sample of the from-to region int steps = (controlPointCount - 1) * 6; //Sampling six points per segment is enough to find the closest point range int step = Count / steps; if (step < 1) { step = 1; } float minDist = (position - samples[0].position).sqrMagnitude; int fromIndex = 0; int toIndex = Count - 1; double lerp; if (from != 0.0) { GetSamplingValues(from, out fromIndex, out lerp); } if (to != 1.0) { GetSamplingValues(to, out toIndex, out lerp); if (lerp > 0.0 && toIndex < Count - 1) { toIndex++; } } int checkFrom = fromIndex; int checkTo = toIndex; //Find the closest point range which will be checked in detail later for (int i = fromIndex; i <= toIndex; i += step) { if (i > toIndex) { i = toIndex; } float dist = (position - samples[i].position).sqrMagnitude; if (dist < minDist) { minDist = dist; checkFrom = Mathf.Max(i - step, 0); checkTo = Mathf.Min(i + step, Count - 1); } if (i == toIndex) { break; } } minDist = (position - samples[checkFrom].position).sqrMagnitude; int index = checkFrom; //Find the closest result within the range for (int i = checkFrom + 1; i <= checkTo; i++) { float dist = (position - samples[i].position).sqrMagnitude; if (dist < minDist) { minDist = dist; index = i; } } //Project the point on the line between the two closest samples int backIndex = index - 1; if (backIndex < 0) { backIndex = 0; } int frontIndex = index + 1; if (frontIndex > Count - 1) { frontIndex = Count - 1; } Vector3 back = LinearAlgebraUtility.ProjectOnLine(samples[backIndex].position, samples[index].position, position); Vector3 front = LinearAlgebraUtility.ProjectOnLine(samples[index].position, samples[frontIndex].position, position); float backLength = (samples[index].position - samples[backIndex].position).magnitude; float frontLength = (samples[index].position - samples[frontIndex].position).magnitude; float backProjectDist = (back - samples[backIndex].position).magnitude; float frontProjectDist = (front - samples[frontIndex].position).magnitude; if (backIndex < index && index < frontIndex) { if ((position - back).sqrMagnitude < (position - front).sqrMagnitude) { SplineSample.Lerp(samples[backIndex], samples[index], backProjectDist / backLength, result); if (sampleMode == SplineComputer.SampleMode.Uniform) { result.percent = DMath.Lerp(GetSamplePercent(backIndex), GetSamplePercent(index), backProjectDist / backLength); } } else { SplineSample.Lerp(samples[frontIndex], samples[index], frontProjectDist / frontLength, result); if (sampleMode == SplineComputer.SampleMode.Uniform) { result.percent = DMath.Lerp(GetSamplePercent(frontIndex), GetSamplePercent(index), frontProjectDist / frontLength); } } } else if (backIndex < index) { SplineSample.Lerp(samples[backIndex], samples[index], backProjectDist / backLength, result); if (sampleMode == SplineComputer.SampleMode.Uniform) { result.percent = DMath.Lerp(GetSamplePercent(backIndex), GetSamplePercent(index), backProjectDist / backLength); } } else { SplineSample.Lerp(samples[frontIndex], samples[index], frontProjectDist / frontLength, result); if (sampleMode == SplineComputer.SampleMode.Uniform) { result.percent = DMath.Lerp(GetSamplePercent(frontIndex), GetSamplePercent(index), frontProjectDist / frontLength); } } if (Count > 1 && from == 0.0 && to == 1.0 && result.percent < samples[1].percent) //Handle looped splines { Vector3 projected = LinearAlgebraUtility.ProjectOnLine(samples[Count - 1].position, samples[Count - 2].position, position); if ((position - projected).sqrMagnitude < (position - result.position).sqrMagnitude) { double l = LinearAlgebraUtility.InverseLerp(samples[Count - 1].position, samples[Count - 2].position, projected); SplineSample.Lerp(samples[Count - 1], samples[Count - 2], l, result); if (sampleMode == SplineComputer.SampleMode.Uniform) { result.percent = DMath.Lerp(GetSamplePercent(Count - 1), GetSamplePercent(Count - 2), l); } } } }
public void Lerp(SplineSample b, float t) { Lerp(this, b, t, this); }
public void Lerp(SplineSample b, double t) { Lerp(this, b, t, this); }