OBJ на 1.12 (Рендер)

Версия Minecraft
1.12.2
355
2
17
Добро, помогите войти в курс дела как обстоят дела с Obj на 1.12+

Необходимо подгрузить напрямую OBJ (Без дополнительных json файлов) и отрисовать в списке GLList.
Попробовал подгружать так:

Java:
IModel model = OBJLoader.INSTANCE.loadModel(
new ResourceLocation(modelPath));

А отрисовал в листе так (нашел тут на форуме)

Java:
GL11.glNewList(indexRenderer, GL11.GL_COMPILE);

Function<ResourceLocation, TextureAtlasSprite> spriteFunction = location -> Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite(location.toString());
model.bake(new OBJModel.OBJState(ImmutableList.of("base"), false), DefaultVertexFormats.ITEM, spriteFunction);

GL11.glEndList();

Соответственно ничего не сработало, возможно проблема еще крылась где-то в парсинге, ибо вывело в консоль:

OBJLoader.Parser: command 's' (model: 'default/default.obj') is not currently supported, skipping. Line: 52 's 1'

Как собственно отрисовать то, что на 1.7.10 работает хорошо?
 
1,173
28
168
Нормали то строятся (даже если они уже есть у полигона) еще при загрузке obj модели. Только вот на некоторых моделях они строятся довольно кривовато, и мне пришлось хукать расчет нормалей, дабы выглядело это визуально без артефактов. Даже если мы экспортировали модельку с нормалями ПРАВИЛЬНЫМИ, фордж все равно зачем то пересобирает их при загрузке, что довольно странно.
tessellator.setNormal() здесь важен, иначе освещение будет из жопы, я уже проверял это хуками. Мне кажется ты не понял просто) Здесь немножко другая роль метода setNormal(), нежели простой расчет и установка нормали к полигону. Тут этот метод как раз важен
 
1,038
57
229
ты говоришь про инструмент, я про OpenGL. Не обязательно строить именно в нём. tesselator это инструмент по работе с буффером данных, FloatBuffer и IntBuffer. Которые в последствии идут как данные для шейдера: соответственно информация о точках и информация об полигонах (индексах точек).
Можно строить напрямую в OpenGL, не всё, а большинство моделей которые для Minecraft (low poly flat). Модели же где используются карты нормали, карты освещенности, карты свечения (glow). Там, где ты и сказал, где требуется (использовать flat и smoth) на одной и той же модели, карта нормали просто необходима. Но это на столько редкий случай для Minecraft... что, нет смысла его рассматривать.
В конце концов можно использовать свой собственный шейдер, который особо не нагрузит систему и который не будет требовать карту нормали (как и сам opengl). Или же наоборот, требовать её наличия.
Сама карта нормалей служит как раз для этих целей, показать круг кругом (но это не будет кругом, обмануть глаз, картинка ниже)
modeling_meshes_editing_normals_example-smooth.png

обрати внимание на рёбра, по ним всё равно видно что модель угловатая
f09d247231.jpg


а вот та же модель, но flat
modeling_meshes_editing_normals_example-flat.png

А теперь вы готовы чтобы посмотреть на это
activa-3g-lowpoly-two-vehicle-3d-model-low-poly-max-obj-fbx-mtl.jpg

на этой модели чётко видно где Flat, а где Smooth. Я такого в Minecraft не встречал))
 
Последнее редактирование:
355
2
17
Ну с нормалями ладно, вроде нашел аналогию, осталось только найти аналог tessellator.startDrawing(glDrawingMode);
Ранее там был один аргумент, который устанавливал мод, а сейчас буффер требует два begin(int glMode, VertexFormat format)
И во всех местах теперь четко указан какой мод и какой формат. Как понять какой мод и формат у Obj? Если он по сути может разным задаваться. Старый метод:


Java:
    public void renderAll()
    {
        Tessellator tessellator = Tessellator.instance;

        if (currentGroupObject != null)
        {
            tessellator.startDrawing(currentGroupObject.glDrawingMode);
        }
        else
        {
            tessellator.startDrawing(GL11.GL_TRIANGLES);
        }
        tessellateAll(tessellator);

        tessellator.draw();
    }
 
5,018
47
783
я как то рисовал тесселятором баундбокс
возможно это то что тебе надо
Java:
    public  void drawBoundingBox(double minX, double minY, double minZ, double maxX, double maxY, double maxZ, float red, float green, float blue, float alpha,EnumFacing facing, IBlockState state, BlockPos pos, World world)
    {
        Tessellator tessellator = Tessellator.getInstance();
        BufferBuilder bufferbuilder = tessellator.getBuffer();
        bufferbuilder.begin(3, DefaultVertexFormats.POSITION_COLOR);
        drawBoundingBox(bufferbuilder, minX, minY, minZ, maxX, maxY, maxZ, red, green, blue, 0.4F, facing, state,pos,world);
        tessellator.draw();
    }
 

tox1cozZ

aka Agravaine
8,454
598
2,890
Ну, рисовать нужно только GL11.GL_TRIANGLES и модель всегда нужно триангулировать. Это делают везде и никто не использует другие режимы.
По поводу vertexState, наверное ж надо position, texture, normal.
 
1,173
28
168
модель всегда нужно триангулировать
не всегда. Если модель/меш состоят только из квадов, оно и их зажует. Фордж не могет в совмещение трианглов и квадов одновременно у модели/меша
 
7,099
324
1,509
Фордж не могет в совмещение трианглов и квадов одновременно у модели/меша
Чтобы их совместить достаточно каждый квад порезать на два треугольника
В графике нужно все рисовать треугольниками
А почему?
 
355
2
17
Использовал bufferBuilder.begin(currentGroupObject.glDrawingMode, DefaultVertexFormats.POSITION_TEX_NORMAL);
Страшно, вырубай
1580987325468.png

upd. POSITION_TEX пофиксило

upd 2.
Но текстуры засвеченные, либо все еще не верный формат выбран или все-таки из-за того что в Face я закоментировал установку этих нормалей как раз таки.
worldRenderer.putNormal(faceNormal.x, faceNormal.y, faceNormal.z); иначе выдавало ошибку IndexOutOfBoundsException
 
Последнее редактирование:
1,038
57
229
Это все делают программы при экспорте моделей
это делают лишь потому что треугольников в любой модели больше чем квадов. И поэтому делать два буфера лень. Но если всё наоборот, то будет меньше производительность, чем два буфера. Например 2 миллиона квадов превращаются в 4 миллиона треугольников. И точек, каждому из них надо соответственно в два раза больше. А на это надо куда больше ресурсов.
Весь код что я видел по скелетной анимации основан тоже на треугольниках, поэтому очень многие просто не понимают как сделать по другому и используют разложение на треугольники. Уметь пользоваться чем то и понимать в этом, это не одно и тоже. Требуется больше знаний, которых обычно некогда учить.
Ещё некоторые модели лучше делать GL_TRIANGLE_STRIP, это аж на 2 вершины меньше чем обычный. И если у вас 2 миллиона вершин, то это чуть 670к. Это ощутим, поверьте, особенно на слабых устройствах.
А GL_TRIANGLE, это просто пушка по воробьям, то есть решение подходит для большинства задач (а это не мало).
 
1,038
57
229
индексы не помогут, потому что кроме этого ещё надо привязать как то индексы UV.
вот какой UV у этой точки?
be74a3cc32.jpg

у этой вершины их три варианта. Один для полигона слева, один для полигона сверху и один для полигона смотрящего на нас. А полигон лишь хранит индексы вершин. Как ты достанешь от туда UV?
 
1,038
57
229
Тут идёт речь о построении полигона. Но полигон нам не нужен, нам нужен закрашенный полигон (текстурированный). А это значит, что количество точек на куб будет по 3и на каждый полигон. То есть всего треугольников будет 12. вершин 3*12 = 36 и UV соответственно тоже 36. Либо придётся индексировать не только вершины, но и UV. Покажи мне такой шейдер. Его там нет, он тупо делает как я написал: 12 полигонов, 36 вершин (а не 8, как именно в этом видео без UV)
 

tox1cozZ

aka Agravaine
8,454
598
2,890
Чел, иди загугли любой загрузчик того же obj, там делается тоже самое и так же рисуется модель с индексами.
Логически подумай, зачем хранить несколько одинаковых данных о вершине, если можно обращаться к ним по индексу?
 
1,038
57
229
нашел, 6ой урок. Ну с ThinMatrix тяжело спорить, я сам использую часть его уроков. Как же он понимает к какому полигону что относится..
О, это видео и надо было выложить в самом начале ответов. Это и был бы ответ.
 

tox1cozZ

aka Agravaine
8,454
598
2,890
Да что там понимать-то? Есть две одинаковые вершины(или uv, или нормали) - одну добавляем и присваем ей индекс. В рендере уже оперирует этими индексами. Тем самым экономим кучу памяти и не храним одинаковые данные.
 
Сверху