Рендер tile entity

Версия Minecraft
1.7.10
Пытался сделать блоки декора, используя один класс рендера для всех блоков. В целом всё работает исправно, но ModelWrapperDisplayList работает только если назначить саму модель за пределами метода, то бишь как в учебнике, иначе оптимизация пропадает. Проблема в том, что если так сделать, то как мне указать имя своего блока в пути к модельке? ( tile.getBlockType().getLocalizedName() ). Я надеюсь, всё понятно написал.
Java:
public class DecorTileRender extends TileEntitySpecialRenderer {

    @Override
    public void renderTileEntityAt(TileEntity tile, double x, double y, double z, float f) {
        render((TileDecor)tile, x, y, z);
    }

    private void render(TileDecor tile, double x, double y, double z) {
        IModelCustom model = new ModelWrapperDisplayList((WavefrontObject) AdvancedModelLoader.loadModel(new ResourceLocation(Main.MODID, "models/decor/" + tile.getBlockType().getLocalizedName() + ".obj")));
            bindTexture(new ResourceLocation(Main.MODID, "models/decor/textures/" + tile.getBlockType().getLocalizedName() + ".png"));
                GL11.glPushMatrix();
                GL11.glTranslated(x, y, z);
                GL11.glTranslatef(0.5F, 0.0F, 0.5F);
                model.renderAll();
                GL11.glPopMatrix();
        }
    }
 
Решение
ну ты можешь тип декора хранить как строку или интегер в своём TileDecor, а модели хранить в мапе. почитай как работает мемоизация, и по этому принципу легко сможешь черпать модели, не нагружая память
еще раз напомню. заводишь мапу <String, IModelCustom> и модель определяешь так:
Java:
public static final HashMap<String, ICustomModel> CACHE = new HashMap<>();

@Override
private void render(TileDecor tile, double x, double y, double z) {
    ICustomModel model = null;   
    String key = tile.getBlockType().getLocalizedName()
    if(!CACHE.contains(key)) {
        model = /**код создания модели, лень копипастить твой **/
        CACHE.put(key, model);
    } else {
        model = CACHE.get(key);
    }
    if(model != null) {...
Java:
    FMLClientHandler.instance().getClient().getTextureManager().bindTexture(new ResourceLocation(Main.MOD_ID, "models/decor/" + block.getUnlocalizedName().replaceFirst("tile.", "") + ".obj"));

И к слову, нельзя в render делать AdvancedModelLoader#loadModel, у тебя таким образом каждый кадр будет пытаться подгрузиться твоя OBJ модель, из-за этого будут большие просадки FPS. Лучше ещё раз пройдись по теме: Ускорение рендера моделей
 
как вариант
Java:
IModelCustom model;
private void render(TileDecor tile, double x, double y, double z) {
        if(model == null) {
            model = new ModelWrapperDisplayList((WavefrontObject) AdvancedModelLoader.loadModel(new ResourceLocation(Main.MODID, "models/decor/" + tile.getBlockType().getLocalizedName() + ".obj"))); 
       }
                bindTexture(new ResourceLocation(Main.MODID, "models/decor/textures/" + tile.getBlockType().getLocalizedName() + ".png"));
                GL11.glPushMatrix();
                GL11.glTranslated(x, y, z);
                GL11.glTranslatef(0.5F, 0.0F, 0.5F);
                model.renderAll();
                GL11.glPopMatrix();
        }
}
 
ну ты можешь тип декора хранить как строку или интегер в своём TileDecor, а модели хранить в мапе. почитай как работает мемоизация, и по этому принципу легко сможешь черпать модели, не нагружая память
 
как вариант
Java:
IModelCustom model;
private void render(TileDecor tile, double x, double y, double z) {
        if(model == null) {
            model = new ModelWrapperDisplayList((WavefrontObject) AdvancedModelLoader.loadModel(new ResourceLocation(Main.MODID, "models/decor/" + tile.getBlockType().getLocalizedName() + ".obj")));
       }
                bindTexture(new ResourceLocation(Main.MODID, "models/decor/textures/" + tile.getBlockType().getLocalizedName() + ".png"));
                GL11.glPushMatrix();
                GL11.glTranslated(x, y, z);
                GL11.glTranslatef(0.5F, 0.0F, 0.5F);
                model.renderAll();
                GL11.glPopMatrix();
        }
}
Костыльный бред..... Лучше вызывать модель из ClientProxy.
 
Java:
@SideOnly(Side.CLIENT)
public class TileExampleRenderer extends TileEntitySpecialRenderer {
    private final int list;
    private final String name;

    public TileExampleRenderer(Block block) {
        this.name = block.getUnlocalizedName().replaceFirst("tile.", "");
        IModelCustom model = new ModelWrapperDisplayList((WavefrontObject) AdvancedModelLoader.loadModel(new ResourceLocation(Main.MOD_ID, "models/decor/" + name + ".obj")));
        list = GL11.glGenLists(1);
        GL11.glNewList(list, GL11.GL_COMPILE);
        model.renderAll();
        GL11.glEndList();
    }

    @Override
    public void renderTileEntityAt(TileEntity tile, double x, double y, double z, float renderPartialTicks) {
        FMLClientHandler.instance().getClient().getTextureManager().bindTexture(new ResourceLocation(Main.MOD_ID, "textures/decor/" + name + ".png"));
        GL11.glPushMatrix();
        GL11.glTranslated(x, y, z);
        GL11.glTranslatef(0.5F, 0.0F, 0.5F);
        GL11.glCallList(list);
        GL11.glPopMatrix();
    }
}

Ну и регистрация: ClientRegistry.bindTileEntitySpecialRenderer(TileEntityFurnace.class, new TileExampleRenderer(Blocks.furnace));
 
Последнее редактирование:
Java:
@SideOnly(Side.CLIENT)
public class TileExampleRenderer extends TileEntitySpecialRenderer {
    private final int list;
    private final String name;

    public TileExampleRenderer(Block block) {
        this.name = block.getUnlocalizedName().replaceFirst("tile.", "");
        IModelCustom model = new ModelWrapperDisplayList((WavefrontObject) AdvancedModelLoader.loadModel(new ResourceLocation(Main.MOD_ID, "models/decor/" + name + ".obj")));
        list = GL11.glGenLists(1);
        GL11.glNewList(list, GL11.GL_COMPILE);
        model.renderAll();
        GL11.glEndList();
    }

    @Override
    public void renderTileEntityAt(TileEntity tile, double x, double y, double z, float renderPartialTicks) {
        FMLClientHandler.instance().getClient().getTextureManager().bindTexture(new ResourceLocation(Main.MOD_ID, "textures/decor/" + name + ".png"));
        GL11.glPushMatrix();
        GL11.glTranslated(x, y, z);
        GL11.glTranslatef(0.5F, 0.0F, 0.5F);
        GL11.glCallList(list);
        GL11.glPopMatrix();
    }
}

Ну и регистрация: ClientRegistry.bindTileEntitySpecialRenderer(TileEntityFurnace.class, new TileExampleRenderer(Blocks.furnace));
Одна модель применяется для всех блоков с этим кодом(
 
ну ты можешь тип декора хранить как строку или интегер в своём TileDecor, а модели хранить в мапе. почитай как работает мемоизация, и по этому принципу легко сможешь черпать модели, не нагружая память
еще раз напомню. заводишь мапу <String, IModelCustom> и модель определяешь так:
Java:
public static final HashMap<String, ICustomModel> CACHE = new HashMap<>();

@Override
private void render(TileDecor tile, double x, double y, double z) {
    ICustomModel model = null;   
    String key = tile.getBlockType().getLocalizedName()
    if(!CACHE.contains(key)) {
        model = /**код создания модели, лень копипастить твой **/
        CACHE.put(key, model);
    } else {
        model = CACHE.get(key);
    }
    if(model != null) {
        //рендеришш
    }
}
без костылей, без проблем.
 
Боже, какой раз уже кидаю код для получения ключа имени блока, но всё равно во всех других ответах вижу:
tile.getBlockType().getLocalizedName()
tile.getBlockType().getLocalizedName()
tile.getBlockType().getLocalizedName()
Этот метод возвращает локализированное имя блока, то есть, чтобы сделать адекватную работу с ним, то в ресурсах мода придётся делать название блока на КАЖДОМ языке, вопрос, серьёзно собираетесь? Будет весело, если вдруг захочется изменить локализированное название. А касательно этого:
public static final HashMap<String, ICustomModel> CACHE = new HashMap<>();
Лучше сделать интерфейс. Тем более, хранить в памяти ICustomModel неправильно, об этом рассказывается в теме: Ускорение рендера моделей

Выше я кидал код, который чутка переделать под интерфейс по типу:
Java:
import net.minecraft.util.ResourceLocation;

public interface IDecoTile {
    ResourceLocation getModelLocation();
    ResourceLocation getTextureLocation();
  
}
И всё будет нормально работать
 
И откуда там null должен взяться?
не посмотрел как он объект ICustomModel создавал. думал через метод какой, мало ли null вернёт, а там конструктор оказывается. лишнее, соглы.
не приходилось пользоваться, но теперь видимо буду. за совет спасибо
 
Лучше сделать интерфейс. Тем более, хранить в памяти ICustomModel неправильно, об этом рассказывается в теме
А ничего что объект всё равно придётся создать и он будет храниться в памяти? В теме рассказывается немного о другом.
Java:
@SideOnly(Side.CLIENT)
public class TileExampleRenderer extends TileEntitySpecialRenderer {
    private final int list;
    private final String name;

    public TileExampleRenderer(Block block) {
        this.name = block.getUnlocalizedName().replaceFirst("tile.", "");
        IModelCustom model = new ModelWrapperDisplayList((WavefrontObject) AdvancedModelLoader.loadModel(new ResourceLocation(Main.MOD_ID, "models/decor/" + name + ".obj")));
        list = GL11.glGenLists(1);
        GL11.glNewList(list, GL11.GL_COMPILE);
        model.renderAll();
        GL11.glEndList();
    }

    @Override
    public void renderTileEntityAt(TileEntity tile, double x, double y, double z, float renderPartialTicks) {
        FMLClientHandler.instance().getClient().getTextureManager().bindTexture(new ResourceLocation(Main.MOD_ID, "textures/decor/" + name + ".png"));
        GL11.glPushMatrix();
        GL11.glTranslated(x, y, z);
        GL11.glTranslatef(0.5F, 0.0F, 0.5F);
        GL11.glCallList(list);
        GL11.glPopMatrix();
    }
}

Ну и регистрация: ClientRegistry.bindTileEntitySpecialRenderer(TileEntityFurnace.class, new TileExampleRenderer(Blocks.furnace));
1. Для бинда текстур есть метод TileEntitySpecialRenderer#bindTexture(ResourceLocation)
2. Нет никакого смысла постоянно создавать новый объект ResourceLocation
3. Получение названия блока у тебя также неправильно, есть метод GameRegistry#findUniqueIdentifierFor. В случае, если надо получить название тайла есть такие перемененные: TileEntity#classToNameMap и TileEntity#nameToClassMap
4. Щепотка занудства: оба glTranslate можно объединить в один
 
Последнее редактирование:
Назад
Сверху