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

1581071850390.png
 
впринципе нормаль можно потом добавить, без нее должно рендерится хорошо (только небольшие баги наложения освещения)
а в чем собсна проблема? 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 или похожее
 
Ну, должно быть вот так (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();
            }
        }
    }
 
upd. POSITION_TEX пофиксило
Этот вершинный формат без нормалей. Вот у тебя их и нету в результате.
А если не работало с POSITION_TEX_NORMAL, то возможно, в "запечёной" модели нет нормалей.
 
Этот вершинный формат без нормалей. Вот у тебя их и нету в результате.
А если не работало с POSITION_TEX_NORMAL, то возможно, в "запечёной" модели нет нормалей.
Ну у меня модель по сути да, без нормалей экспортирована, но эта одна и та же модель, которая на 1.7.10 рисуется нормально, а на 1.12.2 такие вон проблемы со светом.
 
Мне кажется ты забыл включить перед отправкой GL_DEPTH, сортировка видимости полигонов относительно их позиции. (Перекрытие)
GL11.glEnable(GL11.GL_DEPTH_TEST)
 
Последнее редактирование:
Дело не в нормалях, если ты смотришь на полигон нормаль которого направлена в ту же сторону, ты его просто не увидишь. Раз мы видим модель, то нормали у неё в порядке.
Освещения нет лишь по одной простой причине, ты рисуешь объект не в том месте кода. В тот момент, когда должны рисоваться частицы или вода.
Дай большей инфы. Свой ли шейдер, в каком месте и т.д. Ну и чтобы не гадать, код запуска отрисовки и его окончания. Может ты забыл сохранить матрицы glPushMatrix() или вернуть их на место. И лог тоже не повредит
 
Да там по сути все просто, в методе 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();
 
ты пробовал её убирать?
рисовать в GUI, это вообще не правильно. Там не нужен свет. Можно посмотреть как рисуется игрок в инвентаре и сделать тоже самое. Он вроде как раз с освещением.
 
код явно отличается от 1.7, вот эту разницу и надо найти
 
Попробуй перед рендером вставить
Scala:
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 0F, 240F)
Еще можно попробовать выключать освещение, чтобы полигоны имели равномерную яркость
Scala:
GlStateManager.disableLight()
//или
GlStateManager.disableLighting()
//не помню, какой из них
 
Не работает, оно то делает слегка темнее или светлее эту серую массу, но никак не учитывает тени.
Пробовал рисовать в 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 · Просмотры: 22
Посмотри, как сделано в DraconicEvolution, там тоже воксельная детализированная броня
 
Дело не в нормалях,
дело как раз таки в нормалях.
@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, поймешь чо изменить тут)
Тут конечно было бы неплохо засунуть расчеты в первую проверку на нулл, но мне лень 🌕
 
Закоментил я потому что как раз таки вылетает, вот цельная ошибка

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); Точно не использую, я же вон попробовал отдельно в слоях игрока отрисовать, чтобы ничего лишнего.

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