Как да получите лъч от „gluUnProject“

основният ми въпрос е - какъв е правилният начин да използвам "gluUnProject", за да получа лъч или нормален вектор от моята позиция на мишката/курсора.

Преобразувах кода „gluUnProject“ в C# от C кода на mesa glu.

public Vector3 UnProject(Matrix4 projectionMatrix, Matrix4 viewMatrix, int viewX, int viewY, int viewWidth, int viewHeight)
{
    var finalMatrix = viewMatrix.Multiply(projectionMatrix).Invert();

    var vec = new Vector4(this, 1);
    vec.X = (vec.X - viewX) / viewWidth;
    vec.Y = (vec.Y - viewY) / viewHeight;
    vec = (vec * 2) - 1;
    vec.Y = -vec.Y;

    var outVec = vec.Transform(finalMatrix);
    outVec.X /= outVec.W;
    outVec.Y /= outVec.W;
    outVec.Z /= outVec.W;

    return outVec.ToVector3();
}

След това извиквам този метод от моя обект Camera:

public Vector3 UnProject(Vector3 screenPosition)
{
    return screenPosition.UnProject(ProjectionMatrix, ViewMatrix, ViewPort.Location.X, ViewPort.Location.Y, ViewPort.Size.X, ViewPort.Size.Y);
}

За да получа своя нормален вектор от лъча, правя:

var rayLoc = camera.UnProject(new Vector3(Game.Mouse.Location, 0));
var rayLoc2 = camera.UnProject(new Vector3(Game.Mouse.Location, 1));
var rayDirection = (rayLoc2 - rayLoc).Normalize();

Всичко работи добре, докато не преместя моята точка LookAt над, да речем, 1 в X и завъртя камерата малко по оста X и Y. След това векторът вече не е правилен. Не знам какво правя погрешно??

РЕДАКТИРАНЕ: След по-внимателно разглеждане мисля, че моят метод Matrix4.Invert може да е причината. Опитвам се да използвам Row major, някакви идеи?

public Matrix4 Invert()
{
    var mat = new Matrix4(
        new Vector4(
            Y.Y*Z.Z*W.W - Y.Y*Z.W*W.Z - Z.Y*Y.Z*W.W + Z.Y*Y.W*W.Z + W.Y*Y.Z*Z.W - W.Y*Y.W*Z.Z,
            -Y.X*Z.Z*W.W + Y.X*Z.W*W.Z + Z.X*Y.Z*W.W - Z.X*Y.W*W.Z - W.X*Y.Z*Z.W + W.X*Y.W*Z.Z,
            Y.X*Z.Y*W.W - Y.X*Z.W*W.Y - Z.X*Y.Y*W.W + Z.X*Y.Y*W.Y + W.X*Y.Y*Z.W - W.X*Y.W*Z.Y,
            -Y.X*Z.Y*W.Z + Y.X*Z.Z*W.Y + Z.X*Y.Y*W.Z - Z.X*Y.Z*W.Y - W.X*Y.Y*Z.Z + W.X*Y.Z*W.Y),
        new Vector4(
            -X.Y*Z.Z*W.W + X.Y*Z.W*W.Z + Z.Y*X.Z*W.W - Z.Y*X.W*W.Z - W.Y*X.Z*Z.W + W.Y*X.W*Z.Z,
            X.X*Z.Z*W.W - X.X*Z.W*W.Z - Z.X*X.Z*W.W + Z.X*X.W*W.Z + W.X*X.Z*Z.W - W.X*X.W*Z.Z,
            -X.X*Z.Y*W.W + X.X*Z.W*W.Y + Z.X*X.Y*W.W - Z.X*X.W*W.Y - W.X*X.Y*Z.W + W.X*X.W*Z.Y,
            X.X*Z.Y*W.Z - X.X*Z.Z*W.Y - Z.X*X.Y*W.Z + Z.X*X.Z*W.Y + W.X*X.Y*Z.Z - W.X*X.Z*Z.Y),
        new Vector4(
            X.Y*Y.Z*W.W - X.Y*Y.W*W.Z - Y.Y*X.Z*W.W + Y.Y*X.W*W.Z + W.Y*X.Z*Y.W - W.Y*X.W*Y.Z,
            -X.X*Y.Z*W.W + X.X*Y.W*W.Z + Y.X*X.Z*W.W - Y.X*X.W*W.Z - W.X*X.Z*Y.W + W.X*X.W*Y.Z,
            X.X*Y.Y*W.W - X.X*Y.W*W.Y - Y.X*X.Y*W.W + Y.X*X.W*W.Y + W.X*X.Y*Y.W - W.X*X.W*Y.Y,
            -X.X*Y.Y*W.Z + X.X*Y.Z*W.Y + Y.X*X.Y*W.Z - Y.X*X.Z*W.Y - W.X*X.Y*Y.Z + W.X*X.Z*Y.Y),
        new Vector4(
            -X.Y*Y.Z*Z.W + X.Y*Y.W*Z.Z + Y.Y*X.Z*Z.W - Y.Y*X.W*Z.Z - Z.Y*X.Z*Y.W + Z.Y*X.W*Y.Z,
            X.X*Y.Z*Z.W - X.X*Y.W*Z.Z - Y.X*X.Z*Z.W + Y.X*X.W*Z.Z + Z.X*X.Z*Y.W - Z.X*X.Z*Y.Z,
            -X.X*Y.Y*Z.W + X.X*Y.W*Z.Y + Y.X*X.Y*Z.W - Y.X*X.W*Z.Y - Z.X*X.Y*Y.W + Z.X*X.W*Y.Y,
            X.X*Y.Y*Z.Z - X.X*Y.Z*Z.Y - Y.X*X.Y*Z.Z + Y.X*X.Z*Z.Y + Z.X*X.Y*Y.Z - Z.X*X.Z*Y.Y));

    Num delta = X.X*mat.X.X + X.Y*mat.Y.X + X.Z*mat.Z.X + X.W*mat.W.X;
    delta = 1 / delta;
    return mat * delta;
}

person zezba9000    schedule 26.04.2012    source източник


Отговори (2)


Обикновено правя това:

GLint m_viewport[4];
GLdouble m_modelview[16];
GLdouble m_projection[16];

glGetIntegerv(GL_VIEWPORT, m_viewport);
glGetDoublev(GL_MODELVIEW_MATRIX, m_modelview);
glGetDoublev(GL_PROJECTION_MATRIX, m_projection);

GLdouble rx, ry, rz;
gluUnProject(x, y, depth, m_modelview, m_projection, m_viewport, &rx, &ry, &rz);

Където x и y са координатите на мишката, а дълбочината е някаква стойност в (0, 1] - обикновено вземам 0,5.

person Kristian Duske    schedule 26.04.2012

Оказа се, че моят метод Matrix4.Invert е грешен. Използвах OpenTK за справка при създаването на метод за обръщане на главния ред.

РЕДАКТИРАНЕ: Всъщност „https://github.com/Dav1dde/gl3n“ имаше по-добър начин за това.

person zezba9000    schedule 27.04.2012