Получить координаты пространства экрана определенных вершин 3D-модели, когда они видны - PullRequest
5 голосов
/ 26 мая 2011

Я хотел бы визуализировать модель, а затем, если отдельные вершины (как бы я их пометил?) Были видны, я хочу визуализировать что-то 2D там, где они есть.

Как мне это сделать?

Ответы [ 3 ]

4 голосов
/ 26 мая 2011

Прежде всего, вам нужно, чтобы ваша позиция вершины была равна Vector4 (перспективные проекции требуют использования однородных координат; установите W = 1).Я предполагаю, что вы знаете, какую вершину вы хотите и как получить ее положение.Его положение будет в пространстве модели.

Теперь просто преобразуйте эту точку в пространство проекции.То есть - умножьте это на свою матрицу проекции мира.То есть:

Vector4 position = new Vector4(/* your position as a Vector3 */, 1);
IEffectMatrices e = /* a BasicEffect or whatever you are using to render with */
Matrix worldViewProjection = e.World * e.View * e.Projection;
Vector4 result = Vector4.Transform(position, worldViewProjection);
result /= result.W;

Теперь ваш результат будет в проекционном пространстве, которое (-1, -1) в левом нижнем углу экрана и (1,1) в верхнем правом углу,Если вы хотите получить свою позицию в клиентском пространстве (что и использует SpriteBatch), просто преобразуйте ее, используя обратную матрицу, которая соответствует неявной матрице проекции вида, используемой SpriteBatch.

Viewport vp = GraphicsDevice.Viewport;
Matrix invClient = Matrix.Invert(Matrix.CreateOrthographicOffCenter(0, vp.Width, vp.Height, 0, -1, 1));
Vector2 clientResult = Vector2.Transform(new Vector2(result.X, result.Y), invClient);

Отказ от ответственности: я не проверял ни один из этого кода.

(Очевидно, чтобы проверить, видима ли конкретная вершина или нет, просто проверьте, находится ли она в (-1, -1) для(1,1) диапазон в проекционном пространстве.)

1 голос
/ 26 мая 2011

Взгляните на особенности выбраковки окклюзии вашего двигателя. Для XNA вы можете обратиться к руководству по фреймворку (с образцами) здесь.

http://roecode.wordpress.com/2008/02/18/xna-framework-gameengine-development-part-13-occlusion-culling-and-frustum-culling/

1 голос
/ 26 мая 2011

Вероятно, лучший способ сделать это с BoundingFrustrum. Это в основном как прямоугольник, который расширяется в определенном направлении, подобно тому, как работает камера игрока. Затем вы можете проверить, содержится ли заданная точка в BoundingFrustrum, и, если это так, визуализировать ваш объект.

В основном, форма, которую он делает, выглядит следующим образом: Shape of a BoundingFrustrum

Пример:

// A view frustum almost always is initialized with the ViewMatrix * ProjectionMatrix
BoundingFrustum viewFrustum = new BoundingFrustum(ActivePlayer.ViewMatrix * ProjectionMatrix);

// Check every entity in the game to see if it collides with the frustum.
foreach (Entity sourceEntity in entityList)
{
    // Create a collision sphere at the entities location. Collision spheres have a
    // relative location to their entity and this translates them to a world location.
    BoundingSphere sourceSphere = new BoundingSphere(sourceEntity.Position,
                                  sourceEntity.Model.Meshes[0].BoundingSphere.Radius);

    // Checks if entity is in viewing range, if not it is not drawn
    if (viewFrustum.Intersects(sourceSphere))
        sourceEntity.Draw(gameTime);
}

Пример на самом деле предназначен для отбраковки всех объектов в игре, но его можно довольно легко изменить для обработки того, что вы хотите сделать.

Пример источника: http://nfostergames.com/Lessons/SimpleViewCulling.htm

Чтобы получить координаты вашего мира в пространстве экрана, взгляните на Viewport.Project .

...