示例#1
0
        public static SpriteSet Trail(StoryboardLayer layer, OsbSprite sprite, double startTime, double endTime, double timeBetweenSprites, double fadeInTime, double duration, double fadeOutTime, bool cutWhenSpriteDisappears)
        {
            SpriteSet trail = layer.CreateSpriteSet();

            for (double t = startTime; t < endTime; t += timeBetweenSprites)
            {
                if (sprite.OpacityAt(t) == 0)
                {
                    continue;
                }
                var    trailSprite = layer.CreateSprite(sprite.TexturePath, OsbOrigin.Centre, sprite.PositionAt(t));
                double s           = fadeInTime;
                double d           = duration;
                double e           = fadeOutTime;
                double up          = sprite.OpacityAt(t);
                double down        = 0;
                if (cutWhenSpriteDisappears)
                {
                    if (sprite.CommandsEndTime <= t + fadeInTime)
                    { // sprite doesn't get to fade in fully
                        s  = sprite.CommandsEndTime - t;
                        up = InterpolatingFunctions.Double(0, up, (sprite.CommandsEndTime - t) / (t + fadeInTime));
                    }
                    else if (sprite.CommandsEndTime <= t + fadeInTime + duration)
                    { // sprite doesn't get to fade out
                        d = sprite.CommandsEndTime - (t + fadeInTime);
                        e = 0;
                    }
                    else if (sprite.CommandsEndTime <= t + fadeInTime + duration + fadeOutTime)
                    { // sprite doesn't get to fade out fully
                        e    = sprite.CommandsEndTime - (t + fadeInTime + duration);
                        down = InterpolatingFunctions.Double(up, 0, (sprite.CommandsEndTime - (t + fadeInTime + duration)) / (fadeOutTime));
                    }
                }
                if (s == 0 && e == 0)
                {
                    trailSprite.Fade(t, t + d, 1, 1);
                }
                else
                {
                    if (s != 0 && d != 0)
                    {
                        trailSprite.Fade(t, t + s, 0, up);
                    }
                    if (e != 0)
                    {
                        trailSprite.Fade(t + d, t + d + e, up, down);
                    }
                }
                trail.AddSprite(trailSprite);
            }
            return(trail);
        }
示例#2
0
        public override void GenerateStates(double time, CameraState cameraState, Object3dState object3dState)
        {
            var wvp            = object3dState.WorldTransform * cameraState.ViewProjection;
            var screenPosition = cameraState.ToScreen(wvp, Vector3.Zero);

            var angle = 0.0;

            switch (RotationMode)
            {
            case RotationMode.UnitX:
            {
                var unitXPosition = cameraState.ToScreen(wvp, Vector3.UnitX);
                var delta         = unitXPosition - screenPosition;
                angle += (float)Math.Atan2(delta.Y, delta.X);
            }
            break;

            case RotationMode.UnitY:
            {
                var unitYPosition = cameraState.ToScreen(wvp, Vector3.UnitY);
                var delta         = unitYPosition - screenPosition;
                angle += (float)Math.Atan2(delta.Y, delta.X) - Math.PI * 0.5;
            }
            break;
            }

            var previousState = Generator.EndState;
            var rotation      = InterpolatingFunctions.DoubleAngle(previousState?.Rotation ?? 0 - SpriteRotation.ValueAt(previousState?.Time ?? time), angle, 1) + SpriteRotation.ValueAt(time);

            var scale = SpriteScale.ValueAt(time)
                        * object3dState.WorldTransform.ExtractScale().Xy
                        *(float)(cameraState.FocusDistance / screenPosition.W)
                        * (float)cameraState.ResolutionScale;

            var opacity = screenPosition.W < 0 ? 0 : object3dState.Opacity;

            if (UseDistanceFade)
            {
                opacity *= cameraState.OpacityAt(screenPosition.W);
            }

            Generator.Add(new CommandGenerator.State()
            {
                Time     = time,
                Position = screenPosition.Xy,
                Scale    = scale,
                Rotation = rotation,
                Color    = object3dState.Color,
                Opacity  = opacity,
                Additive = Additive,
            });
        }
示例#3
0
        public override void GenerateStates(double time, CameraState cameraState, Object3dState object3dState)
        {
            var wvp         = object3dState.WorldTransform * cameraState.ViewProjection;
            var startVector = cameraState.ToScreen(wvp, StartPosition.ValueAt(time));
            var endVector   = cameraState.ToScreen(wvp, EndPosition.ValueAt(time));

            var delta  = endVector.Xy - startVector.Xy;
            var length = delta.Length;

            if (length == 0)
            {
                return;
            }

            var angle    = Math.Atan2(delta.Y, delta.X);
            var rotation = InterpolatingFunctions.DoubleAngle(GeneratorBody.EndState?.Rotation ?? 0, angle, 1);

            var thickness   = Thickness.ValueAt(time);
            var scaleFactor = object3dState.WorldTransform.ExtractScale().Y *(float)cameraState.ResolutionScale;
            var startScale  = scaleFactor * (float)(cameraState.FocusDistance / startVector.W) * thickness * StartThickness.ValueAt(time);
            var endScale    = scaleFactor * (float)(cameraState.FocusDistance / endVector.W) * thickness * EndThickness.ValueAt(time);

            var totalHeight = Math.Max(startScale, endScale);
            var bodyHeight  = Math.Min(startScale, endScale);
            var edgeHeight  = (totalHeight - bodyHeight) * 0.5f;
            var flip        = startScale < endScale;

            var ignoreEdges = edgeHeight < EdgeOverlap;

            if (ignoreEdges)
            {
                bodyHeight += edgeHeight * 2;
            }

            var opacity = startVector.W < 0 && endVector.W < 0 ? 0 : object3dState.Opacity;

            if (UseDistanceFade)
            {
                opacity *= Math.Max(cameraState.OpacityAt(startVector.W), cameraState.OpacityAt(endVector.W));
            }

            // Body

            var bitmapBody = StoryboardObjectGenerator.Current.GetMapsetBitmap(spriteBody.GetTexturePathAt(time));
            var bodyScale  = new Vector2(length / bitmapBody.Width, bodyHeight / bitmapBody.Height);

            var positionBody = startVector.Xy + delta * 0.5f;
            var bodyOpacity  = opacity;

            GeneratorBody.Add(new CommandGenerator.State()
            {
                Time     = time,
                Position = positionBody,
                Scale    = bodyScale,
                Rotation = rotation,
                Color    = object3dState.Color,
                Opacity  = bodyOpacity,
                Additive = Additive,
            });

            // Edges

            if (SpritePathEdge != null)
            {
                var bitmapEdge = StoryboardObjectGenerator.Current.GetMapsetBitmap(spriteTopEdge.GetTexturePathAt(time));
                var edgeScale  = new Vector2(length / bitmapEdge.Width, edgeHeight / bitmapEdge.Height);

                var edgeOffset     = new Vector2((float)Math.Cos(angle - Math.PI * 0.5), (float)Math.Sin(angle - Math.PI * 0.5)) * (bodyHeight * 0.5f - EdgeOverlap);
                var positionTop    = positionBody + edgeOffset;
                var positionBottom = positionBody - edgeOffset;

                var edgeOpacity = ignoreEdges ? 0 : opacity;

                GeneratorTopEdge.Add(new CommandGenerator.State()
                {
                    Time     = time,
                    Position = positionTop,
                    Scale    = edgeScale,
                    Rotation = rotation,
                    Color    = object3dState.Color,
                    Opacity  = edgeOpacity,
                    FlipH    = flip,
                    Additive = Additive,
                });
                GeneratorBottomEdge.Add(new CommandGenerator.State()
                {
                    Time     = time,
                    Position = positionBottom,
                    Scale    = edgeScale,
                    Rotation = rotation,
                    Color    = object3dState.Color,
                    Opacity  = edgeOpacity,
                    Additive = Additive,
                    FlipH    = flip,
                    FlipV    = true,
                });
            }

            // Caps

            if (SpritePathCap != null)
            {
                var bitmapCap     = StoryboardObjectGenerator.Current.GetMapsetBitmap(spriteStartCap.GetTexturePathAt(time));
                var startCapScale = new Vector2(startScale / bitmapCap.Width, startScale / bitmapCap.Height);
                var endCapScale   = new Vector2(endScale / bitmapCap.Width, endScale / bitmapCap.Height);

                var capOffset = OrientedCaps ? new Vector2((float)Math.Cos(angle), (float)Math.Sin(angle)) * CapOverlap : Vector2.Zero;

                if (OrientedCaps)
                {
                    startCapScale.X *= 0.5f;
                    endCapScale.X   *= 0.5f;
                }

                var startCapOpacity = startScale > 0.5f ? opacity : 0;
                var endCapOpacity   = endScale > 0.5f ? opacity : 0;

                GeneratorStartCap.Add(new CommandGenerator.State()
                {
                    Time     = time,
                    Position = startVector.Xy + capOffset,
                    Scale    = startCapScale,
                    Rotation = OrientedCaps ? rotation + Math.PI : 0,
                    Color    = object3dState.Color,
                    Opacity  = startCapOpacity,
                    Additive = Additive,
                });
                GeneratorEndCap.Add(new CommandGenerator.State()
                {
                    Time     = time,
                    Position = endVector.Xy - capOffset,
                    Scale    = endCapScale,
                    Rotation = OrientedCaps ? rotation + Math.PI : 0,
                    Color    = object3dState.Color,
                    Opacity  = endCapOpacity,
                    Additive = Additive,
                    FlipH    = OrientedCaps,
                });
            }
        }
示例#4
0
        public override void GenerateStates(double time, CameraState cameraState, Object3dState object3dState)
        {
            var wvp         = object3dState.WorldTransform * cameraState.ViewProjection;
            var startVector = cameraState.ToScreen(wvp, StartPosition.ValueAt(time));
            var endVector   = cameraState.ToScreen(wvp, EndPosition.ValueAt(time));

            var delta  = endVector.Xy - startVector.Xy;
            var length = delta.Length;

            if (length == 0)
            {
                return;
            }

            var angle    = Math.Atan2(delta.Y, delta.X);
            var rotation = InterpolatingFunctions.DoubleAngle(Generator.EndState?.Rotation ?? 0, angle, 1);

            var bitmap = StoryboardObjectGenerator.Current.GetMapsetBitmap(sprite.GetTexturePathAt(time));
            var scale  = new Vector2(length / bitmap.Width, Thickness.ValueAt(time));

            var opacity = startVector.W < 0 && endVector.W < 0 ? 0 : object3dState.Opacity;

            if (UseDistanceFade)
            {
                opacity *= Math.Max(cameraState.OpacityAt(startVector.W), cameraState.OpacityAt(endVector.W));
            }

            Vector2 position;

            switch (sprite.Origin)
            {
            default:
            case OsbOrigin.TopLeft:
            case OsbOrigin.CentreLeft:
            case OsbOrigin.BottomLeft:
                position = startVector.Xy;
                break;

            case OsbOrigin.TopCentre:
            case OsbOrigin.Centre:
            case OsbOrigin.BottomCentre:
                position = startVector.Xy + delta * 0.5f;
                break;

            case OsbOrigin.TopRight:
            case OsbOrigin.CentreRight:
            case OsbOrigin.BottomRight:
                position = endVector.Xy;
                break;
            }

            Generator.Add(new CommandGenerator.State()
            {
                Time     = time,
                Position = position,
                Scale    = scale,
                Rotation = rotation,
                Color    = object3dState.Color,
                Opacity  = opacity,
                Additive = Additive,
            });
        }
示例#5
0
        void Section4_1()
        {
            // circle
            int   s    = 62840;
            int   e    = 63468;
            float fade = 1;

            layer      = GetLayer("");
            maskLayer  = GetLayer("masks");
            maskLayer2 = GetLayer("masks2");
            var downwardsMovement = new Movement(OsbEasing.OutExpo, s, e, Vectors.Centre + Vectors.up(100), Vectors.Centre);

            var ring1     = maskLayer2.CreateSprite(Sprites.Circle, OsbOrigin.Centre, downwardsMovement.StartPosition);
            var ring1Mask = maskLayer2.CreateSprite(Sprites.Circle, OsbOrigin.Centre, downwardsMovement.StartPosition);

            int   circleWidth   = GetMapsetBitmap(Sprites.Circle).Width;
            float width         = 350.0f;
            float width2        = 250.0f;
            float scale         = width / circleWidth;
            float thickness     = 10;
            float lineThickness = thickness * 0.71f;
            float maskScale     = (width - thickness * 2) / circleWidth / scale;

            ring1.Fade(s, e, fade, fade);
            ring1.Scale(OsbEasing.OutExpo, s, e - Timing.beat(s), scale, scale / width * width2);
            ring1.Move(downwardsMovement);

            ring1Mask.Fade(s, e, 1, 1);
            ring1Mask.Color(s, Color4.Black); ring1Mask.Scale(OsbEasing.OutExpo, s, e - Timing.beat(s), scale * maskScale, scale * maskScale / width * width2);
            ring1Mask.Move(downwardsMovement);

            // 3d ring
            float startOfRotation = e - 1.25f * (float)Timing.beat(s);
            var   inOutExpo       = OsbEasing.InOutExpo.ToEasingFunction();
            var   outExpo         = OsbEasing.OutExpo.ToEasingFunction();
            Func <float, float, Vector3> moving3DCircle = (float t, float time) =>
            {
                float   tilt   = time < startOfRotation ? 0 : (float)inOutExpo((time - startOfRotation) / (e - startOfRotation));
                Vector3 centre = downwardsMovement.PositionAtTime(time).withZ(0);
                float   radius = (MathHelper.Clamp(
                                      InterpolatingFunctions.Float(width, width2, outExpo((time - s) / (e - Timing.beat(s) - s))),
                                      width2, width
                                      ) - thickness) / 2;

                Vector3 rot1 = new Vector3(
                    5 * (float)Math.PI / 16,
                    (float)Math.PI / 2,
                    0
                    );

                Vector3 rot2 = new Vector3(
                    5 * (float)Math.PI / 16,
                    (float)Math.PI / 4,
                    0
                    );

                Vector3 rot = Vector3.Lerp(rot1, rot2, tilt);

                var res = radius * new Vector3(
                    (float)Math.Cos(-t),
                    (float)Math.Sin(-t),
                    0
                    ).rotateX(rot.X).rotateY(rot.Y).rotateZ(rot.Z) + centre;
                return(res);
            };

            int   count    = 200;
            float dotScale = lineThickness / circleWidth;

            for (int i = 0; i < count; i++)
            {
                var sprite = layer.CreateSprite(Sprites.Circle, OsbOrigin.Centre);
                sprite.Fade(s, e, 1, 1);
                for (float t = s; t < e; t += delta)
                {
                    float t2 = t + delta < e ? t + delta : e;

                    Vector3 p1 = moving3DCircle(
                        i * 2 * (float)Math.PI / count,
                        t
                        );

                    Vector3 p2 = moving3DCircle(
                        i * 2 * (float)Math.PI / count,
                        t2
                        );

                    sprite.Move3D(
                        OsbEasing.None,
                        t, t2,
                        p1, p2,
                        FOV,
                        (_sprite, _p1, _p2) =>
                    {
                        float scale1 = dotScale / _p1.normalisedVector.Length;
                        float scale2 = dotScale / _p2.normalisedVector.Length;
                        if (scale1 != scale2)
                        {
                            _sprite.Scale(t, t2, scale1, scale2);
                        }
                    }
                        );
                }
            }

            // dotted line through the sphere
            count = 35;
            float opacity             = 1;
            float lineAppearStart     = s + (float)Timing.beat(s) / 3;
            float appearDelay         = (float)Timing.beat(s) / 2 / count;
            float length              = width2 + 2 * 70;
            float dottedLineThickness = 1.2f;

            SpriteSet axisDottedLine = maskLayer.CreateSpriteSet(
                Sprites.Pixel,
                _ => OsbOrigin.TopCentre,
                Patterns.Line2D(Vectors.Centre + Vectors.up(length / 2), Vectors.Centre + Vectors.down(length / 2), count),
                count
                );

            var dotMovement = new Movement(OsbEasing.OutQuint, s + Timing.beat(s) / 3, e, Vectors.Centre + Vectors.up(100), Vectors.Centre);

            axisDottedLine.MoveRelative(dotMovement - Vectors.Centre);
            axisDottedLine.ScaleVec((int)lineAppearStart, new Vector2(dottedLineThickness, length / count / 2));

            axisDottedLine.Fade(
                OsbEasing.None,
                i => lineAppearStart + i * appearDelay,
                i => lineAppearStart + i * appearDelay + 100,
                0, opacity
                );
            axisDottedLine.Fade(e, 0);

            SpriteSet gradientMask = maskLayer.CreateSpriteSet(Sprites.TransparentGradient, _ => OsbOrigin.CentreRight, 2);

            gradientMask.Rotate(lineAppearStart, i => Math.PI / 2 + i * Math.PI);
            float gradientWidth = GetMapsetBitmap(Sprites.TransparentGradient).Width;

            gradientMask.ScaleVec(lineAppearStart, new Vector2(length / 2 / gradientWidth, dottedLineThickness));
            gradientMask.AddSprites(
                Sprites.Pixel,
                i => (i % 2 == 0 ? OsbOrigin.BottomCentre : OsbOrigin.TopCentre),
                i => Vectors.Centre + (i % 2 == 0 ? 1 : -1) * Vectors.up(length / 2),
                2
                );
            float gradientExtension = Vectors.Centre.Y - length / 2;

            gradientMask.ScaleVec(lineAppearStart, new Vector2(dottedLineThickness, gradientExtension), 2);
            gradientMask.Color(lineAppearStart, Color4.Black);
            gradientMask.Fade(lineAppearStart, e, 1.0, 1.0);

            SpriteSet cover = maskLayer.CreateSpriteSet(Sprites.Pixel, 2);

            cover.Move(i => downwardsMovement.ResampledSection(lineAppearStart, e, delta)
                       + Vectors.up((width2 - lineThickness) / 2) * (i % 2 == 0 ? 1 : -1));
            cover.Fade(lineAppearStart, e, 1.0, 1.0);
            cover.ScaleVec(lineAppearStart, new Vector2(dottedLineThickness, lineThickness));

            // point cloud
            count = 50;
            float pointScale = 0.2f;
            var   pattern    = Patterns.PointCloudGlobe(Vectors.Centre.withZ(0), 500, new Random(RandomSeed));
            var   points     = new List <Vector3>();

            for (int i = 0; i < count; i++)
            {
                points.Add(pattern(i));
            }
            SpriteSet pointCloud = layer.CreateSpriteSet(
                Sprites.Particle,
                _ => OsbOrigin.Centre,
                i => points[i].project(Vectors.ScreenSize, Vectors.Centre, FOV).screenSpaceVector,
                count
                );

            pointCloud.Fade(startOfRotation, startOfRotation + Timing.beat(s) / 2, 0, 0.6);
            pointCloud.Fade(e, 0);
            pointCloud.Scale(startOfRotation, 5);
            for (float t = startOfRotation; t < e; t += delta)
            {
                float t2     = t + delta < e ? t + delta : e;
                float angle  = (float)(-Math.PI / 4 * inOutExpo((t - startOfRotation) / (e - startOfRotation)));
                float angle2 = (float)(-Math.PI / 4 * inOutExpo((t2 - startOfRotation) / (e - startOfRotation)));
                pointCloud.Move3D(
                    OsbEasing.None,
                    t, t2,
                    i => points[i].rotateY(angle, Vectors.Centre3D),
                    i => points[i].rotateY(angle2, Vectors.Centre3D),
                    FOV,
                    (_sprite, _p1, _p2) =>
                {
                    float scale1 = pointScale / _p1.normalisedVector.Length;
                    float scale2 = pointScale / _p2.normalisedVector.Length;
                    if (scale1 != scale2)
                    {
                        _sprite.Scale(t, t2, scale1, scale2);
                    }
                }
                    );
            }
            foreach (var sprite in pointCloud.Sprites)
            {
                SpriteSet trail = Effects.Trail(layer, sprite, startOfRotation, e, 1000.0 / 60, 0, 0, 150, true);
                trail.UseScaleOf(sprite);
            }
        }
示例#6
0
        public override void GenerateStates(double time, CameraState cameraState, Object3dState object3dState)
        {
            var wvp = object3dState.WorldTransform * cameraState.ViewProjection;

            if (FixedEdge >= 0)
            {
                edgeIndex = FixedEdge;
            }

            Vector4 vector0, vector1, vector2;

            switch (edgeIndex)
            {
            case 0:
                vector0 = cameraState.ToScreen(wvp, Position0.ValueAt(time));
                vector1 = cameraState.ToScreen(wvp, Position1.ValueAt(time));
                vector2 = cameraState.ToScreen(wvp, Position2.ValueAt(time));
                break;

            case 1:
                vector2 = cameraState.ToScreen(wvp, Position0.ValueAt(time));
                vector0 = cameraState.ToScreen(wvp, Position1.ValueAt(time));
                vector1 = cameraState.ToScreen(wvp, Position2.ValueAt(time));
                break;

            case 2:
                vector1 = cameraState.ToScreen(wvp, Position0.ValueAt(time));
                vector2 = cameraState.ToScreen(wvp, Position1.ValueAt(time));
                vector0 = cameraState.ToScreen(wvp, Position2.ValueAt(time));
                break;

            default: throw new InvalidOperationException();
            }

            var cross = (vector2.X - vector0.X) * (vector1.Y - vector0.Y)
                        - (vector2.Y - vector0.Y) * (vector1.X - vector0.X);

            if (cross > 0)
            {
                if (Generator0.EndState != null)
                {
                    Generator0.EndState.Opacity = 0;
                }
                if (Generator1.EndState != null)
                {
                    Generator1.EndState.Opacity = 0;
                }
                return;
            }

            var bitmap = StoryboardObjectGenerator.Current.GetMapsetBitmap(sprite0.GetTexturePathAt(time));

            var switchedEdge = false;

            for (var i = 0; i < 3; i++)
            {
                var delta           = vector2.Xy - vector0.Xy;
                var deltaLength     = delta.Length;
                var normalizedDelta = delta / deltaLength;

                var delta2 = vector1.Xy - vector0.Xy;
                var dot    = Vector2.Dot(normalizedDelta, delta2);
                if (dot <= 0 || dot > deltaLength)
                {
                    if (FixedEdge >= 0)
                    {
                        if (Generator0.EndState != null)
                        {
                            Generator0.EndState.Opacity = 0;
                        }
                        if (Generator1.EndState != null)
                        {
                            Generator1.EndState.Opacity = 0;
                        }
                        break;
                    }

                    var temp = vector0;
                    vector0      = vector1;
                    vector1      = vector2;
                    vector2      = temp;
                    edgeIndex    = (edgeIndex + 1) % 3;
                    switchedEdge = true;
                    continue;
                }

                var position = project(vector0.Xy, vector2.Xy, vector1.Xy);
                var scale0   = new Vector2((vector2.Xy - position).Length / bitmap.Width, (vector1.Xy - position).Length / bitmap.Height);
                var scale1   = new Vector2((vector0.Xy - position).Length / bitmap.Width, scale0.Y);

                var angle    = Math.Atan2(delta.Y, delta.X);
                var rotation = InterpolatingFunctions.DoubleAngle(Generator0.EndState?.Rotation ?? 0, angle, 1);

                var opacity = vector0.W < 0 && vector1.W < 0 && vector2.W < 0 ? 0 : object3dState.Opacity;
                if (UseDistanceFade)
                {
                    opacity *= (cameraState.OpacityAt(vector0.W) + cameraState.OpacityAt(vector1.W) + cameraState.OpacityAt(vector2.W)) / 3;
                }

                if (switchedEdge)
                {
                    if (Generator0.EndState != null)
                    {
                        Generator0.EndState.Opacity = 0;
                    }
                    if (Generator1.EndState != null)
                    {
                        Generator1.EndState.Opacity = 0;
                    }
                }

                Generator0.Add(new CommandGenerator.State()
                {
                    Time     = time,
                    Position = position,
                    Scale    = scale0,
                    Rotation = rotation,
                    Color    = object3dState.Color,
                    Opacity  = switchedEdge ? 0 : opacity,
                    Additive = Additive,
                });
                Generator1.Add(new CommandGenerator.State()
                {
                    Time     = time,
                    Position = position,
                    Scale    = scale1,
                    Rotation = rotation,
                    Color    = object3dState.Color,
                    Opacity  = switchedEdge ? 0 : opacity,
                    Additive = Additive,
                    FlipH    = true,
                });
                break;
            }
        }