Поле зрения и координатный перевод - PullRequest
0 голосов
/ 16 февраля 2011

В моей программе у меня есть вход и выход. Ввод представляет собой 2D-позицию, которая может варьироваться от (0,0) до (240,360). Мой вывод - трехмерный мир, созданный в XNA.

Однако я не смог понять, как перевести точки из 2D-сетки в 3D. Я хочу иметь возможность переводить точки так, чтобы (0,0) приводил к XNA, показывающему точку в работе в верхнем левом углу того, что может видеть камера. Кроме того, я хочу, чтобы точка (240 360) отображалась в нижнем правом углу того, что может видеть камера. Значение Z будет равно нулю (оно изменится, но это выходит за рамки этого вопроса).

Как я могу определить, где находятся углы обзора моей камеры? Вот как я рисую свои объекты в трехмерном мире.

        Vector3 camPos = new Vector3(0.0f, 0.0f, 500.0f);

        Matrix view = Matrix.CreateLookAt(camPos, Vector3.Zero, Vector3.Up);
        Matrix proj = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, GraphicsDevice.DisplayMode.AspectRatio, 1, 10000);
        Matrix ballWorld = Matrix.Identity;

        //rotate it so that it is always facing foward
        ballWorld.Forward = direction;
        ballWorld.Up = Vector3.Up;
        ballWorld.Right = Vector3.Cross(direction, Vector3.Up);

        foreach (SphereObject so in blobs) {
            Matrix sphereWorld = ballWorld;
            sphereWorld *= Matrix.CreateTranslation(so.Position);
            sphereWorld *= Matrix.CreateScale(so.Scale);

            so.SphereModel.Draw(sphereWorld, view, proj);
        }

И вот где я получаю точки из 2D-плоскости и создаю объект SphereObject

    public void CreateNewBlob(System.Drawing.Point p) {
        Random rand = new Random();

        SphereObject so = new SphereObject(model, new Vector3(p.X, p.Y, 0));
        so.SetColor(new Color((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble()));

        blobs.Add(so);
    }

Ответы [ 2 ]

0 голосов
/ 17 февраля 2011

Вы уверены, что не хотите использовать ортографическую проекцию ?

enter image description here

0 голосов
/ 17 февраля 2011

Как насчет отображения 2D-точки на область просмотра, затем проецирования луча из этой точки и использования его для нахождения самой дальней видимой точки на луче на основе дальней плоскости отсечения?

        float farplane = 1000;

        Matrix proj = Matrix.CreateLookAt(Vector3.Zero, Vector3.Forward, Vector3.Up);
        Matrix view = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, this.GraphicsDevice.Viewport.AspectRatio, 1, farplane);

        Vector2 Coord = new Vector2(10,10);     //between 0,0 and 240,360

        Coord.X = Coord.X * (GraphicsDevice.Viewport.Width / 240);
        Coord.Y = Coord.Y * (GraphicsDevice.Viewport.Height / 360);

        Ray r = ProjectRayFromPointOnScreen((int)Coord.X, (int)Coord.Y, proj, view);

        Vector3 ballpos = r.Position + (r.Direction *= (farplane - 1)); //Move just inside the far plane so its not clipped by accident

    public Ray ProjectRayFromPointOnScreen(int x, int y, Matrix ProjectionMatrix, Matrix ViewMatrix)
    {
        Vector3 nearsource = new Vector3(x, y, 0);
        Vector3 farsource = new Vector3(x, y, 1);

        /* The Unproject method: http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.graphics.viewport.unproject.aspx */

        GraphicsDevice graphics = this.GraphicsDevice;

        Vector3 startpoint = graphics.Viewport.Unproject(nearsource,
                                                         ProjectionMatrix,
                                                         ViewMatrix,
                                                         Matrix.Identity);
        Vector3 endpoint = graphics.Viewport.Unproject(farsource,
                                                       ProjectionMatrix,
                                                       ViewMatrix,
                                                       Matrix.Identity);

        Vector3 direction = endpoint - startpoint;
        direction.Normalize();

        Ray r = new Ray(startpoint, direction);
        return r;
    }

Кажется, это работает, хотя я не уверен, какой именно эффект вы пытаетесь достичь в своем приложении. Удачи!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...