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
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);
}
}
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? –
Sie sollten während des Setups nicht "basicEffect.View" aufrufen. – MickyD
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