Линии рендеринга - Метод 1 (Примитивы)
Для простых линий в трехмерном пространстве вы можете нарисовать их, используя LineList
или LineStrip
примитив. Вот минимальный объем кода, который вы должны добавить в пустой проект XNA, чтобы нарисовать линию от (0,0,0) до (0,0, -50). Линия должна иметь примерно одинаковую ширину независимо от того, где находится камера.
// Inside your Game class
private BasicEffect basicEffect;
private Vector3 startPoint = new Vector3(0, 0, 0);
private Vector3 endPoint = new Vector3(0, 0, -50);
// Inside your Game.LoadContent method
basicEffect = new BasicEffect(GraphicsDevice);
basicEffect.View = Matrix.CreateLookAt(new Vector3(50, 50, 50), new Vector3(0, 0, 0), Vector3.Up);
basicEffect.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45f), GraphicsDevice.Viewport.AspectRatio, 1f, 1000f);
// Inside your Game.Draw method
basicEffect.CurrentTechnique.Passes[0].Apply();
var vertices = new[] { new VertexPositionColor(startPoint, Color.White), new VertexPositionColor(endPoint, Color.White) };
GraphicsDevice.DrawUserPrimitives(PrimitiveType.LineList, vertices, 0, 1);
Я в основном создал простое, BasicEffect
чтобы хранить преобразования вида и проекции, и передал две вершины (положение и цвет) GraphicsDevice.DrawUserPrimitives
методу, который будет отображаться как LineList
.
Конечно, есть много способов его оптимизации, большинство из которых включает создание a VertexBuffer
для хранения всех вершин и пакетирование как можно большего количества строк в один вызов Draw, но это не имеет отношения к вопросу.
Точки рендеринга - метод 1 (SpriteBatch)
Что касается рисования точек, раньше было легко использовать точечные спрайты, но они были удалены из XNA 4.0 . Хотя есть несколько альтернатив. Самый простой способ - создать белый Texture2D
объект 1x1 и отобразить его, используя SpriteBatch
правильное расположение экрана, которое вы можете легко найти с помощью метода Viewport.Project .
Вы можете создать необходимый Texture2D
объект следующим образом:
Texture2D pixel = new Texture2D(GraphicsDevice, 1, 1);
pixel.SetData(new [] { Color.White });
И отрендерить его в местоположении (x, y, z) следующим образом:
// Find screen equivalent of 3D location in world
Vector3 worldLocation = new Vector3(0, 0, 50);
Vector3 screenLocation = GraphicsDevice.Viewport.Project(worldLocation, projectionMatrix, viewMatrix, Matrix.Identity);
// Draw our pixel texture there
spriteBatch.Begin();
spriteBatch.Draw(pixel, new Vector2(screenLocation.X, screenLocation.Y), Color.White);
spriteBatch.End();
Рендеринг линий - Метод 2 (SpriteBatch)
Кроме того, вы также можете рисовать линии, SpriteBatch
используя технику, описанную здесь . В этом случае вам просто нужно найти координаты экранного пространства для обоих концов 3D-линии (снова используя Viewport.Project
), а затем нарисовать регулярную линию между ними.
Точки рендеринга - Метод 2 (Малая линия с примитивами)
В комментариях eBusiness поднял следующий вопрос:
Как насчет линии с одинаковыми начальной и конечной точкой, разве это не даст точку? Или это будет просто невидимым?
Я попробовал, и рендеринг с LineList
использованием одинаковых начальных и конечных точек ничего не нарисовал. Я нашел способ обойти это, хотя, поэтому я опишу это здесь для полноты.
Хитрость заключается не в том, чтобы использовать одинаковые начальную и конечную точки, а в том, чтобы нарисовать линию, настолько маленькую, что при рисовании она выглядит как один пиксель . Итак, чтобы выбрать правильную конечную точку, я сначала спроецировал точку мирового пространства в пространство экрана, переместил ее на один пиксель в пространстве экрана и, наконец, спроецировал ее обратно в мировое пространство. Это конечная точка вашей линии, чтобы она выглядела как точка. Что-то вроде этого:
Vector3 GetEndPointForDot(Vector3 start)
{
// Convert start point to screen space
Vector3 screenPoint = GraphicsDevice.Viewport.Project(start, projection, view, Matrix.Identity);
// Screen space is defined in pixels so adding (1,0,0) moves it right one pixel
screenPoint += Vector3.Right;
// Finally unproject it back into world space
return GraphicsDevice.Viewport.Unproject(screenPoint, projection, view, Matrix.Identity);
}
Затем следует преобразовать его в обычный примитив строки.
демонстрация
Вот что я получил, нарисовав белую линию в трехмерном пространстве, используя примитив списка линий, и красные точки на обоих концах линии, используя текстуру 1x1 и SpriteBatch. Используемый код в значительной степени соответствует тому, что я написал выше. Я также увеличил масштаб, чтобы вы могли убедиться, что они имеют ширину ровно в один пиксель:
Это помечено как XNA, так что я полагаю, это то, о чем вы спрашиваете?
Если это так, эта статья должна быть полезна для строк:
http://msdn.microsoft.com/en-us/library/bb196414(v=xnagamestudio.40).aspx
Конечно, вы можете использовать свои собственные матрицы вида / проекции вместо их. В основном,
PrimitiveType.LineList
илиLineStrip
как рисовать линии на уровне графического процессора.Что касается точек, вы больше не можете использовать PrimitiveType.PointList для рисования точек в XNA 4.0. Вместо этого вам придется сделать очень маленькие треугольники. Этот образец обеспечивает хорошую основу:
http://create.msdn.com/education/catalog/sample/primitives_3d
В предыдущих версиях XNA, если вы используете одну из них, вы можете прочитать часть Point статьи XNA 3.0, опубликованной выше:
http://msdn.microsoft.com/en-us/library/bb196414(v=xnagamestudio.30).aspx
Обратите внимание, что ссылка имеет:
Очевидно, изменить это на
1
.источник