C# OpenGL Проблема при перетаскивании объектов

214
04 февраля 2019, 18:10

Почему при перетаскивании объекта, он перетаскивается не конкретно с курсором, а слегка обтекая его (попытался отобразить на скриншотах ниже)?

На скриншотах, по порядку:
1. Начинаю тянуть за центр объекта
2. Если оттягиваю мышь влево
3. Если оттягиваю мышь вверх

Вправо и вниз, соответственно, ситуация та же.
Ниже приведу фрагменты своего кода.

Объект будто опаздывает за курсором.

Метод при перемещении мыши:

    private void MainWindow_MouseMove(object sender, MouseMoveEventArgs e)
    {
        if (e.Mouse.LeftButton == ButtonState.Pressed)
        {
            if (CardManager.SelectedCard != null)
            {
                Ray.Create(e.X, e.Y, camera);
                Vector3 prePos = CardManager.SelectedCard.IntersectionPoint;
                float planeDist = camera.Position.Z - prePos.Z;
                Vector3 curPos = -Ray.Direction * (planeDist / Ray.Direction.Z) + camera.Position;
                CardManager.SelectedCard.IntersectionPoint = curPos;
                curPos = curPos - prePos;
                CardManager.SelectedCard.object3d.translationMatrix *= Matrix4.CreateTranslation(curPos);
            }
        }
    }

Как я получаю IntersectionPoint из этой строки:

Vector3 prePos = CardManager.SelectedCard.IntersectionPoint;

В этом методе:

    public bool RayIntersect(Vector3 rayStart, Vector3 rayDir, Camera camera)
    {
        Vector3 cmin = Vector3.TransformPosition(object3d.objectMin, object3d.Object3DMatrix);
        Vector3 cmax = Vector3.TransformPosition(object3d.objectMax, object3d.Object3DMatrix);
        Vector3 rs = rayStart;
        Vector3 rd = rayDir;
        Vector3 diff0 = cmin - rs;
        Vector3 diff1 = cmax - rs;
        Vector3 t0 = new Vector3(diff0.X / rd.X, diff0.Y / rd.Y, diff0.Z / rd.Z);
        Vector3 t1 = new Vector3(diff1.X / rd.X, diff1.Y / rd.Y, diff1.Z / rd.Z);
        Vector3 tMin = new Vector3(Math.Min(t0.X, t1.X), Math.Min(t0.Y, t1.Y), Math.Min(t0.Z, t1.Z));
        Vector3 tMax = new Vector3(Math.Max(t0.X, t1.X), Math.Max(t0.Y, t1.Y), Math.Max(t0.Z, t1.Z));
        float tnear = Math.Max(Math.Max(tMin.X, tMin.Y), tMin.Z);
        float tfar = Math.Min(Math.Min(tMax.X, tMax.Y), tMax.Z);
        if (tnear <= tfar)
        {
            IntersectionPoint = rd * tnear + camera.Position;
            return true;
        }
        return false;
    }

Класс Ray:

public static class Ray
{
    public static Vector3 Start = Vector3.Zero;
    public static Vector3 End = Vector3.Zero;
    public static Vector3 Direction = Vector3.Zero;
    public static void Create(int mouse_x, int mouse_y, Camera camera)
    {
        int[] viewport = new int[4];
        GL.GetInteger(GetPName.Viewport, viewport);
        Start = new Vector3(mouse_x, mouse_y, 0.0f).UnProject(camera, new Size(viewport[2], viewport[3]));
        End = new Vector3(mouse_x, mouse_y, 1.0f).UnProject(camera, new Size(viewport[2], viewport[3]));
        Direction = End - Start;
        Direction.Normalize();
    }
}

И метод UnProject:

    public static Vector3 UnProject(this Vector3 mouse, Camera camera, Size viewport)
    {
        Vector4 vec;
        vec.X = 2.0f * mouse.X / viewport.Width - 1;
        vec.Y = -(2.0f * mouse.Y / viewport.Height - 1);
        vec.Z = mouse.Z;
        vec.W = 1.0f;
        Matrix4 projInv = Matrix4.Invert(camera.ProjectionPerspectiveMatrix);
        Matrix4 viewInv = Matrix4.Invert(camera.ViewMatrix);
        Vector4.Transform(ref vec, ref projInv, out vec);
        Vector4.Transform(ref vec, ref viewInv, out vec);
        if (vec.W > 0.000001f || vec.W < -0.000001f)
        {
            vec.X /= vec.W;
            vec.Y /= vec.W;
            vec.Z /= vec.W;
        }
        return vec.Xyz;
    }
Answer 1

Проблема была в неверном способе нахождения точки пересечения луча и объекта (IntersectionPoint) в методе RayIntersect.

Нужно заменить

IntersectionPoint = rd * tnear + camera.Position;

на

IntersectionPoint = rd * tnear + rs;
READ ALSO
Поворот объекта через transform.Rotate

Поворот объекта через transform.Rotate

Как повернуть объект по направлению к другому через transformRotate только по оси у?

206
Репозиторий &ldquo;два-в-одном&rdquo;

Репозиторий “два-в-одном”

Есть некоторый сервис, который дёргает два репозитория (первый - к сущности Order, второй - к сущности OrderPosition) и возвращает уже собранный заказ...

253
Как эффективно затереть данные

Как эффективно затереть данные

Задача: повредить файл, для обеспечения невозможности его чтения(И удачного восстановления если его удалить программным способом, на той...

395
Bluetooth LE не обнаруживает устройства

Bluetooth LE не обнаруживает устройства

Делаю попытку обнаружения устройств с помощью Bluetooth LE, сделал как написано в этой библиотеке для Xamarin, однако обнаруженных устройств 0

207