Follow along with the video below to see how to install our site as a web app on your home screen.
Примечание: This feature may not be available in some browsers.
Вот есть гуи, в гуе мышь не привязана к центру. Координаты мыши в двух измерениях, в пределах разрешения экрана. Вот, хочу узнать координаты блока под этим самым курсором мышиAgravaine написал(а):Всмысле в открытом гуи?
Смотри. Ты когда-нибудь строил что-то в мкэдите? В нём есть замечательное выделение блоков. Ты тыкаешь в любое место в мире - редактор узнаёт координаты блока - начинает выделять сетку. Вот такую штуку хочу замутить в майнкрафтеAgravaine написал(а):А, типо вид сверху?
Не выйдет. Придется рендерить свой маленький мир внутри гуи с включенной глубиной.desu написал(а):Вот есть гуи, в гуе мышь не привязана к центру. Координаты мыши в двух измерениях, в пределах разрешения экрана. Вот, хочу узнать координаты блока под этим самым курсором мышиAgravaine написал(а):Всмысле в открытом гуи?
Не знаю, или я объяснил не так, или вы не так поняли. Мне не надо ничего рендерить, мне просто нужно получить блок на который указывает мой курсорDragon2488 написал(а):Не выйдет. Придется рендерить свой маленький мир внутри гуи с включенной глубиной.desu написал(а):Вот есть гуи, в гуе мышь не привязана к центру. Координаты мыши в двух измерениях, в пределах разрешения экрана. Вот, хочу узнать координаты блока под этим самым курсором мышиAgravaine написал(а):Всмысле в открытом гуи?
Ох чёрт, у меня с ГЛ всё очень плохо. Да и с векторами, синусами и косинусами. Зря я не учил матан, позор мне. СпасибоGloomyFolken написал(а):Неужели, в кой-то веки интересный вопрос.
Более-менее подробная статья, да еще и на русском! Справишься сам с портированием на java/lwjgl? Могу помочь. Ну и сразу небольшая подсказка: функция gluUnProject в lwjgl находится в классе Project.
Да что-то ничерта у меня не выйдет, я перестал понимать начиная с "буффер глубины", печальGloomyFolken написал(а):Ну и естественно вариант решения с чтением из буфера глубины будет работать только если там действительно то, что нужно в буфере глубины: что-то может перекрывать блок, и тогда он выберется неправильно. Если это проблема, то стоит всё-таки отказаться от чтения из буфера глубины и вызвать World#clip() (или как там называется метод на рейтрейсинг блоков между двумя точками в нужной тебе версии), указав начало и конец "селектирующего отрезка", как его обзывают в той статье.
//не стоит каждый раз создавать новый буфер, это чревато проблемами с производительностью
private static IntBuffer viewportBuf = BufferUtils.createIntBuffer(16);
private static FloatBuffer projectionBuf = BufferUtils.createFloatBuffer(16);
private static FloatBuffer modelviewBuf = BufferUtils.createFloatBuffer(16);
/**
* Метод использует текущие матрицу проекции и modelview матрицу, так что вызывать
* его во время отрисовки ГУИ - не дело. Вызывай в RenderWorldLastEvent, например
*/
public MovingObjectPosition calcBlockMouseOver(World world){
GL11.glGetInteger(GL11.GL_VIEWPORT, viewportBuf);
GL11.glGetFloat(GL11.GL_PROJECTION_MATRIX, projectionBuf);
GL11.glGetFloat(GL11.GL_MODELVIEW_MATRIX, modelviewBuf);
float vx = Mouse.getX();
// я не очень помню, где находится 0 по оси Y: сверху или снизу.
// если сверху, то vy = mc.displayHeight - Mouse.getY().
float vy = Mouse.getY();
// этот буфер не нативный, так что всё ОК
FloatBuffer resultBuf = FloatBuffer.allocate(3);
// В той статье предполагается ставить z на -1,
// но я не уверен, что оно будет правильно работать.
// Всё-таки миниальная глубина - это 0, а не -1. Решай сам, кому верить
Project.gluUnProject(vx, vy, -1, modelviewBuf, projectionBuf, viewportBuf, resultBuf);
Vec3 p1 = Vec3.createVectorHelper(resultBuf.get(0), resultBuf.get(1), resultBuf.get(2));
Project.gluUnProject(vx, vy, 1, modelviewBuf, projectionBuf, viewportBuf, resultBuf);
Vec3 p2 = Vec3.createVectorHelper(resultBuf.get(0), resultBuf.get(1), resultBuf.get(2));
//И всё бы ничего, но p1 и p2 центрированы то ли к камере, то ли к голове персонажа.
//Склоняюсь ко второму варианту. Поправим это.
p1 = p1.addVector(RenderManager.renderPosX, RenderManager.renderPosY, RenderManager.renderPosZ);
p2 = p2.addVector(RenderManager.renderPosX, RenderManager.renderPosY, RenderManager.renderPosZ);
return world.clip(p1, p2);
}
Ох чёрт! Я когда писал сюда, я не расчитывал на помощь. Пошёл качать сурсы форжа, в который раз. Спасибос от души простоGloomyFolken написал(а):Конкретно здесь матан не особо нужен, потому что задачу уже десять раз решили до нас
Попробовал портировать на lwjgl, но не тестил. Надеюсь, сможешь отдебажить.
Код://не стоит каждый раз создавать новый буфер, это чревато проблемами с производительностью private static IntBuffer viewportBuf = BufferUtils.createIntBuffer(4); private static FloatBuffer projectionBuf = BufferUtils.createFloatBuffer(16); private static FloatBuffer modelviewBuf = BufferUtils.createFloatBuffer(16); /** * Метод использует текущие матрицу проекции и modelview матрицу, так что вызывать * его во время отрисовки ГУИ - не дело. Вызывай в RenderWorldLastEvent, например */ public MovingObjectPosition calcBlockMouseOver(World world){ GL11.glGetInteger(GL11.GL_VIEWPORT, viewportBuf); GL11.glGetFloat(GL11.GL_PROJECTION_MATRIX, projectionBuf); GL11.glGetFloat(GL11.GL_MODELVIEW_MATRIX, modelviewBuf); float vx = Mouse.getX(); // я не очень помню, где находится 0 по оси Y: сверху или снизу. // если сверху, то vy = mc.displayHeight - Mouse.getY(). float vy = Mouse.getY(); // этот буфер не нативный, так что всё ОК FloatBuffer resultBuf = FloatBuffer.allocate(3); // В той статье предполагается ставить z на -1, // но я не уверен, что оно будет правильно работать. // Всё-таки миниальная глубина - это 0, а не -1. Решай сам, кому верить Project.gluUnProject(vx, vy, -1, modelviewBuf, projectionBuf, viewportBuf, resultBuf); Vec3 p1 = Vec3.createVectorHelper(resultBuf.get(0), resultBuf.get(1), resultBuf.get(2)); Project.gluUnProject(vx, vy, 1, modelviewBuf, projectionBuf, viewportBuf, resultBuf); Vec3 p2 = Vec3.createVectorHelper(resultBuf.get(0), resultBuf.get(1), resultBuf.get(2)); //И всё бы ничего, но p1 и p2 центрированы то ли к камере, то ли к голове персонажа. //Склоняюсь ко второму варианту. Поправим это. p1.addVector(RenderManager.renderPosX, RenderManager.renderPosY, RenderManager.renderPosZ); p2.addVector(RenderManager.renderPosX, RenderManager.renderPosY, RenderManager.renderPosZ); return world.clip(p1, p2); }
Много интересующихся видать. ХехеGloomyFolken написал(а):
Например, блок может заслонять какая-нибудь сущность. Тогда в буфере глубины значение окажется меньше нужного. А ещё нужно вспоминать, как из числа в буфере глубины получить расстояние до объекта:GloomyFolken написал(а):Ну и естественно вариант решения с чтением из буфера глубины будет работать только если там действительно то, что нужно в буфере глубины: что-то может перекрывать блок, и тогда он выберется неправильно. Если это проблема, то стоит всё-таки отказаться от чтения из буфера глубины и вызвать World#clip() (или как там называется метод на рейтрейсинг блоков между двумя точками в нужной тебе версии), указав начало и конец "селектирующего отрезка", как его обзывают в той статье.
private static float depthToDistance(float zNear, float zFar, float zValue){
float a = zFar / (zFar - zNear);
float b = zFar * zNear / (zNear - zFar);
return b/(zValue-a);
}
Ну, вместо "отдельного буфера глубины" можно просто трейсить, когда блоки уже отрисовались, а остальное ещё нетOldestkon написал(а):Не, не. Я в общем случае рассматриваю. Не именно для кубача.
Даже если для кубача, допустим, у нас есть отдельный буфер глубины ОНЛИ для блоков. В таком случае, имеет ли смысл такая оптимизация? Или всё засрет скорость доступа к видеопамяти и текстуре буфера глубины?