/// <summary> /// Modeled after quarter-cycle of sine wave /// </summary> public static float EaseInSine(this float This) { return(Math.Sin((This - 1) * HalfPi) + 1); }
/// <summary> /// Fill a texture with a signed distance field generated from the alpha channel of a source texture. /// </summary> /// <param name="source"> /// Source texture. Alpha values of 1 are considered inside, values of 0 are considered outside, and any other values /// are considered /// to be on the edge. Must be readable. /// </param> /// <param name="destination"> /// Destination texture. Must be the same size as the source texture. Must be readable. /// The texture change does not get applied automatically, you need to do that yourself. /// </param> /// <param name="maxInside"> /// Maximum pixel distance measured inside the edge, resulting in an alpha value of 1. /// If set to or below 0, everything inside will have an alpha value of 1. /// </param> /// <param name="maxOutside"> /// Maximum pixel distance measured outside the edge, resulting in an alpha value of 0. /// If set to or below 0, everything outside will have an alpha value of 0. /// </param> /// <param name="postProcessDistance"> /// Pixel distance from the edge within which pixels will be post-processed using the edge gradient. /// </param> /// <param name="rgbMode"> /// How to fill the destination texture's RGB channels. /// </param> public static void Generate( Image <Rgba32> source, Image <Rgba32> destination, float maxInside, float maxOutside, float postProcessDistance, RGBFillMode rgbMode) { if (source.Height != destination.Height || source.Width != destination.Width) { Logger.WriteErrorLine("Source and destination textures must be the same size."); return; } width = source.Width; height = source.Height; pixels = new Pixel[width, height]; int x, y; float scale; Rgba32 c = rgbMode == RGBFillMode.White ? Color.White : Color.Black; for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { pixels[x, y] = new Pixel(); } } if (maxInside > 0f) { for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { pixels[x, y].alpha = source.GetPixel(x, y).R / 255f; } } ComputeEdgeGradients(); GenerateDistanceTransform(); if (postProcessDistance > 0f) { PostProcess(postProcessDistance); } scale = 1f / maxInside; for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { c.A = (byte)(255f * Math.Clamp(pixels[x, y].distance * scale, 0, 1)); destination.SetPixel(x, y, c); } } } if (maxOutside > 0f) { for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { pixels[x, y].alpha = 1f - source.GetPixel(x, y).R / 255f; } } ComputeEdgeGradients(); GenerateDistanceTransform(); if (postProcessDistance > 0f) { PostProcess(postProcessDistance); } scale = 1f / maxOutside; if (maxInside > 0f) { for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { c.A = (byte)(255f * (0.5f + (destination.GetPixel(x, y).A / 255f - Math.Clamp(pixels[x, y].distance * scale, 0, 1)) * 0.5f)); destination.SetPixel(x, y, c); } } } else { for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { c.A = (byte)(255f * Math.Clamp(1f - pixels[x, y].distance * scale, 0, 1)); destination.SetPixel(x, y, c); } } } } if (rgbMode == RGBFillMode.Distance) { for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { c = destination.GetPixel(x, y); c.R = c.A; c.G = c.A; c.B = c.A; destination.SetPixel(x, y, c); } } } else if (rgbMode == RGBFillMode.Source) { for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { c = source.GetPixel(x, y); c.A = destination.GetPixel(x, y).A; destination.SetPixel(x, y, c); } } } pixels = null; }
/// <summary> /// Modeled after quarter-cycle of sine wave /// </summary> static internal float easeInSine(float p) { return(Math.Sin((p - 1) * HALFPI) + 1); }
/// <summary> /// Modeled after the damped sine wave y = sin(13pi/2*x)*Math.Pow(2, 10 * (x - 1)) /// </summary> public static float EaseInElastic(this float This) { return(Math.Sin(13 * HalfPi * This) * Math.Pow(2, 10 * (This - 1))); }
/// <summary> /// Modeled after the overshooting cubic y = x^3-x*sin(x*pi) /// </summary> public static float EaseInBack(this float This) { return(This * This * This - This * Math.Sin(This * Pi)); }
/// <summary> /// Modeled after shifted quadrant IV of unit circle /// </summary> public static float EaseInCircular(this float This) { return(1 - Math.Sqrt(1 - This * This)); }
/// <summary> /// Modeled after the exponential function y = 2^(10(x - 1)) /// </summary> public static float EaseInExponential(this float This) { return(This.IsAlmostZero() ? This : Math.Pow(2, 10 * (This - 1))); }
/// <summary> /// Modeled after the expo function y = -2^(-10x) + 1 /// </summary> static internal float easeOutExpo(float p) { return((p == 1.0f) ? p : 1 - Math.Pow(2, -10 * p)); }
/// <summary> /// Modeled after the damped sine wave y = sin(13pi/2*x)*Math.Pow(2, 10 * (x - 1)) /// </summary> static internal float easeInElastic(float p) { return(Math.Sin(13 * HALFPI * p) * Math.Pow(2, 10 * (p - 1))); }
/// <summary> /// Modeled after shifted quadrant II of unit circle /// </summary> static internal float easeOutCirc(float p) { return(Math.Sqrt((2 - p) * p)); }
/// <summary> /// Modeled after the expo function y = 2^(10(x - 1)) /// </summary> static internal float easeInExpo(float p) { return((p == 0.0f) ? p : Math.Pow(2, 10 * (p - 1))); }
/// <summary> /// Modeled after shifted quadrant IV of unit circle /// </summary> static internal float easeInCirc(float p) { return(1 - Math.Sqrt(1 - (p * p))); }
/// <summary> /// Modeled after half sine wave /// </summary> static internal float easeInOutSine(float p) { return(0.5f * (1 - Math.Cos(p * PI))); }
/// <summary> /// Modeled after quarter-cycle of sine wave (different phase) /// </summary> static internal float easeOutSine(float p) { return(Math.Sin(p * HALFPI)); }
/// <summary> /// Modeled after quarter-cycle of sine wave (different phase) /// </summary> public static float EaseOutSine(this float This) { return(Math.Sin(This * HalfPi)); }
/// <summary> /// Modeled after the damped sine wave y = sin(-13pi/2*(x + 1))*Math.Pow(2, -10x) + 1 /// </summary> static internal float easeOutElastic(float p) { return(Math.Sin(-13 * HALFPI * (p + 1)) * Math.Pow(2, -10 * p) + 1); }
/// <summary> /// Modeled after half sine wave /// </summary> public static float EaseInOutSine(this float This) { return(0.5f * (1 - Math.Cos(This * Pi))); }
/// <summary> /// Modeled after the overshooting cubic y = x^3-x*sin(x*pi) /// </summary> static internal float easeInBack(float p) { return(p * p * p - p * Math.Sin(p * PI)); }
/// <summary> /// Modeled after shifted quadrant II of unit circle /// </summary> public static float EaseOutCircular(this float This) { return(Math.Sqrt((2 - This) * This)); }
/// <summary> /// Modeled after overshooting cubic y = 1-((1-x)^3-(1-x)*sin((1-x)*pi)) /// </summary> static internal float easeOutBack(float p) { float f = (1 - p); return(1 - (f * f * f - f * Math.Sin(f * PI))); }
/// <summary> /// Modeled after the exponential function y = -2^(-10x) + 1 /// </summary> public static float EaseOutExponential(this float This) { return(This.IsAlmostEqualTo(1f) ? This : 1 - Math.Pow(2, -10 * This)); }
public static float CalcInnerDiameter(float outerDiameter, float tubeWidth) { var innerDiameter = outerDiameter - (tubeWidth * 2); return(Mathf.Max(0, innerDiameter)); }
/// <summary> /// Modeled after the damped sine wave y = sin(-13pi/2*(x + 1))*Math.Pow(2, -10x) + 1 /// </summary> public static float EaseOutElastic(this float This) { return(Math.Sin(-13 * HalfPi * (This + 1)) * Math.Pow(2, -10 * This) + 1); }
public static float CalcTubeWidth(float outerDiameter, float innerDiameter) { var tubeWidth = (outerDiameter - innerDiameter) * 0.5f; return(Mathf.Max(kMinTubeDiameter, tubeWidth)); }
/// <summary> /// Modeled after overshooting cubic y = 1-((1-x)^3-(1-x)*sin((1-x)*pi)) /// </summary> public static float EaseOutBack(this float This) { var f = 1 - This; return(1 - (f * f * f - f * Math.Sin(f * Pi))); }
internal static void Interpolate(JToken a, JToken b, float linearT, ref JToken mix, CubicBezier easing) { var easedT = easing.Sample(linearT); // compound types if (a.Type == JTokenType.Object) { JObject A = (JObject)a; JObject B = (JObject)b; JObject Mix = (JObject)mix; if (A.ContainsKey("x") && A.ContainsKey("y")) { if (A.ContainsKey("z")) { // quaternion if (A.ContainsKey("w")) { tempA.Set(A.ForceFloat("x"), A.ForceFloat("y"), A.ForceFloat("z"), A.ForceFloat("w")); tempB.Set(B.ForceFloat("x"), B.ForceFloat("y"), B.ForceFloat("z"), B.ForceFloat("w")); tempMix = Quaternion.Slerp(tempA, tempB, easedT); Mix.SetOrAdd("x", tempMix.x); Mix.SetOrAdd("y", tempMix.y); Mix.SetOrAdd("z", tempMix.z); Mix.SetOrAdd("w", tempMix.w); } // Vector3 else { Mix.SetOrAdd("x", UnityMath.Lerp(A.ForceFloat("x"), B.ForceFloat("x"), easedT)); Mix.SetOrAdd("y", UnityMath.Lerp(A.ForceFloat("y"), B.ForceFloat("y"), easedT)); Mix.SetOrAdd("z", UnityMath.Lerp(A.ForceFloat("z"), B.ForceFloat("z"), easedT)); } } // Vector2 else { Mix.SetOrAdd("x", UnityMath.Lerp(A.ForceFloat("x"), B.ForceFloat("x"), easedT)); Mix.SetOrAdd("y", UnityMath.Lerp(A.ForceFloat("y"), B.ForceFloat("y"), easedT)); } } // TODO: other compound types (color3, color4) } // simple types else { JValue A = (JValue)a; JValue B = (JValue)b; JValue Mix = (JValue)mix; // numeric types if (a.Type == JTokenType.Float || a.Type == JTokenType.Integer) { Mix.Value = UnityMath.Lerp(A.ForceFloat(), B.ForceFloat(), easedT); } // no interpolation available, just use A else { Mix.Value = A.Value; } } }
static void WriteBackInstance(ILRuntime.Runtime.Enviorment.AppDomain __domain, StackObject *ptr_of_this_method, IList <object> __mStack, ref UnityEngine.Mathf instance_of_this_method) { ptr_of_this_method = ILIntepreter.GetObjectAndResolveReference(ptr_of_this_method); switch (ptr_of_this_method->ObjectType) { case ObjectTypes.Object: { __mStack[ptr_of_this_method->Value] = instance_of_this_method; } break; case ObjectTypes.FieldReference: { var ___obj = __mStack[ptr_of_this_method->Value]; if (___obj is ILTypeInstance) { ((ILTypeInstance)___obj)[ptr_of_this_method->ValueLow] = instance_of_this_method; } else { var t = __domain.GetType(___obj.GetType()) as CLRType; t.SetFieldValue(ptr_of_this_method->ValueLow, ref ___obj, instance_of_this_method); } } break; case ObjectTypes.StaticFieldReference: { var t = __domain.GetType(ptr_of_this_method->Value); if (t is ILType) { ((ILType)t).StaticInstance[ptr_of_this_method->ValueLow] = instance_of_this_method; } else { ((CLRType)t).SetStaticFieldValue(ptr_of_this_method->ValueLow, instance_of_this_method); } } break; case ObjectTypes.ArrayReference: { var instance_of_arrayReference = __mStack[ptr_of_this_method->Value] as UnityEngine.Mathf[]; instance_of_arrayReference[ptr_of_this_method->ValueLow] = instance_of_this_method; } break; } }
public static bool GeneratePathedStairs(ref ChiselBrushContainer brushContainer, ref ChiselPathedStairsDefinition definition) { definition.Validate(); var shapeVertices = new List <Vector2>(); var shapeSegmentIndices = new List <int>(); GetPathVertices(definition.shape, definition.curveSegments, shapeVertices, shapeSegmentIndices); var totalSubMeshCount = 0; for (int i = 0; i < shapeVertices.Count; i++) { if (i == 0 && !definition.shape.closed) { continue; } var leftSide = (!definition.shape.closed && i == 1) ? definition.stairs.leftSide : StairsSideType.None; var rightSide = (!definition.shape.closed && i == shapeVertices.Count - 1) ? definition.stairs.rightSide : StairsSideType.None; totalSubMeshCount += BrushMeshFactory.GetLinearStairsSubMeshCount(definition.stairs, leftSide, rightSide); } if (totalSubMeshCount == 0) { return(false); } // var stairDirections = definition.shape.closed ? shapeVertices.Count : (shapeVertices.Count - 1); brushContainer.EnsureSize(totalSubMeshCount); var depth = definition.stairs.absDepth; var height = definition.stairs.absHeight; var halfDepth = depth * 0.5f; var halfHeight = height * 0.5f; int subMeshIndex = 0; for (int vi0 = shapeVertices.Count - 3, vi1 = shapeVertices.Count - 2, vi2 = shapeVertices.Count - 1, vi3 = 0; vi3 < shapeVertices.Count; vi0 = vi1, vi1 = vi2, vi2 = vi3, vi3++) { if (vi2 == 0 && !definition.shape.closed) { continue; } // TODO: optimize this, we're probably redoing a lot of stuff for every iteration var v0 = shapeVertices[vi0]; var v1 = shapeVertices[vi1]; var v2 = shapeVertices[vi2]; var v3 = shapeVertices[vi3]; var m0 = (v0 + v1) * 0.5f; var m1 = (v1 + v2) * 0.5f; var m2 = (v2 + v3) * 0.5f; var d0 = (v1 - v0); var d1 = (v2 - v1); var d2 = (v3 - v2); var maxWidth0 = d0.magnitude; var maxWidth1 = d1.magnitude; var maxWidth2 = d2.magnitude; var halfWidth1 = d1 * 0.5f; d0 /= maxWidth0; d1 /= maxWidth1; d2 /= maxWidth2; var depthVector = new Vector3(d1.y, 0, -d1.x); var lineCenter = new Vector3(m1.x, halfHeight, m1.y) - (depthVector * halfDepth); var depthVector0 = new Vector2(d0.y, -d0.x) * depth; var depthVector1 = new Vector2(d1.y, -d1.x) * depth; var depthVector2 = new Vector2(d2.y, -d2.x) * depth; m0 -= depthVector0; m1 -= depthVector1; m2 -= depthVector2; Vector2 output; var leftShear = Intersect(m1, d1, m0, d0, out output) ? Vector2.Dot(d1, (output - (m1 - halfWidth1))) : 0; var rightShear = Intersect(m1, d1, m2, d2, out output) ? -Vector2.Dot(d1, (output - (m1 + halfWidth1))) : 0; var transform = Matrix4x4.TRS(lineCenter, // move to center of line Quaternion.LookRotation(depthVector, Vector3.up), // rotate to align with line Vector3.one); // set the width to the width of the line definition.stairs.width = maxWidth1 * (definition.stairs.width < 0 ? -1 : 1); definition.stairs.nosingWidth = 0; var leftSide = (!definition.shape.closed && vi2 == 1) ? definition.stairs.leftSide : StairsSideType.None; var rightSide = (!definition.shape.closed && vi2 == shapeVertices.Count - 1) ? definition.stairs.rightSide : StairsSideType.None; var subMeshCount = BrushMeshFactory.GetLinearStairsSubMeshCount(definition.stairs, leftSide, rightSide); if (subMeshCount == 0) { continue; } if (!BrushMeshFactory.GenerateLinearStairsSubMeshes(ref brushContainer, definition.stairs, leftSide, rightSide, subMeshIndex)) { return(false); } var halfWidth = maxWidth1 * 0.5f; for (int m = 0; m < subMeshCount; m++) { var vertices = brushContainer.brushMeshes[subMeshIndex + m].vertices; for (int v = 0; v < vertices.Length; v++) { // TODO: is it possible to put all of this in a single matrix? // lerp the stairs to go from less wide to wider depending on the depth of the vertex var depthFactor = 1.0f - ((vertices[v].z / depth) + 0.5f); var wideFactor = (vertices[v].x / halfWidth) + 0.5f; var scale = (vertices[v].x / halfWidth); // lerp the stairs width depending on if it's on the left or right side of the stairs vertices[v].x = Mathf.Lerp(scale * (halfWidth - (rightShear * depthFactor)), scale * (halfWidth - (leftShear * depthFactor)), wideFactor); vertices[v] = transform.MultiplyPoint(vertices[v]); } } subMeshIndex += subMeshCount; } return(false); }