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 работает хорошо?
 
355
2
17
Это конечно все хорошо, но по проблеме подскажите то, как нормаль то настроить с новым буфером, если через метод как я указал вылезает за границы. Освещение то в самом UI настроено, вроде как, по крайне мере на версии 1.7.10 все отлично.

1581071850390.png
 
1,075
22
129
впринципе нормаль можно потом добавить, без нее должно рендерится хорошо (только небольшие баги наложения освещения)
а в чем собсна проблема? worldRenderer вообще тут кстати не причем
вот что собсна делает setNormal()
Java:
public void setNormal(float p_78375_1_, float p_78375_2_, float p_78375_3_)
    {
        this.hasNormals = true;
        byte b0 = (byte)((int)(p_78375_1_ * 127.0F));
        byte b1 = (byte)((int)(p_78375_2_ * 127.0F));
        byte b2 = (byte)((int)(p_78375_3_ * 127.0F));
        this.normal = b0 & 255 | (b1 & 255) << 8 | (b2 & 255) << 16;
    }
}
Попробуй поискать в тессе что то подобное, или в буффербилдере, шобы там было поле normal или похожее
 
355
2
17
Ну, должно быть вот так (1.7.10)
1581082099464.png

А получается собственно как выше, без учета источника света, теней.
Код при этом не менялся

Java:
GL11.glAlphaFunc(516, 0.1F);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);

RenderHelper.enableStandardItemLighting();
item.getModel().renderAll();
В BufferBuilder есть такое, но при его использовании выдает ошибку, пару постов выше.

Java:
    public void putNormal(float x, float y, float z)
    {
        int i = (byte)((int)(x * 127.0F)) & 255;
        int j = (byte)((int)(y * 127.0F)) & 255;
        int k = (byte)((int)(z * 127.0F)) & 255;
        int l = i | j << 8 | k << 16;
        int i1 = this.vertexFormat.getNextOffset() >> 2;
        int j1 = (this.vertexCount - 4) * i1 + this.vertexFormat.getNormalOffset() / 4;
        this.rawIntBuffer.put(j1, l);
        this.rawIntBuffer.put(j1 + i1, l);
        this.rawIntBuffer.put(j1 + i1 * 2, l);
        this.rawIntBuffer.put(j1 + i1 * 3, l);
    }
А насчет worldRender, это был косяк названия переменной, не знаю как такое произошло, вот:


Java:
@SideOnly(Side.CLIENT)
    public void addFaceForRender(BufferBuilder bufferBuilder, float textureOffset)
    {

        if (faceNormal == null)
        {
            faceNormal = this.calculateFaceNormal();
        }

        bufferBuilder.putNormal(faceNormal.x, faceNormal.y, faceNormal.z); <--- Тут косячок

        float averageU = 0F;
        float averageV = 0F;

        if ((textureCoordinates != null) && (textureCoordinates.length > 0))
        {
            for (int i = 0; i < textureCoordinates.length; ++i)
            {
                averageU += textureCoordinates[i].u;
                averageV += textureCoordinates[i].v;
            }

            averageU = averageU / textureCoordinates.length;
            averageV = averageV / textureCoordinates.length;
        }

        float offsetU, offsetV;

        for (int i = 0; i < vertices.length; ++i)
        {

            if ((textureCoordinates != null) && (textureCoordinates.length > 0))
            {
                offsetU = textureOffset;
                offsetV = textureOffset;

                if (textureCoordinates[i].u > averageU)
                {
                    offsetU = -offsetU;
                }
                if (textureCoordinates[i].v > averageV)
                {
                    offsetV = -offsetV;
                }

                bufferBuilder.pos(vertices[i].x, vertices[i].y, vertices[i].z).tex(textureCoordinates[i].u + offsetU, textureCoordinates[i].v + offsetV).endVertex();
            }
            else
            {
                bufferBuilder.pos(vertices[i].x, vertices[i].y, vertices[i].z).endVertex();
            }
        }
    }
 
355
2
17
Этот вершинный формат без нормалей. Вот у тебя их и нету в результате.
А если не работало с POSITION_TEX_NORMAL, то возможно, в "запечёной" модели нет нормалей.
Ну у меня модель по сути да, без нормалей экспортирована, но эта одна и та же модель, которая на 1.7.10 рисуется нормально, а на 1.12.2 такие вон проблемы со светом.
 
590
25
107
Мне кажется ты забыл включить перед отправкой GL_DEPTH, сортировка видимости полигонов относительно их позиции. (Перекрытие)
GL11.glEnable(GL11.GL_DEPTH_TEST)
 
Последнее редактирование:
590
25
107
Дело не в нормалях, если ты смотришь на полигон нормаль которого направлена в ту же сторону, ты его просто не увидишь. Раз мы видим модель, то нормали у неё в порядке.
Освещения нет лишь по одной простой причине, ты рисуешь объект не в том месте кода. В тот момент, когда должны рисоваться частицы или вода.
Дай большей инфы. Свой ли шейдер, в каком месте и т.д. Ну и чтобы не гадать, код запуска отрисовки и его окончания. Может ты забыл сохранить матрицы glPushMatrix() или вернуть их на место. И лог тоже не повредит
 
355
2
17
Да там по сути все просто, в методе draw от GuiScreen,
Оборачиваю в pushMatrix и popMatrix этот код. Ну еще бинд текстуры и позиционирование glTranslatef и glRotatef в добавок.

Не исключаю конечно что возможно в enableStandardItemLighting чет конкретно меняли с версией, или правила игнорируются, но опять же, раз в 1.7.10 они выставлены такие же и все работает нормально, а от версии изменился только тесселятор и вот как раз какие-то из правил рендера самого майна, то явно не тут нужно копать.

Java:
GL11.glAlphaFunc(516, 0.1F);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);

RenderHelper.enableStandardItemLighting();
item.getModel().renderAll();
 
590
25
107
ты пробовал её убирать?
рисовать в GUI, это вообще не правильно. Там не нужен свет. Можно посмотреть как рисуется игрок в инвентаре и сделать тоже самое. Он вроде как раз с освещением.
 

tox1cozZ

aka Agravaine
Модератор
7,123
455
2,146
Что ты несешь? Иди посмотри как отрисовываются блоки в инвентаре со светом.
Снова чушь какуе-то паришь...
 
590
25
107
код явно отличается от 1.7, вот эту разницу и надо найти
 
5,392
179
979
Попробуй перед рендером вставить
Scala:
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 0F, 240F)
Еще можно попробовать выключать освещение, чтобы полигоны имели равномерную яркость
Scala:
GlStateManager.disableLight()
//или
GlStateManager.disableLighting()
//не помню, какой из них
 
355
2
17
Не работает, оно то делает слегка темнее или светлее эту серую массу, но никак не учитывает тени.
Пробовал рисовать в LayerRenderer<EntityPlayer>, эффект тот же, просто серая масса без учета теней.

Так что я все еще думаю, что проблема как раз таки где-то в отрисовке, в посте выше.


Java:
    @SideOnly(Side.CLIENT)
    public void addFaceForRender(BufferBuilder bufferBuilder, float textureOffset)
    {

        if (faceNormal == null)
        {
            faceNormal = this.calculateFaceNormal();
        }

        // Либо тут
        // bufferBuilder.putNormal(faceNormal.x, faceNormal.y, faceNormal.z);

        float averageU = 0F;
        float averageV = 0F;

        if ((textureCoordinates != null) && (textureCoordinates.length > 0))
        {
            for (int i = 0; i < textureCoordinates.length; ++i)
            {
                averageU += textureCoordinates[i].u;
                averageV += textureCoordinates[i].v;
            }

            averageU = averageU / textureCoordinates.length;
            averageV = averageV / textureCoordinates.length;
        }

        float offsetU, offsetV;

        for (int i = 0; i < vertices.length; ++i)
        {

            if ((textureCoordinates != null) && (textureCoordinates.length > 0))
            {
                offsetU = textureOffset;
                offsetV = textureOffset;

                if (textureCoordinates[i].u > averageU)
                {
                    offsetU = -offsetU;
                }
                if (textureCoordinates[i].v > averageV)
                {
                    offsetV = -offsetV;
                }

                // Либо тут
                bufferBuilder.pos(vertices[i].x, vertices[i].y, vertices[i].z).tex(textureCoordinates[i].u + offsetU, textureCoordinates[i].v + offsetV).endVertex();
            }
            else
            {
                // Либо тут
                bufferBuilder.pos(vertices[i].x, vertices[i].y, vertices[i].z).endVertex();
            }
        }
    }
 

Вложения

  • 1581115100885.png
    1581115100885.png
    95 KB · Просмотры: 13
5,392
179
979
Посмотри, как сделано в DraconicEvolution, там тоже воксельная детализированная броня
 
1,075
22
129
Дело не в нормалях,
дело как раз таки в нормалях.
@Sunrise зачем закомментил
Java:
bufferBuilder.putNormal(faceNormal.x, faceNormal.y, faceNormal.z);
?
Тут негде выдавать эксепшн на выход за пределы массива.
Нащет однотонности, может юзаешь glDisable(GL_LIGHTING);? Или похожее, у меня это отрубало расчет освещения (нувыпонялименякрч)
Еще надо бы изменить расчет нормалей в Face, фордж их постоянно пересобирает заново даже если они есть, поэтому измени метод calculateFaceNormal() вот так

Java:
public static Vertex calculateFaceNormal(Face face)
    {
 
        Vec3 v2 = Vec3.createVectorHelper(face.vertices[1].x - face.vertices[0].x, face.vertices[1].y - face.vertices[0].y, face.vertices[1].z - face.vertices[0].z);
        Vec3 v3 = Vec3.createVectorHelper(face.vertices[2].x - face.vertices[1].x, face.vertices[2].y - face.vertices[1].y, face.vertices[2].z - face.vertices[1].z);
        //рассчитываем нормаль к полигону
        Vec3 normalVector = v2.crossProduct(v3).normalize();
        //если нормали в obj модели нет, то рассчитываем
        if(face.vertexNormals == null) {
        return new Vertex((float) normalVector.xCoord, (float) normalVector.yCoord, (float) normalVector.zCoord);
        } else { //если есть, то берем готовую из obj модели
        return new Vertex((float) face.vertexNormals[0].x, (float) face.vertexNormals[0].y, (float) face.vertexNormals[0].z);
        }
    }
(это если что мой хук, я же не могу изменять класс Face, поймешь чо изменить тут)
Тут конечно было бы неплохо засунуть расчеты в первую проверку на нулл, но мне лень 🌕
 
355
2
17
Закоментил я потому что как раз таки вылетает, вот цельная ошибка

Java:
 java.lang.IndexOutOfBoundsException
     at java.nio.Buffer.checkIndex(Buffer.java:540)
     at java.nio.DirectIntBufferU.put(DirectIntBufferU.java:306)
     at net.minecraft.client.renderer.BufferBuilder.putNormal(BufferBuilder.java:489)
     at forge.Face.addFaceForRender(Face.java:33)
     at forge.Face.addFaceForRender(Face.java:21)
     at forge.GroupObject.render(GroupObject.java:56)
     at forge.WavefrontObject.tessellateAll(WavefrontObject.java:197)
     at forge.WavefrontObject.renderAll(WavefrontObject.java:187)
     at forge.WavefrontObject.renderAll(WavefrontObject.java:187)
     at net.mod.accessories.client.item.AccessoryItem.initRendererCall(AccessoryItem.java:143)
     at net.mod.accessories.client.data.ModelLoader.initModels(ModelLoader.java:210)
     at net.mod.accessories.client.ClientProxy.init(ClientProxy.java:48)
     at net.mod.accessories.AccessoriesCore.init(AccessoriesCore.java:38)
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
     at java.lang.reflect.Method.invoke(Method.java:498)
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
     at java.lang.reflect.Method.invoke(Method.java:498)
     at net.minecraftforge.fml.common.FMLModContainer.handleModStateEvent(FMLModContainer.java:639)
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
     at java.lang.reflect.Method.invoke(Method.java:498)
     at com.google.common.eventbus.Subscriber.invokeSubscriberMethod(Subscriber.java:91)
     at com.google.common.eventbus.Subscriber$SynchronizedSubscriber.invokeSubscriberMethod(Subscriber.java:150)
     at com.google.common.eventbus.Subscriber$1.run(Subscriber.java:76)
     at com.google.common.util.concurrent.MoreExecutors$DirectExecutor.execute(MoreExecutors.java:399)
     at com.google.common.eventbus.Subscriber.dispatchEvent(Subscriber.java:71)
     at com.google.common.eventbus.Dispatcher$PerThreadQueuedDispatcher.dispatch(Dispatcher.java:116)
     at com.google.common.eventbus.EventBus.post(EventBus.java:217)
     at net.minecraftforge.fml.common.LoadController.sendEventToModContainer(LoadController.java:219)
     at net.minecraftforge.fml.common.LoadController.propogateStateMessage(LoadController.java:197)
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
     at java.lang.reflect.Method.invoke(Method.java:498)
     at com.google.common.eventbus.Subscriber.invokeSubscriberMethod(Subscriber.java:91)
     at com.google.common.eventbus.Subscriber$SynchronizedSubscriber.invokeSubscriberMethod(Subscriber.java:150)
     at com.google.common.eventbus.Subscriber$1.run(Subscriber.java:76)
     at com.google.common.util.concurrent.MoreExecutors$DirectExecutor.execute(MoreExecutors.java:399)
     at com.google.common.eventbus.Subscriber.dispatchEvent(Subscriber.java:71)
     at com.google.common.eventbus.Dispatcher$PerThreadQueuedDispatcher.dispatch(Dispatcher.java:116)
     at com.google.common.eventbus.EventBus.post(EventBus.java:217)
     at net.minecraftforge.fml.common.LoadController.distributeStateMessage(LoadController.java:136)
     at net.minecraftforge.fml.common.Loader.initializeMods(Loader.java:749)
     at net.minecraftforge.fml.client.FMLClientHandler.finishMinecraftLoading(FMLClientHandler.java:336)
     at net.minecraft.client.Minecraft.init(Minecraft.java:582)
     at net.minecraft.client.Minecraft.run(Minecraft.java:422)
     at net.minecraft.client.main.Main.main(Main.java:118)
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
     at java.lang.reflect.Method.invoke(Method.java:498)
     at net.minecraft.launchwrapper.Launch.launch(Launch.java:135)
     at net.minecraft.launchwrapper.Launch.main(Launch.java:28)
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
     at java.lang.reflect.Method.invoke(Method.java:498)
     at net.minecraftforge.gradle.GradleStartCommon.launch(GradleStartCommon.java:97)
     at GradleStart.main(GradleStart.java:25)

[minecraft/Minecraft]: Reported exception thrown!
net.minecraft.util.ReportedException: Rendering screen
    at net.minecraft.client.renderer.EntityRenderer.updateCameraAndRender(EntityRenderer.java:1204) ~[EntityRenderer.class:?]
    at net.minecraft.client.Minecraft.runGameLoop(Minecraft.java:1209) ~[Minecraft.class:?]
    at net.minecraft.client.Minecraft.run(Minecraft.java:442) [Minecraft.class:?]
    at net.minecraft.client.main.Main.main(Main.java:118) [Main.class:?]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_151]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_151]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_151]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_151]
    at net.minecraft.launchwrapper.Launch.launch(Launch.java:135) [launchwrapper-1.12.jar:?]
    at net.minecraft.launchwrapper.Launch.main(Launch.java:28) [launchwrapper-1.12.jar:?]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_151]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_151]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_151]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_151]
    at net.minecraftforge.gradle.GradleStartCommon.launch(GradleStartCommon.java:97) [start/:?]
    at GradleStart.main(GradleStart.java:25) [start/:?]
Caused by: java.lang.IllegalStateException: Already building!
    at net.minecraft.client.renderer.BufferBuilder.begin(BufferBuilder.java:188) ~[BufferBuilder.class:?]
    at net.minecraft.client.gui.GuiMainMenu.drawPanorama(GuiMainMenu.java:449) ~[GuiMainMenu.class:?]
    at net.minecraft.client.gui.GuiMainMenu.renderSkybox(GuiMainMenu.java:517) ~[GuiMainMenu.class:?]
    at net.minecraft.client.gui.GuiMainMenu.drawScreen(GuiMainMenu.java:549) ~[GuiMainMenu.class:?]
    at net.minecraftforge.client.ForgeHooksClient.drawScreen(ForgeHooksClient.java:396) ~[ForgeHooksClient.class:?]
    at net.minecraft.client.renderer.EntityRenderer.updateCameraAndRender(EntityRenderer.java:1177) ~[EntityRenderer.class:?]
    ... 15 more
Насколько я понял по этому логу, инициализация моделей проходит с ошибкой, и крашит в момент когда они пытаются записаться в листы
Java:
GL11.glNewList(indexRenderer, GL11.GL_COMPILE);

model.renderAll(); <--- Вызывает уже полный краш.

GL11.glEndList();
glDisable(GL_LIGHTING); Точно не использую, я же вон попробовал отдельно в слоях игрока отрисовать, чтобы ничего лишнего.

Код попробовал, он ничего не изменил
 

tox1cozZ

aka Agravaine
Модератор
7,123
455
2,146
Напиши уже лучше свой загрузчик и рендер с помощью vao вместо тесселатора.
 
355
2
17
Напиши уже лучше свой загрузчик и рендер с помощью vao вместо тесселатора.
Вариант возможно годный, но оно того не стоит, мне сейчас лишь нужно адаптировать под новую версию, любыми существующими методами.
 
355
2
17
Что-то прям вообще глубокая яма с этим Obj на 1.12.2. А в Forge завезли нормальную альтернативу загрузки Json модели? Не прикручивая к блоку или предмету, а просто получить IBakeModel и отрисовать его с текстурой? Без хуков там всяких
 
Сверху