2016-08-02 27 views
0

Ich möchte einen einfachen Punktwolken-Viewer erstellen. Ich benutze C# und XNA. In diesem Moment habe ich diese erstellt haben:So verbessern Sie die Leistung des Punktwolken-Viewers

Link

Ich kann es drehen und zoomen aber Perfomance ist schwach. Bei einer Wolke mit 1.500.000 Punkten dauert es etwa 6 Sekunden, um das Bild zu drehen oder zu zoomen. Irgendwelche Ideen, wie man es besser macht? Gibt es eine Möglichkeit zu drehen oder zu zoomen, ohne alles neu zeichnen zu müssen?

Mein Code-Snippet über Zeichnung. Im mit SpriteBatches:

ba.Begin(); 
for (int i = 0; i < DBmanager.data.Length; i++) 
{ 
    Vector3 screenLocation = Device.Viewport.Project(DBmanager.data[i], basicEffect.Projection, basicEffect.View, basicEffect.World); 
    ba.Draw(pixel, new Vector2(screenLocation.X, screenLocation.Y), Color.Orange); 
} 
ba.End(); 

Funktion Move:

private void move(float x,float y) 
{ 
    //currentx += x; 
    Debug.WriteLine(x); 
    Debug.WriteLine(y); 
    if (x == 0) 
    { 
     Vector3 target = new Vector3(Center.X, Center.Y, Center.Z); 
     cameraPosition = Vector3.Transform(cameraPosition - target, Matrix.CreateRotationY(y)) + target; 
     basicEffect.View = Matrix.CreateLookAt(cameraPosition, target, Vector3.Up); 
    } 
    if (y == 0) 
    { 
     Vector3 target = new Vector3(Center.X, Center.Y, Center.Z); 
     cameraPosition = Vector3.Transform(cameraPosition - target, Matrix.CreateRotationX(x)) + target; 
     basicEffect.View = Matrix.CreateLookAt(cameraPosition, target, Vector3.Up); 
    } 
} 

My Draw Funktion:

 protected override void Draw() 
    { 
     if (called) 
     { 
      Application.Idle -= IdleHandler; 
      timer.Stop(); 
      SetUpVertices(); 
      called = false; 
      //Invalidate(); 
     } 
     // if (drawn) 
     // { 
      //Application.Idle -= IdleHandler; 
      //timer.Stop(); 
      // UpdateCam(); 
      // Debug.WriteLine("Obrót zakonczony"); 
      //SetUpVertices(); 
     // } 
     if (leftDrag) 
     { 
      Application.Idle -= IdleHandler; 
      timer.Stop(); 
      UpdateCam(); 
      //SetUpVertices(); 
      leftDrag = false; 
     } 
     if (Zoomed) 
     { 
      Application.Idle -= IdleHandler; 
      timer.Stop(); 
      Zoom(Zoomlevel); 
      //UpdateCam(); 
      //SetUpVertices(); 
      Zoomed = false; 
     } 

    } 

SetupVertices:

private void SetUpVertices() 
    { 
     Device.Clear(Color.Black); 
     VertexPositionColor [] Verts = new VertexPositionColor [65535]; 
     RasterizerState rasterizerState = new RasterizerState(); 
     rasterizerState.CullMode = CullMode.None; 
     Device.RasterizerState = rasterizerState; 
     int j = 0; 
     for (int i = 0; i < DBmanager.data.Length; i++) 
     { 
      if (j==65535) 
      { 
       buf = new VertexBuffer(Device, typeof(VertexPositionColor), Verts.Length, BufferUsage.WriteOnly); 
       buf.SetData<VertexPositionColor>(Verts); 
       Device.SetVertexBuffer(buf); 
       foreach (EffectPass pass in basicEffect.CurrentTechnique.Passes) 
       { 
        pass.Apply(); 
        Device.DrawPrimitives(PrimitiveType.TriangleList, 0, Verts.Length); 
       } 
       Verts = new VertexPositionColor[65535]; 
       j = 0; 
      } 
      else 
      { 
       Verts[j] = new VertexPositionColor(new Vector3(DBmanager.data[i].X, DBmanager.data[i].Y, DBmanager.data[i].Z),Color.Orange); 
       j++; 
      } 
     } 
     if (!IsCenterCalculated) 
     { 
      Box = BoundingBox.CreateFromPoints(DBmanager.data); 
      corners = Box.GetCorners(); 
      setCenter(CalculateCenter(corners)); 
      IsCenterCalculated = true; 
      basicEffect.View = Matrix.CreateLookAt(cameraPosition, new Vector3(Center.X, Center.Y, Center.Z), Vector3.Up); 
     } 
    } 
+1

Sie sollten Interaktion ('Game.Update()'), Datenverwaltung und tatsächliche Zeichnung ('Game.Draw()') trennen. Es scheint, dass Sie die Punktwolke über 'SetupVertices()' zeichnen. Da dies auch immer wieder die gesamten Daten an die GPU sendet, haben Sie das gleiche Problem wie zuvor. Setze die Scheitelpunkte nur einmal auf und dann kannst du 'DrawPrimitives()' in jedem Frame ziehen. Btw, sollte es nicht eine 'PointList' anstelle von' TriangleList' sein? –

+0

Sie sollten während des Setups nicht "basicEffect.View" aufrufen. – MickyD

+0

Sprite-Batches sind langsam, das ist im Wesentlichen _immediate mode_, in dem alle Zeichenoperationen in jedem Frame erneut an die GPU gesendet werden. Sie wollen eine Technik, bei der viel auf der GPU gespeichert bleibt – MickyD

Antwort

0

Der richtige Weg, dies zu tun ist, zu verwenden, Vertexpuffer, um den Punkt zu speichern Daten. Du lädst sie einmal auf die Grafikkarte hoch und modifizierst dann einfach die Ansichtsmatrix.

Dies verhindert das Hochladen von Daten in jeden Frame und die Grafikkarte führt die Projektion parallel durch. Mit einer minimalen Schätzung der Datengröße von ungefähr 24 Bytes pro Punkt erhalten Sie ungefähr 36 MB Daten. Wenn Sie dies in jedem Frame mit 60 fps hochladen, benötigen Sie für die Normalpunktdaten eine Übertragungsrate von ca. 16 Gb/s. Und mit dem Sprite-Stapel ist es noch mehr, weil Sie Rechtecke anstelle von Punkten hochladen müssen.

Also machen Sie sich mit Vertex Buffern vertraut. Legen Sie die Daten einmal ein und laden Sie sie auf die GPU hoch. Dann können Sie alle Punkte gleichzeitig mit einem einzigen Zeichenaufruf zeichnen.

+0

Ich habe Ihre Lösung versucht, aber ist immer noch die gleiche.Wenn ich drehen oder zoomen ohne Neuzeichnen aller Sachen, wird angedockte Formular leer. Vielleicht habe ich etwas falsch verstanden. Ich kann meine ganze Lösung posten und du kannst mir sagen, was ich falsch mache. – Habababa

+0

Es sollte kein Problem sein, beim Rotieren alles zu zeichnen. Zeigen Sie einfach Ihren Zeichencode (ohne das Initialisierungskram). Dies sollte ausreichen, um zu beurteilen, was Sie tun. –

+0

Ich habe meine Frage aktualisiert – Habababa