如何提高点云查看器的性能

时间:2016-08-02 19:21:42

标签: c# xna

我想创建一个简单的点云查看器。我使用C#和XNA。 在这一刻,我创造了这个:

Link

我可以旋转和缩放,但性能很差。在具有1,500 000点的云上,完成旋转或缩放大约需要6秒。任何想法如何使它更好?是否有可能旋转或缩放而不重绘所有内容?

关于绘图的我的代码片段。我正在使用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();

移动功能:

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);
    }
}

我的绘画功能:

        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 个答案:

答案 0 :(得分:0)

正确的方法是使用顶点缓冲区来存储点数据。您将它们上传到图形卡,然后只需修改视图矩阵。

这将避免每帧中的数据上传,并且图形卡并行执行投影。通过对每点大约24个字节的数据大小的最小估计,您可以获得大约36 MB的数据。如果以60 fps的速度在每帧中上传,则普通点数据的传输速率约为16 Gb / s。使用sprite批处理,更是因为你需要上传矩形而不是点。

所以只需熟悉顶点缓冲区即可。将数据放入一次,将其上传到GPU。然后,您可以通过一次绘制调用一次绘制所有点。