[1.7.10] Как получить координаты камеры?

Версия Minecraft
1.7.10
API
Forge
39
8
5
Мне нужно повернуть модельку игрока (например, чтобы Стив плыл на спине). Это можно сделать в ивенте RenderPlayerEvent.Pre, но есть проблема - отрисовка в этом ивенте происходит относительно камеры, а не относительно координат игрока. Поэтому необходимо как-то добыть координаты камеры, чтобы перенестись на игрока и уже на нужных координатах выполнить GL11.glRotated. В классе Minecraft камеры нет, а кроме этого класса вообще без понятия где она может быть...
 
Последнее редактирование:
Решение
После долгих тестов выяснил, что всё-таки точка отсчёта в этом ивенте - глаза игрока, а координатные оси совпадают с мировыми (100, 010 и 001). Почему фодж не написали это в доках... Вот примерный код для поворота игрока на спину:

Java:
@SubscribeEvent
public void playerRender1(RenderPlayerEvent.Pre event){
    GL11.glPushMatrix();
    EntityPlayer player = event.entityPlayer;
    Vec3 eyes = precisePosition(Minecraft.getMinecraft().renderViewEntity, event.partialRenderTick);
    Vec3 relToWorld = precisePosition(player, event.partialRenderTick);
    Vec3 relToEyes = subtract(relToWorld, eyes);
    if (player != Minecraft.getMinecraft().thePlayer) {
        relToEyes = relToEyes.addVector(0, 1.62, 0); //координаты Minecraft.thePlayer=...
39
8
5
Похоже, позиция камеры собирается по кусочкам в EntityRenderer.setupCameraTransform(partialTicks, anaglyph), единственный способ их получить - проделать всё то же самое, что и в этом методе... И всё равно там фордж свои ивенты кидает, так что какой-то другой мод может вмешаться и всё испортить
 
39
8
5
После долгих тестов выяснил, что всё-таки точка отсчёта в этом ивенте - глаза игрока, а координатные оси совпадают с мировыми (100, 010 и 001). Почему фодж не написали это в доках... Вот примерный код для поворота игрока на спину:

Java:
@SubscribeEvent
public void playerRender1(RenderPlayerEvent.Pre event){
    GL11.glPushMatrix();
    EntityPlayer player = event.entityPlayer;
    Vec3 eyes = precisePosition(Minecraft.getMinecraft().renderViewEntity, event.partialRenderTick);
    Vec3 relToWorld = precisePosition(player, event.partialRenderTick);
    Vec3 relToEyes = subtract(relToWorld, eyes);
    if (player != Minecraft.getMinecraft().thePlayer) {
        relToEyes = relToEyes.addVector(0, 1.62, 0); //координаты Minecraft.thePlayer= координаты глаз, но координаты других игроков - это координаты их нижних точек. Так что надо поднять точку поворота, чтобы и ваш персонаж, и другие игроки крутились одинаково.
    }

    GL11.glTranslated(relToEyes.xCoord, relToEyes.yCoord, relToEyes.zCoord);
    Vec3 look = player.getLookVec();
    Vec3 yAxis = Vec3.createVectorHelper(0, 1, 0);
    Vec3 normal = look.crossProduct(yAxis).normalize();
    GL11.glRotated(90, normal.xCoord, normal.yCoord, normal.zCoord);
    GL11.glTranslated(-relToEyes.xCoord, -relToEyes.yCoord, -relToEyes.zCoord);
}

@SubscribeEvent
public void playerRender2(RenderPlayerEvent.Post event){
    GL11.glPopMatrix();
}

public static Vec3 precisePosition(Entity entity, float partialTicks){
    return Vec3.createVectorHelper(
        entity.lastTickPosX + (entity.posX - entity.lastTickPosX) * partialTicks,
        entity.lastTickPosY + (entity.posY - entity.lastTickPosY) * partialTicks,
        entity.lastTickPosZ + (entity.posZ - entity.lastTickPosZ) * partialTicks);
}

public static Vec3 subtract(Vec3 a, Vec3 b){
    return Vec3.createVectorHelper(a.xCoord - b.xCoord, a.yCoord - b.yCoord, a.zCoord - b.zCoord);
}

Теперь про камеру, хоть это и оказалось не нужно. Вот так можно получить координаты сущности в пространстве камеры (нулевые координаты - точка, откуда мы видим, ось X идёт слева направо, Y - снизу вверх, Z - в глубь экрана):

Java:
public static Vec3 relToCamera(Vec3 relToWorld, float partialTicks){
    Vec3 eyesInWorld = precisePosition(Minecraft.getMinecraft().renderViewEntity, partialTicks);
    FloatBuffer buf = BufferUtils.createFloatBuffer(16);
    GL11.glGetFloat(GL11.GL_MODELVIEW_MATRIX, buf);
    Matrix4f mat = (Matrix4f) new Matrix4f().load(buf);
    Vec3 relToEyes = subtract(relToWorld, eyesInWorld);
    Vec3 relToCamera = multiply(mat, relToEyes);
    return Vec3.createVectorHelper(relToCamera.xCoord, relToCamera.yCoord, -relToCamera.zCoord); //Почему z меняет знак? А чёрт знает...
}

public static Vec3 multiply(Matrix4f m, Vec3 v){
    return Vec3.createVectorHelper(
        v.xCoord * m.m00 + v.yCoord * m.m10 + v.zCoord * m.m20 + m.m30,
        v.xCoord * m.m01 + v.yCoord * m.m11 + v.zCoord * m.m21 + m.m31,
        v.xCoord * m.m02 + v.yCoord * m.m12 + v.zCoord * m.m22 + m.m32);
}
Если понадобятся оси - их можно легко получить, домножив матрицу на (1,0,0) и т.д., либо, что быстрее, просто взяв нужные числа из неё (Vec3 xAxis = Vec3.createVectorHelper(mat.m00, mat.m01, mat.m02 и т.д.).
Чтобы получить координаты камеры в мировом пространстве, придётся обратить mat и посмотреть на последний столбец. Мне это делать впадлу, т.к. для этого нужно решить систему уравнений, но это делается достаточно быстро и просадок фпс не вызовет.
 
Сверху