public static ValueTransform lerp(ValueTransform start, ValueTransform end, float factor) { return(new ValueTransform( Vector3.LerpUnclamped(start.position, end.position, factor), Quaternion.LerpUnclamped(start.rotation, end.rotation, factor) )); }
public void ShrinkToLength(float targetLength) { // Base mesh { // How many rings to remove float headPatchLength = GetPatchLength(headPatch); int targetRings = (int)((targetLength - headPatchLength) / interval) + 1; // Leave at least one ring targetRings = Mathf.Max(targetRings, 1); while (snakeMesh.Count > targetRings) snakeMesh.PopFromStart(); } // Tail position { float tailPatchLength = targetLength - GetPatchLength(headPatch) - baseLength; float factor = tailPatchLength / interval; ValueTransform tailRing = ValueTransform.lerp(snakeMesh.Kernel.Path[0], lastPoppedRing, factor); tailRing.SetTransform(tail); UpdateTailPatch(tailRing); // UV offset float distanceTraveled = baseDistanceTraveled - baseLength - tailPatchLength; baseTailOffset = tailMaterial.GetUnscaledTextureOffset(); baseTailOffset.y = distanceTraveled / snakeMesh.RingLength; tailMaterial.SetUnscaledTextureOffset(baseTailOffset); } }
public void PushToEnd(ValueTransform ring, float distanceTraveled) { kernel.PushToEnd(ring); // Vertices and normals for (int i = 0; i < RealPointsPerRing; ++i) { float angle = (2 * Mathf.PI) * i / visiblePointsPerRing; var normal = new Vector3(Mathf.Cos(angle), Mathf.Sin(angle)); normal = ring.rotation * normal; Vector3 vertex = normal * radius + ring.position; Vector2 uv = new Vector2(); uv.x = 0.75f - (float)i / visiblePointsPerRing; uv.y = distanceTraveled / RingLength; vertices.Enqueue(vertex); normals.Enqueue(normal); uvs.Enqueue(uv); #if UNITY_EDITOR UpdateVertexDebugInfo(vertices.Count - 1); #endif } AddSegmentTriangles(); meshIsDirty = true; }
public void Init() { snakeMesh = snakeMesh_ as ISnakeMesh; Assert.IsNotNull(snakeMesh); headPatch = InitPatch("Head Patch"); tailPatch = InitPatch("Tail Patch"); tailMaterial = tail.GetChild(0).GetRequiredComponent<MeshRenderer>().material; // Add first ring // TODO: replace by more sane mechanism (incorrect ring here) { ValueTransform ring = new ValueTransform(tail); GrowBaseMesh(ring, true); lastPoppedRing = ring; float distanceTraveled = 0; headPatch.PushToEnd(ring, distanceTraveled); headPatch.PushToEnd(ring, distanceTraveled); tailPatch.PushToEnd(ring, distanceTraveled); tailPatch.PushToEnd(ring, distanceTraveled); } snakeMesh.Kernel.OnPopFromStart += (ring) => { lastPoppedRing = ring; }; }
// TODO: remove duplicate code in UpdateHeadPatch() and UpdateTailPatch() private void UpdateHeadPatch(ValueTransform headRing) { headPatch.PopFromStart(); headPatch.PopFromStart(); ValueTransform baseRing = snakeMesh.Kernel.Path.Last; float patchLength = (headRing.position - baseRing.position).magnitude; headPatch.PushToEnd(baseRing, baseDistanceTraveled); headPatch.PushToEnd(headRing, baseDistanceTraveled + patchLength); }
private void UpdateTailPatch(ValueTransform tailRing) { tailPatch.PopFromStart(); tailPatch.PopFromStart(); ValueTransform baseRing = snakeMesh.Kernel.Path[0]; float baseDistance = baseDistanceTraveled - baseLength; float tailPatchLength = (tailRing.position - baseRing.position).magnitude; tailPatch.PushToEnd(tailRing, baseDistance - tailPatchLength); tailPatch.PushToEnd(baseRing, baseDistance); }
// Grows base mesh if needed in current frame. // // TODO: remove "force" argument private void GrowBaseMesh(ValueTransform ring, bool force = false) { Vector3 lastGrowPoint; if (force) lastGrowPoint = ring.position; else lastGrowPoint = snakeMesh.Kernel.Path.Last.position; Vector3 delta = ring.position - lastGrowPoint; if (delta.magnitude >= interval || force) { // Grow //lastGrowPoint += delta.normalized * interval; float distanceTraveled = baseDistanceTraveled + interval; snakeMesh.PushToEnd(ring, distanceTraveled); } }
public void Grow(ValueTransform value, bool force = false) { // TEST; TODO: remove float distance = 0; if (intPath.Size == 0) { force = true; } else { distance = (value.position - intPath.Last.position).magnitude; } if (force || distance >= interval) { intPath.PushToEnd(value); } }
public void PopFromStart() { ValueTransform popped = Path.Dequeue(); OnPopFromStart?.Invoke(popped); }
public void PushToEnd(ValueTransform dest) { Path.Enqueue(dest); RingsAdded++; }
public void Grow(ValueTransform ring) { GrowBaseMesh(ring); UpdateHeadPatch(ring); }