好的,所以我正在使用我在XNA的第一次认真经验。这是我当前的任务:下载文件。从该文件解析一个"形状的列表。"每个"形状"包含一个点列表。这些点是要在地图上绘制的线条的顶点。事实上,它是整个美国的县地图,所以"形状的数量"不是微不足道的。我们需要能够放大和缩小此地图,因此需要在3d空间中进行二维渲染。我想知道最好的策略是什么。
我尝试过简单地使用DrawUserIndexedPrimitives,但是绘制函数需要花费太长时间来处理它。
然后我想我会尝试在LoadContent中绘制一系列RenderTarget2D,并在Draw函数中保存这些纹理以进行绘制。但到目前为止,我似乎得到的只是一系列紫色盒子。
编辑:
这是我目前的代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.Runtime.InteropServices;
namespace First
{
class FirstShape : DrawableGameComponent
{
const int kSizeMultiplier = 10;
public FirstShape(string inFilePath, Game inGame) : base(inGame)
{
DrawOrder = 1000;
mFile = inFilePath;
}
protected override void LoadContent()
{
mSpriteBatch = new SpriteBatch(GraphicsDevice);
FirstMemoryStream stream = FirstMemoryStream.MakeSeekableStream(File.OpenRead(mFile));
// skip headers
stream.Seek(100, 0);
for (int i = 0; stream.Position != stream.Length; i++)
{
stream.Seek(stream.Position + 12, 0);
double minX = stream.ReadDouble();
double minY = stream.ReadDouble();
double maxX = stream.ReadDouble();
double maxY = stream.ReadDouble();
int numParts = stream.ReadInt();
int numPoints = stream.ReadInt();
VertexPositionColor[] points = new VertexPositionColor[numPoints];
stream.Seek(stream.Position + (4 * numParts), 0);
int top, bottom, left, right;
float x2, y2;
x2 = (float)stream.ReadDouble();
y2 = (float)stream.ReadDouble();
Vector2 projectedPoint = Vertex(x2, y2);
left = right = (int)Math.Round(projectedPoint.X * kSizeMultiplier);
top = bottom = (int)Math.Round(maxY - (projectedPoint.Y * kSizeMultiplier));
points[0].Position.X = left;
points[0].Position.Y = top;
for (int j = 1; j < points.Length; j++)
{
float x1 = x2;
float y1 = y2;
x2 = (float)stream.ReadDouble();
y2 = (float)stream.ReadDouble();
Vector2 p1 = Vertex(x1, y1);
Vector2 p2 = Vertex(x2, y2);
p1.X *= kSizeMultiplier;
p1.Y *= kSizeMultiplier;
p2.X *= kSizeMultiplier;
p2.Y *= kSizeMultiplier;
points[j].Position.X = (int)Math.Round(p2.X);
points[j].Position.Y = (int)Math.Round(maxY - p2.Y);
if (points[j].Position.X < left)
left = (int)points[j].Position.X;
if (points[j].Position.X > right)
right = (int)points[j].Position.X;
if (points[j].Position.Y < top)
top = (int)points[j].Position.Y;
if (points[j].Position.Y > bottom)
bottom = (int)points[j].Position.Y;
}
if (mTopLeft.X == 0 || mTopLeft.X > left)
mTopLeft.X = left;
if (mTopLeft.Y == 0 || mTopLeft.Y > top)
mTopLeft.Y = top;
for (int j = 0; j < points.Length; j++)
{
points[j].Color = Color;
}
int width = (right - left) + 1;
int height = (bottom - top) + 1;
mTextures.Add(new FirstImage(GraphicsDevice, width, height, new Vector2(left, top)));
GraphicsDevice.SetRenderTarget(mTextures.Last());
GraphicsDevice.Indices = new IndexBuffer(GraphicsDevice, IndexElementSize.SixteenBits, points.Length, BufferUsage.None);
GraphicsDevice.SetVertexBuffer(new VertexBuffer(GraphicsDevice, VertexPositionColor.VertexDeclaration, points.Length, BufferUsage.None));
BasicEffect basicEffect = new BasicEffect(GraphicsDevice);
basicEffect.LightingEnabled = false;
basicEffect.VertexColorEnabled = true;
foreach (EffectPass pass in basicEffect.CurrentTechnique.Passes)
{
pass.Apply();
GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.LineStrip, 0, 0, points.Length, 0, points.Length - 1);
}
}
GraphicsDevice.SetRenderTarget(null);
stream.Close();
for (int i = 0; i < mTextures.Count; i++)
{
mTextures[i].Position -= mTopLeft;
}
}
public override void Draw(GameTime inTime)
{
mSpriteBatch.Begin();
for(int i = 0; i < mTextures.Count; i++)
{
mSpriteBatch.Draw(mTextures[i], mTextures[i].Position, Color.White);
}
mSpriteBatch.End();
}
private Vector2 Vertex(float inX, float inY)
{
return FirstProjector.Project(new Vector2(inX, inY));
}
public Color Color { get; set; }
private string mFile;
private List<FirstImage> mTextures = new List<FirstImage>();
private SpriteBatch mSpriteBatch;
private Vector2 mTopLeft = new Vector2(0.0f, 0.0f);
private Vector2 mBottomRight = new Vector2(0.0f, 0.0f);
}
class FirstImage : RenderTarget2D
{
public FirstImage(GraphicsDevice inDevice, int inWidth, int inHeight, Vector2 inPosition) : base(inDevice, inWidth, inHeight, false, SurfaceFormat.Color, DepthFormat.None)
{
Position = inPosition;
}
public Vector2 Position {get; set;}
}
}