我想创建一个简单的点云查看器。我使用C#和XNA。 在这一刻,我创造了这个:
我可以旋转和缩放,但性能很差。在具有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);
}
}
答案 0 :(得分:0)
正确的方法是使用顶点缓冲区来存储点数据。您将它们上传到图形卡,然后只需修改视图矩阵。
这将避免每帧中的数据上传,并且图形卡并行执行投影。通过对每点大约24个字节的数据大小的最小估计,您可以获得大约36 MB的数据。如果以60 fps的速度在每帧中上传,则普通点数据的传输速率约为16 Gb / s。使用sprite批处理,更是因为你需要上传矩形而不是点。
所以只需熟悉顶点缓冲区即可。将数据放入一次,将其上传到GPU。然后,您可以通过一次绘制调用一次绘制所有点。