Ejemplo n.º 1
0
        void adjustCurvePoint(Vector3 center, Vector3 vertexOffset, int side, TrackProps trackProps, LineVertex[] lineVerts, int vertIndex, float step, float lineWidth)
        {
            Vector3 curPos = center + vertexOffset * side;
            Vector3 dummyCenter, dummyNormal, newVerteexOffset;

            getCurvePoint(out dummyCenter, out dummyNormal, out newVerteexOffset, step, curPos.X, trackProps, lineWidth);
            float newPosX = curPos.X + newVerteexOffset.X * side;

            lineVerts[vertIndex].pos = curPos;
            if (curPos.X > center.X != newPosX > curPos.X)
            {
                int     prevIndex = Math.Max(vertIndex - 2, 3);
                Vector3 prevPos   = lineVerts[prevIndex].pos;
                lineVerts[vertIndex].pos = prevPos;
                //int keyIndex;
                //float timeT = Project.getTimeT(center.X);
                //keyIndex = trackProps.TrackView.Curve.Keys.IndexAtPosition(timeT);
                //if (curPos.X < center.X)
                //	keyIndex--;
                //if (keyIndex < trackProps.TrackView.Curve.Keys.Count)
                //{
                //	CurveKey key = trackProps.TrackView.Curve.Keys[keyIndex];
                //	lineVerts[vertIndex].pos.X = Project.getScreenPosX((int)key.Position);
                //	//lineVerts[vertIndex].pos.Y = Project.getScreenPosY(key.Value) + (float)LineWidth / 2 * side;
                //	lineVerts[vertIndex].pos.Y = lineVerts[vertIndex-2].pos.Y;
                //}
            }
            lineVerts[vertIndex].normal = (lineVerts[vertIndex].pos - center) * -side;
            lineVerts[vertIndex].normal.Normalize();
        }
Ejemplo n.º 2
0
        public override void drawTrack(Midi.Track midiTrack, TrackProps trackProps, MaterialProps texMaterial)
        {
            float songPosP;

            base.drawTrack(midiTrack, trackProps, texMaterial, out songPosP);
            trackProps.TrackView.OcTree.drawGeo(Project.Props.Camera);
        }
Ejemplo n.º 3
0
        public void createGeo(Midi.Track midiTrack, TrackProps trackProps, TrackProps globalTrackProps, MaterialProps texMaterial)
        {
            _createGeoChunk(out _geo, _bbox, midiTrack, trackProps, texMaterial);
            return;

            if (_nodes != null)
            {
                foreach (var node in _nodes)
                {
                    if (node == null)
                    {
                        continue;
                    }
                    node.createGeo(midiTrack, trackProps, globalTrackProps, texMaterial);
                }
            }
        }
Ejemplo n.º 4
0
        public override void drawTrack(Midi.Track midiTrack, TrackProps trackProps, MaterialProps texMaterial)
        {
            float songPosP;

            base.drawTrack(midiTrack, trackProps, texMaterial, out songPosP);
            List <Midi.Note> noteList = midiTrack.Notes;

            //List<Midi.Note> noteList = getNotes(0, midiTrack, songDrawProps);
            if (noteList.Count == 0)
            {
                return;
            }

            //this.trackProps = trackProps;

            fx.Parameters["LineType"].SetValue((int)LineType);
            fx.Parameters["HlSize"].SetValue(VpHlSize / 2.0f);
            float radius = (float)VpLineWidth / 2.0f;

            fx.Parameters["Radius"].SetValue(radius);
            fx.Parameters["InnerHlSize"].SetValue(0.0f);

            fx.CurrentTechnique = fx.Techniques["Line"];
            fx.Parameters["DiscardAtOnce"].SetValue(true);
            fx.CurrentTechnique.Passes[0].Apply();
            trackProps.TrackView.OcTree.drawGeo(Project.Props.Camera);
            fx.Parameters["DiscardAtOnce"].SetValue(false);
            fx.CurrentTechnique.Passes[0].Apply();
            trackProps.TrackView.OcTree.drawGeo(Project.Props.Camera);

            DepthStencilState oldDss = GraphicsDevice.DepthStencilState;

            GraphicsDevice.DepthStencilState = DepthStencilState.None;
            drawHighLights(midiTrack, trackProps, songPosP);
            GraphicsDevice.DepthStencilState = oldDss;
        }
Ejemplo n.º 5
0
        public bool areObjectsInFrustum(BoundingFrustum frustum, float songPos, Project project, TrackProps trackProps)
        {
            foreach (var bbox in _geo.bboxes)
            {
                BoundingBoxEx bb = bbox.clone();
                bb.scale(new Vector3(project.ViewWidthQnScale, 1, 1));

                Vector3 posOffset = project.getSpatialNormPosOffset(trackProps);
                posOffset.X -= songPos;
                bb.translate(posOffset);

                if (bb.intersects(frustum))
                {
                    return(true);
                }
            }
            return(false);
        }
Ejemplo n.º 6
0
        public override void createGeoChunk(out Geo geo, BoundingBox bbox, Midi.Track midiTrack, TrackProps trackProps, MaterialProps texMaterial)
        {
            BarGeo barGeo = new BarGeo();

            geo = barGeo;
            List <Midi.Note> noteList = midiTrack.Notes;

            if (noteList.Count == 0)
            {
                return;
            }

            float halfNoteHeight = Project.Props.NoteHeight / 2;
            int   instanceIndex  = 0;

            for (int n = 0; n < noteList.Count; n++)
            {
                Midi.Note note = noteList[n];
                if (note.start > Project.Notes.SongLengthT) //only if audio ends before the notes end
                {
                    continue;
                }
                Vector2 noteStart = Project.getScreenPos(note.start, note.pitch);
                Vector2 noteEnd   = Project.getScreenPos(note.stop, note.pitch);

                //Create bounding boxes
                Vector3 boxMin = new Vector3(noteStart.X, noteStart.Y - halfNoteHeight, 0);
                Vector3 boxMax = new Vector3(noteEnd.X, noteEnd.Y + halfNoteHeight, 0);
                geo.bboxes.Add(new BoundingBoxEx(boxMin, boxMax));

                //Create inctance data
                Vector2 topLeft_world = new Vector2(noteStart.X, noteStart.Y - halfNoteHeight);
                Vector2 size_world    = new Vector2(noteEnd.X - noteStart.X, halfNoteHeight * 2 - 0.001f);
                Vector2 topLeft_tex   = topLeft_world;
                Vector2 size_tex      = size_world;

                Texture2D texture = texMaterial.TexProps.Texture;
                if (texture != null)
                {
                    Vector2 texSize = new Vector2(texture.Width, texture.Height);
                    calcRectTexCoords(out topLeft_tex, out size_tex, texSize, topLeft_world, size_world, texMaterial);
                }
                instanceVerts[instanceIndex].destRect = new Vector4(topLeft_world.X, topLeft_world.Y, size_world.X, size_world.Y);
                instanceVerts[instanceIndex].srcRect  = new Vector4(topLeft_tex.X, topLeft_tex.Y, size_tex.X, size_tex.Y);
                if (++instanceIndex >= MaxInstances - 1)
                {
                    createVb(ref instanceIndex, barGeo);
                }
            }
            if (instanceIndex > 0)
            {
                createVb(ref instanceIndex, barGeo);
            }
        }
Ejemplo n.º 7
0
 public NoteStyle_Bar(TrackProps tprops)
     : base(tprops)
 {
     styleType = NoteStyleType.Bar;
 }
Ejemplo n.º 8
0
 public NoteStyle_Line(TrackProps tprops)
     : base(tprops)
 {
     styleType = NoteStyleType.Line;
 }
Ejemplo n.º 9
0
        void drawHighLights(Midi.Track midiTrack, TrackProps trackProps, float songPosP)
        {
            List <Midi.Note> noteList = midiTrack.Notes;
            int hlNoteIndex           = midiTrack.getLastNoteIndexAtTime((int)(Project.SongPosT - Project.PlaybackOffsetT));

            if (hlNoteIndex < 0)
            {
                return;
            }
            Midi.Note note = noteList[hlNoteIndex], nextNote;
            if (note.start > Project.Notes.SongLengthT) //only  if audio ends before the notes end
            {
                return;
            }

            if (hlNoteIndex < noteList.Count - 1)
            {
                nextNote = noteList[hlNoteIndex + 1];
            }
            else
            {
                nextNote = note;
            }

            Vector3 noteStart = new Vector3(Project.getScreenPos(note.start, note.pitch), 0);
            float   noteEnd   = Project.getScreenPos(note.stop, note.pitch).X;

            Vector3 nextNoteStart = new Vector3(Project.getScreenPos(nextNote.start, nextNote.pitch), 0);

            if (noteEnd > nextNoteStart.X && hlNoteIndex < noteList.Count - 1)
            {
                noteEnd = nextNoteStart.X;
            }

            if ((float)(nextNote.start - note.stop) > Qn_gapThreshold * Project.Notes.TicksPerBeat || note == nextNote)
            {
                if (nextNoteStart.X != noteStart.X)
                {
                    nextNoteStart.Y = MathHelper.Lerp(noteStart.Y, nextNoteStart.Y, (float)(noteEnd - noteStart.X) / (nextNoteStart.X - noteStart.X));
                }
                nextNoteStart.X = noteEnd;
            }

            Vector3 hlPos      = noteStart;
            float   noteLength = (noteEnd - noteStart.X);
            float   normPos    = (songPosP - noteStart.X) / noteLength;

            if ((bool)MovingHl)
            {
                float poweredNormPos = (float)Math.Pow(normPos, (double)HlMovementPow);
                hlPos.X = noteStart.X + poweredNormPos * noteLength;
                hlPos.Y = Project.getScreenPosY(trackProps.TrackView.Curve.Evaluate((float)Project.pixelsToTicks(hlPos.X)));
            }

            //Set common fx params---------------------

            //For shrinking highlights
            float shrinkPercent = normPos * 1.0001f;

            if (!(bool)ShrinkingHl)
            {
                shrinkPercent = 0;
                if ((bool)HlBorder)
                {
                    shrinkPercent = 1;
                }
            }
            fx.Parameters["ClipPercent"].SetValue(shrinkPercent);
            float innerHlSize = VpHlSize * 0.5f * (1 - shrinkPercent);

            fx.Parameters["InnerHlSize"].SetValue(innerHlSize);

            //Vector4 hlColor;
            //Texture2D hlTexture;
            //getMaterial(trackProps, true, out hlColor, out hlTexture);
            //Vector4 hlColor = fx.Parameters["HlColor"].GetValueVector4();
            //fx.Parameters["HlColor"].SetValue(SongPanel.HSLA2RGBA(hlColor).ToVector4());
            fx.Parameters["Border"].SetValue((bool)HlBorder);
            //-----------------------------------------------

            if (HlType == LineHlType.Arrow)
            {
                float   arrowLength;
                Vector3 arrowDir;
                Vector3 arrowNormal;
                if (!(bool)MovingHl)  //Non-moving arrow
                {
                    Vector3 nextNoteOffset = nextNoteStart - noteStart;
                    arrowLength = nextNoteOffset.Length();
                    arrowDir    = nextNoteOffset;;
                }
                else //Moving arrow
                {
                    float x1     = hlPos.X;
                    float y1     = hlPos.Y;
                    float x2     = x1 + 0.001f;
                    float pitch2 = trackProps.TrackView.Curve.Evaluate((float)Project.pixelsToTicks(x2));
                    float y2     = Project.getScreenPosY(pitch2);
                    arrowDir    = new Vector3(x2 - x1, y2 - y1, 0);
                    arrowLength = VpHlSize * 1.25f;  //Make arrow 25% longer than wide
                }
                arrowDir.Normalize();
                arrowNormal = new Vector3(-arrowDir.Y, arrowDir.X, 0);
                arrowNormal.Normalize();

                float halfArrowWidth = VpHlSize * 0.5f;

                lineHlVerts[0].pos = hlPos + arrowNormal * halfArrowWidth;
                lineHlVerts[1].pos = hlPos - arrowNormal * halfArrowWidth;
                lineHlVerts[2].pos = hlPos + arrowDir * arrowLength;

                fx.Parameters["ArrowDir"].SetValue(arrowDir);
                //lineFx.Parameters["ArrowLength"].SetValue(nextNoteOffsetLength);
                fx.Parameters["ArrowStart"].SetValue(hlPos);
                fx.Parameters["ArrowEnd"].SetValue(lineHlVerts[2].pos); //Is used to calc distance from the two "sides" of the triangle (not the bottom) since they share this point
                Vector3 side1Tangent = lineHlVerts[2].pos - lineHlVerts[0].pos;
                Vector3 side1Normal  = new Vector3(-side1Tangent.Y, side1Tangent.X, 0);
                side1Normal.Normalize();
                fx.Parameters["Side1Normal"].SetValue(side1Normal);
                Vector3 side2Tangent = lineHlVerts[2].pos - lineHlVerts[1].pos;
                Vector3 side2Normal  = new Vector3(-side2Tangent.Y, side2Tangent.X, 0);
                side2Normal.Normalize();
                fx.Parameters["Side2Normal"].SetValue(side2Normal);

                //Calc shortest dist to incenter from border, ie. the inscribed circle's radius
                float a        = (lineHlVerts[0].pos - lineHlVerts[1].pos).Length();
                float b        = (lineHlVerts[0].pos - lineHlVerts[2].pos).Length();
                float c        = (lineHlVerts[1].pos - lineHlVerts[2].pos).Length();
                float k        = (a + b + c) / 2.0f;
                float icRadius = (float)Math.Sqrt(k * (k - a) * (k - b) * (k - c)) / k;
                fx.Parameters["DistToCenter"].SetValue(icRadius);

                fx.CurrentTechnique = fx.Techniques["Arrow"];
                fx.CurrentTechnique.Passes[0].Apply();
                GraphicsDevice.DrawUserPrimitives(PrimitiveType.TriangleList, lineHlVerts, 0, 1);
            }
            else if (HlType == LineHlType.Circle)
            {
                setHlCirclePos(hlPos);

                fx.CurrentTechnique = fx.Techniques["Circle"];
                fx.CurrentTechnique.Passes[0].Apply();
                GraphicsDevice.DrawUserPrimitives(PrimitiveType.TriangleStrip, lineHlVerts, 0, 2);
            }
        }
Ejemplo n.º 10
0
        //static string GetName<T>(T item) where T : class
        //{
        //	return typeof(T).GetProperties()[0].Name;
        //}

        public override void createGeoChunk(out Geo geo, BoundingBox bbox, Midi.Track midiTrack, TrackProps trackProps, MaterialProps texMaterial)
        {
            LineGeo lineGeo = new LineGeo();

            geo = lineGeo;
            if (LineWidth == 0)
            {
                return;
            }
            List <Midi.Note> noteList = midiTrack.Notes;

            //List<Midi.Note> noteList = getNotes(0, midiTrack, songDrawProps);
            if (noteList.Count == 0)
            {
                return;
            }

            int   vertIndex                  = 3;
            int   hLineVertIndex             = 0;
            int   completeNoteListIndex      = midiTrack.Notes.IndexOf(noteList[0]);
            float vpLineWidth                = VpLineWidth;
            float maxNumBboxesPerScreenWidth = 1000;
            float bboxMinSqLength            = (float)Math.Pow(Project.Props.Camera.ViewportSize.X / maxNumBboxesPerScreenWidth, 2);

            //for (int i = 0; i < 100; i++)
            //{
            //	vertIndex = 30000;
            //	createLineSegment(ref vertIndex, ref hLineVertIndex, lineGeo, vpLineWidth);
            //}
            //return;
            for (int n = 0; n < noteList.Count; n++)
            {
                //Get current note
                Midi.Note note = noteList[n], nextNote;
                if (note.start > Project.Notes.SongLengthT) //only  if audio ends before the notes end
                {
                    continue;
                }

                if (n < noteList.Count - 1)
                {
                    nextNote = noteList[n + 1];
                }
                else if (completeNoteListIndex < midiTrack.Notes.Count - 1)
                {
                    nextNote = midiTrack.Notes[completeNoteListIndex + 1];
                }
                else
                {
                    nextNote = note;
                }

                Vector2 noteStart = Project.getScreenPos(note.start, note.pitch);
                float   noteEnd   = Project.getScreenPos(note.stop, note.pitch).X;

                Vector2 nextNoteStart = Project.getScreenPos(nextNote.start, nextNote.pitch);
                if (noteEnd > nextNoteStart.X && completeNoteListIndex < midiTrack.Notes.Count - 1)
                {
                    noteEnd = nextNoteStart.X;
                }

                bool endOfSegment = false;
                if ((float)(nextNote.start - note.stop) > Qn_gapThreshold * Project.Notes.TicksPerBeat || note == nextNote)
                {
                    if (nextNoteStart.X != noteStart.X)
                    {
                        nextNoteStart.Y = (int)MathHelper.Lerp(noteStart.Y, nextNoteStart.Y, (float)(noteEnd - noteStart.X) / (nextNoteStart.X - noteStart.X));
                    }
                    nextNoteStart.X = noteEnd;
                    endOfSegment    = true;
                }

                float startDraw = noteStart.X;
                float endDraw   = nextNoteStart.X;

                //Don't draw if length is 0
                if (startDraw == endDraw)
                {
                    continue;
                }

                float curvature = calcLinearLineAngle(n, trackProps.TrackView.Curve);
                //if (n > 0)
                //{
                //	float prevCurvature = calcLinearLineAngle(n - 1, trackProps.TrackView.Curve);
                //	if (prevCurvature > curvature)
                //		curvature = (prevCurvature + curvature) / 2;    //Prevent too big jumps between levels of tesselation which will cause sharp bends
                //}
                if (n < noteList.Count - 1)
                {
                    curvature = Math.Max(curvature, calcLinearLineAngle(n + 1, trackProps.TrackView.Curve));
                }

                //curvature /= (float)Math.PI; //Map to [0,1]
                curvature = Math.Min(curvature, 0.97f * (float)Math.PI); //Clip below 180 degrees to avoid extreme tesselation
                curvature = (float)Math.Pow(curvature, 2.25) * 1000;
                float step;
                if (curvature == 0)
                {
                    step = (endDraw - startDraw) * 0.999f; //Only one point for the note
                }
                else
                {
                    step = 1 / curvature;
                }

                if (step >= endDraw - startDraw)
                {
                    step = (endDraw - startDraw);// * 0.999f;
                }
                int iterations = (int)((endDraw - startDraw) / step);
                if (iterations < 0)
                {
                    throw new OverflowException($"Too many vertices for note {n}, track {trackProps.TrackView.TrackNumber}.");
                }
                step = (endDraw - startDraw) / (iterations + 1);

                Vector3 bboxStart = Vector3.Zero;

                for (float x = startDraw; x <= endDraw + 0.00001f; x += step)
                {
                    Vector3 center, normal, vertexOffset;
                    getCurvePoint(out center, out normal, out vertexOffset, step, x, trackProps, vpLineWidth);
                    //normal.X = curvature/10f;
                    lineVerts[vertIndex].normal = lineVerts[vertIndex + 1].normal = normal;

                    //Create vertices
                    //adjustCurvePoint(center, vertexOffset, -1, trackProps, lineVerts, vertIndex, step, vpLineWidth);
                    //adjustCurvePoint(center, vertexOffset, 1, trackProps, lineVerts, vertIndex + 1, step, vpLineWidth);

                    //curvature = trackProps.TrackView.Curve.EvaluateCurvature(Project.getTimeT(x));
                    //center.Y = curvature / 10;
                    lineVerts[vertIndex].pos     = center - vertexOffset;
                    lineVerts[vertIndex + 1].pos = center + vertexOffset;
                    lineVerts[vertIndex].center  = lineVerts[vertIndex + 1].center = center;
                    float normStepFromNoteStart = (x - startDraw) / (nextNoteStart.X - noteStart.X);
                    //lineVerts[vertIndex].normStepFromNoteStart = lineVerts[vertIndex + 1].normStepFromNoteStart = normStepFromNoteStart;
                    lineVerts[vertIndex].normPos     = new Vector2(normStepFromNoteStart, 0);
                    lineVerts[vertIndex + 1].normPos = new Vector2(normStepFromNoteStart, 1);

                    if (texMaterial.TexProps.Texture != null)
                    {
                        calcTexCoords(out lineVerts[vertIndex].texCoords, out lineVerts[vertIndex + 1].texCoords, texMaterial.TexProps, x - startDraw, normStepFromNoteStart, vpLineWidth, lineVerts[vertIndex].pos, lineVerts[vertIndex + 1].pos);
                    }

                    if (LineType == VisualMusic.LineType.Ribbon)
                    {
                        float hLineStart = center.X;
                        float hLineEnd   = hLineStart;
                        do
                        {
                            hLineEnd += step;
                        } while ((int)center.Y == (int)Project.getCurveScreenY((float)hLineEnd + step, trackProps.TrackView.Curve) && hLineEnd < endDraw);
                        if (hLineEnd > hLineStart + vpLineWidth / 2)
                        {
                            hLineVerts[hLineVertIndex++] = lineVerts[vertIndex];
                            hLineVerts[hLineVertIndex++] = lineVerts[vertIndex + 1];
                        }
                        //float horizontalFactor = Math.Abs(normal.Y);
                        //float horizontalLimit = 0.98f;
                        //float minThickness = 0.001f;
                        //if (horizontalFactor > horizontalLimit)
                        //{ //todo use vertexoffset for non-ribbon instead of normal
                        //	horizontalFactor = (horizontalFactor - horizontalLimit) / (1 - horizontalLimit);  //[horizontalFactor, 1] -> [0, 1]
                        //	lineVerts[vertIndex].pos.Y -= minThickness * horizontalFactor * Math.Sign(normal.X);
                        //}
                    }

                    if (x == startDraw && vertIndex > 3)
                    {
                        lineVerts[vertIndex].pos     = lineVerts[vertIndex - 2].pos;
                        lineVerts[vertIndex + 1].pos = lineVerts[vertIndex - 1].pos;
                    }

                    //Create bounding box
                    if (bboxStart == Vector3.Zero)
                    {
                        bboxStart = lineVerts[vertIndex].center;
                    }
                    Vector3 bboxEnd = lineVerts[vertIndex].center;
                    if (Vector3.DistanceSquared(bboxStart, bboxEnd) > bboxMinSqLength)
                    {
                        Vector3 bboxCenter = (bboxStart + bboxEnd) / 2;
                        geo.bboxes.Add(new BoundingBoxEx(bboxCenter, bboxEnd - bboxCenter, bboxEnd - lineVerts[vertIndex].pos, new Vector3(0, 0, 0)));
                        bboxStart = bboxEnd;
                    }

                    vertIndex += 2;

                    if (vertIndex >= MaxLineVerts - 2 || hLineVertIndex >= MaxHLineVerts - 2)
                    {
                        createLineSegment(ref vertIndex, ref hLineVertIndex, lineGeo, vpLineWidth);
                        x -= step;
                    }
                    //break;
                }

                if (!(bool)Continuous)
                {
                    endOfSegment = true; //One draw call per note. Can be used to avoid glitches between notes because of instant IN.normStepFromNoteStart interpolation from 1 to 0.
                }
                if (endOfSegment)
                {
                    createLineSegment(ref vertIndex, ref hLineVertIndex, lineGeo, vpLineWidth);
                }

                completeNoteListIndex++;
            }
            createLineSegment(ref vertIndex, ref hLineVertIndex, lineGeo, vpLineWidth);
        }
Ejemplo n.º 11
0
        void getCurvePoint(out Vector3 pos, out Vector3 normal, out Vector3 vertexOffset, float step, float x, TrackProps trackProps, float lineWidth)
        {
            Vector3[] points   = new Vector3[3];
            Vector3[] tangents = new Vector3[2];
            step *= 0.1f;

            for (int i = 0; i < points.Length; i++)
            {
                points[i]   = new Vector3();
                points[i].X = x + i * step - step;
                points[i].Y = Project.getCurveScreenY(points[i].X, trackProps.TrackView.Curve);
                points[i].Z = 0;
            }

            for (int i = 0; i < tangents.Length; i++)
            {
                tangents[i] = points[i + 1] - points[i];
            }

            normal = tangents[0] + tangents[1];
            normal = new Vector3(-normal.Y, normal.X, 0);
            normal.Normalize();
            pos = points[1];

            //normal.X = 1;
            //normal.Y = Project.getScreenPosY(trackProps.TrackView.Curve.EvaluateSignedCurvatureDerivative(x));
            //normal.Z = 0;
            //normal.Normalize();

            if (LineType == VisualMusic.LineType.Ribbon)
            {
                vertexOffset = new Vector3(1, 0, 0);
            }
            else
            {
                vertexOffset = normal;
            }
            vertexOffset *= lineWidth / 2.0f;
        }