- 25
- 3
Имеется:
OBJ Модель из 2х мешей/сеток [сфера и параллелепипед] + 2 материала [с текстурой для сферы и синий цвет для параллелепипеда]
Задача:
Отрисовать модель в GUI или на экране во время игры с параметрами:
Сие обсуждение, и некоторые другие из интернетов, привело меня к следующему действию:
I - для начала я создал класс для хранения моделей с необходимыми параметрами:
II - далее создал класс для загрузки/получения OBJ моделей и отрисовки их по указанным параметрам:
III - ну и самое интересное - отрисовка этого дела на экране:
Вызов листа в таком виде не работает (модель просто невидимая).
1 - Однако если до вызова листа отрисовать какой нибудь текст:
То модель будет отрисована неполностью, её нормали отображены, а так же стороны рисуются лишь на 50%
2 - Или забиндить любую текстуру:
То модель отрисуется вся, но первый меш всегда будет чёрным + нормали всё ещё отображены.
Что касается задачи по параметрам, то всё работает как надо (проверено через другие модели):
Вопрос: Где у меня косяк, или Как отрисовать модель с правильными нормалями и целиком в нужном освещении?
OBJ Модель из 2х мешей/сеток [сфера и параллелепипед] + 2 материала [с текстурой для сферы и синий цвет для параллелепипеда]
Задача:
Отрисовать модель в GUI или на экране во время игры с параметрами:
- возможность сместить базовое положение модели для манипуляций с вращением и т.д.;
- возможность выбора мешей, какие отрисовать из всей модели;
- возможность изменить текстуры у любого материала модели;
Сие обсуждение, и некоторые другие из интернетов, привело меня к следующему действию:
I - для начала я создал класс для хранения моделей с необходимыми параметрами:
ParameterizedModel.class:
public class ParameterizedModel {
public int listId;
public ResourceLocation file;
public List<String> visibleMeshes;
public Map<String, String> materialTextures;
public float[] baseOffset;
public OBJModel iModel;
public ParameterizedModel(int list, ResourceLocation file, float[] baseAxisOffsets, List<String> visibleMeshes, Map<String, String> replacesMaterialTextures) {
this.listId = list;
this.file = file;
this.iModel = null;
this.baseOffset = new float[] { 0.0f, 0.0f, 0.0f };
if (baseAxisOffsets!=null && baseAxisOffsets.length>=3) {
for (int i=0; i<3; i++) { this.baseOffset[i] = baseAxisOffsets[i]; }
}
this.visibleMeshes = Lists.<String>newArrayList();
this.materialTextures = Maps.<String, String>newHashMap();
if (visibleMeshes!=null && visibleMeshes.size()>0) { this.visibleMeshes = visibleMeshes; }
if (materialTextures!=null && materialTextures.size()>0) { this.materialTextures = replacesMaterialTextures; }
}
public boolean equals(Object obj) {
if (!(obj instanceof ParameterizedModel)) { return false; }
ParameterizedModel objPM = (ParameterizedModel) obj;
if (this == objPM) { return true; }
if (!this.file.equals(objPM.file)) { return false; }
for (int i=0; i<3; i++) {
if (this.baseOffset[i]!=objPM.baseOffset[i]) { return false; }
}
if (this.visibleMeshes.size()==0 && this.materialTextures.size()==0 && objPM.visibleMeshes.size()==0 && objPM.materialTextures.size()==0) { return true; }
if (this.visibleMeshes.size()!=objPM.visibleMeshes.size()) {
if (objPM.visibleMeshes.size()>0) { return false; }
}
if (this.visibleMeshes.size()>0 && objPM.visibleMeshes.size()>0) {
for (String name : this.visibleMeshes) {
if (!objPM.visibleMeshes.contains(name)) { return false; }
}
}
if (this.materialTextures.size()!=objPM.materialTextures.size()) {
if (objPM.materialTextures.size()>0) { return false; }
}
if (this.materialTextures.size()>0 && objPM.materialTextures.size()>0) {
for (String name : this.materialTextures.keySet()) {
if (!objPM.materialTextures.containsKey(name) || !objPM.materialTextures.get(name).equals(this.materialTextures.get(name))) { return false; }
}
}
return true;
}
}
ModelBuffer.class:
public class ModelBuffer {
private static List<ParameterizedModel> MODELS = Lists.<ParameterizedModel>newArrayList();
private static List<String> NOT_FOUND = Lists.<String>newArrayList();
public static int getDisplayList(String objModel, float[] baseAxisOffsets, List<String> visibleMeshes, Map<String, String> replacesMaterialTextures) {
ParameterizedModel model = new ParameterizedModel(-1, new ResourceLocation(objModel), baseAxisOffsets, visibleMeshes, replacesMaterialTextures);
for (ParameterizedModel pm : ModelBuffer.MODELS) {
if (pm.equals(model)) {
model = pm;
break;
}
}
if (model.listId<0 && !ModelBuffer.NOT_FOUND.contains(objModel)) {
try {
model.iModel = (OBJModel) OBJLoader.INSTANCE.loadModel(model.file);
if (model.iModel==null) {
ModelBuffer.NOT_FOUND.add(objModel);
return -1;
}
model.listId = GLAllocation.generateDisplayLists(1);
GlStateManager.glNewList(model.listId, GL11.GL_COMPILE);
Function<ResourceLocation, TextureAtlasSprite> spriteFunction = location -> {
ResourceLocation loc;
if (replacesMaterialTextures!=null && replacesMaterialTextures.containsKey(location.toString())) { loc = new ResourceLocation(replacesMaterialTextures.get(location.toString())); }
else { loc = location; }
TextureAtlasSprite sprite = Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite(loc.toString());
return sprite;
};
if (model.visibleMeshes==null || model.visibleMeshes.size()==0) { model.visibleMeshes = Lists.<String>newArrayList(model.iModel.getMatLib().getGroups().keySet()); }
@SuppressWarnings("deprecation")
IBakedModel bakedmodel = model.iModel.bake(new OBJModel.OBJState(ImmutableList.copyOf(model.visibleMeshes), false), DefaultVertexFormats.ITEM, spriteFunction);
if (model.baseOffset[0]!=0.0f || model.baseOffset[1]!=0.0f || model.baseOffset[2]!=0.0f) {
GlStateManager.translate(model.baseOffset[0], model.baseOffset[1], model.baseOffset[2]);
}
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder worldrenderer = tessellator.getBuffer();
worldrenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.ITEM);
for (BakedQuad bakedquad : bakedmodel.getQuads(null, null, 0)) {
worldrenderer.addVertexData(bakedquad.getVertexData());
}
tessellator.draw();
GlStateManager.glEndList();
ModelBuffer.MODELS.add(model);
}
catch (Exception e) { }
}
return model.listId;
}
}
Где нибудь в событиях GUI или Экрана:
GlStateManager.pushMatrix();
GlStateManager.callList(ModelBuffer.getDisplayList("customnpcs:models/block/obj/test.obj", null, null, null));
GlStateManager.popMatrix();
Вызов листа в таком виде не работает (модель просто невидимая).
1 - Однако если до вызова листа отрисовать какой нибудь текст:
доп строка 1:
this.drawString(Minecraft.getMinecraft().fontRenderer, "LIST:"+list, 0, 0, 0xFFFFFF);
2 - Или забиндить любую текстуру:
доп строка 2:
Minecraft.getMinecraft().renderEngine.bindTexture(new ResourceLocation("any_path"));
Что касается задачи по параметрам, то всё работает как надо (проверено через другие модели):
- Смещение модели работает, если передать массив чисел с точкой;
- Нужные меши рисуются, если передать лист с их именами;
- Текстуры у материалов подменяются, если передать мапу с подменами;
Вопрос: Где у меня косяк, или Как отрисовать модель с правильными нормалями и целиком в нужном освещении?
Последнее редактирование: