예제 #1
0
 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)
                ));
 }
예제 #2
0
    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);
        }
    }
예제 #3
0
        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;
        }
예제 #4
0
    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;
        };
    }
예제 #5
0
    // 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);
    }
예제 #6
0
    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);
    }
예제 #7
0
    // 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);
        }
    }
예제 #8
0
        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);
            }
        }
예제 #9
0
        public void PopFromStart()
        {
            ValueTransform popped = Path.Dequeue();

            OnPopFromStart?.Invoke(popped);
        }
예제 #10
0
 public void PushToEnd(ValueTransform dest)
 {
     Path.Enqueue(dest);
     RingsAdded++;
 }
예제 #11
0
 public void Grow(ValueTransform ring) {
     GrowBaseMesh(ring);
     UpdateHeadPatch(ring);
 }