示例#1
0
        public override void drawGeoChunk(Geo geo)
        {
            LineGeo lineGeo = (LineGeo)geo;

            foreach (var vb in lineGeo.lineVb)
            {
                GraphicsDevice.SetVertexBuffer(vb);
                GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleStrip, 3, vb.VertexCount - 5);
            }
            foreach (var vb in lineGeo.hLineVb)
            {
                GraphicsDevice.SetVertexBuffer(vb);
                GraphicsDevice.DrawPrimitives(PrimitiveType.LineList, 0, vb.VertexCount);
            }
        }
示例#2
0
 void createLineSegment(ref int numVerts, ref int numHLineVerts, LineGeo geo, float lineWidth)
 {
     //Console.WriteLine(numVerts);
     if (lineWidth > 0)
     {
         if (numVerts > 5 || numHLineVerts > 1)
         {
             if (numHLineVerts > 1)
             {
                 VertexBuffer vb = new VertexBuffer(GraphicsDevice, lineVertDecl, numHLineVerts, BufferUsage.WriteOnly);
                 vb.SetData(hLineVerts, 0, numHLineVerts);
                 geo.hLineVb.Add(vb);
                 numHLineVerts = 0;
             }
             if (numVerts > 5)
             {
                 VertexBuffer vb = new VertexBuffer(GraphicsDevice, lineVertDecl, numVerts, BufferUsage.WriteOnly);
                 vb.SetData(lineVerts, 0, numVerts);
                 geo.lineVb.Add(vb);
                 numVerts = 3;
             }
         }
     }
 }
示例#3
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);
        }