版本信息
IDE版本:<Eclipse Java 2019-12>
Forge版本: <1.12.2-14.23.5.2847>
Minecraft版本: <1.12.2>
情况简述
自定义Gl模型的旋转与TileEntityModel的旋转不一致。
- 旋转发生的地方:
TileEntityBeamLampRenderer: render(TileEntityBeamLamp tileEntity, double x, double y, double z, float partialTicks, int destroyStage, float alpha)
modelBeamLampBulb.render((Entity) null, tileEntity.getRotateAngle(), 0.0625F);
LayersHelper.drawRay(RAY_TRANSLATE, tileEntity.getRotateAngle(), tileEntity.getLength(), tileEntity.getAngle(), tileEntity.getFirstColor(), tileEntity.getAfterColor());
我认为可能影响的地方
- 模型本身被预先旋转过:
TileEntityBeamLampRenderer: render(TileEntityBeamLamp tileEntity, double x, double y, double z, float partialTicks, int destroyStage, float alpha)
GlStateManager.rotate(180F, 1.0F, 0F, 1.0F);
- 旋转原点(在实际游戏中,即使我旋转了90°模型也没有旋转到90°,应该不是这个问题):
ModelBeamLampBulb: ModelBeamLampBulb()
holder.setRotationPoint(0.0F, 20.0F, 0.0F);
...
bulb.setRotationPoint(0.0F, 17.0F, 0.0F);
相关代码
<TileEntityBeamLampRenderer>
//TileEntity的渲染类,在这里渲染所有相关模型
package net.tealing.studiocraft.client.renderer.tileentity;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer;
import net.minecraft.entity.Entity;
import net.minecraft.util.ResourceLocation;
import net.tealing.studiocraft.client.model.ModelBeamLampBulb;
import net.tealing.studiocraft.client.renderer.LayersHelper;
import net.tealing.studiocraft.tileentity.TileEntityBeamLamp;
public class TileEntityBeamLampRenderer extends TileEntitySpecialRenderer<TileEntityBeamLamp>{
private static final ResourceLocation TEXTURE_BEAM_LAMP_BULB = new ResourceLocation("studiocraft:textures/entity/beam_lamp_bulb.png");
private final ModelBeamLampBulb modelBeamLampBulb = new ModelBeamLampBulb();
private static final float[] RAY_TRANSLATE = {0F, 18/16F, 0F};
public void render(TileEntityBeamLamp tileEntity, double x, double y, double z, float partialTicks, int destroyStage, float alpha) {
GlStateManager.pushMatrix();
GlStateManager.translate((float)x + 8/16F, (float)y + 24/16F, (float)z + 8/16F);
GlStateManager.rotate(180F, 1.0F, 0F, 1.0F);
this.bindTexture(TEXTURE_BEAM_LAMP_BULB);
GlStateManager.enableCull();
modelBeamLampBulb.render((Entity) null, tileEntity.getRotateAngle(), 0.0625F);
LayersHelper.drawRay(RAY_TRANSLATE, tileEntity.getRotateAngle(), tileEntity.getLength(), tileEntity.getAngle(), tileEntity.getFirstColor(), tileEntity.getAfterColor());
GlStateManager.popMatrix();
}
@Override
public boolean isGlobalRenderer(TileEntityBeamLamp te) {
return true;
}
@Override
protected void setLightmapDisabled(boolean disabled) {
//FIXME Have not tested yet
super.setLightmapDisabled(false);
}
}
<LayersHelper>
//封装了各种模型供调用
package net.tealing.studiocraft.client.renderer;
import org.lwjgl.opengl.GL11;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
@SideOnly(Side.CLIENT)
public class LayersHelper {
private static Tessellator tessellator;
private static BufferBuilder bufferBuilder;
public static void drawRay(float[] translate, float[] rotateAngle, double length, double angle, int[] firstColor, int[] afterColor) {
//TODO Unsafe data
tessellator = Tessellator.getInstance();
bufferBuilder = tessellator.getBuffer();
RenderHelper.disableStandardItemLighting();
GlStateManager.disableTexture2D();
GlStateManager.shadeModel(7425);
GlStateManager.enableBlend();
GlStateManager.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE);
GlStateManager.disableAlpha();
GlStateManager.enableCull();
GlStateManager.depthMask(false);
GlStateManager.pushMatrix();
GlStateManager.translate(translate[0], translate[1], translate[2]);
GlStateManager.rotate(rotateAngle[0], 1F, 0F, 0F);
GlStateManager.rotate(rotateAngle[1], 0F, 1F, 0F);
GlStateManager.rotate(rotateAngle[2], 0F, 0F, 1F);
double d1 = length * Math.tan(Math.toRadians(angle / 2D));
double d2 = d1 / Math.tan(Math.toRadians(60D));
double d3 = d2 * 2D;
bufferBuilder.begin(GL11.GL_TRIANGLE_FAN, DefaultVertexFormats.POSITION_COLOR);
bufferBuilder.pos(0D, 0D, 0D).color(firstColor[0], firstColor[1], firstColor[2],255).endVertex();
bufferBuilder.pos(-d1, -length, -d2).color(afterColor[0], afterColor[1], afterColor[2],0).endVertex();
bufferBuilder.pos(d1, -length, -d2).color(afterColor[0], afterColor[1], afterColor[2],0).endVertex();
bufferBuilder.pos(0D, -length, d3).color(afterColor[0], afterColor[1], afterColor[2],0).endVertex();
bufferBuilder.pos(-d1, -length, -d2).color(afterColor[0], afterColor[1], afterColor[2],0).endVertex();
tessellator.draw();
GlStateManager.popMatrix();
GlStateManager.disableCull();
GlStateManager.depthMask(true);
GlStateManager.disableBlend();
GlStateManager.shadeModel(7424);
GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
GlStateManager.enableTexture2D();
GlStateManager.enableAlpha();
RenderHelper.enableStandardItemLighting();
}
}
<TileEntityBeamLamp>
//TileEntity类,储存数据
package net.tealing.studiocraft.tileentity;
import javax.annotation.Nullable;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.inventory.Container;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.play.server.SPacketUpdateTileEntity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.ITickable;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.util.text.TextComponentTranslation;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemStackHandler;
import net.minecraftforge.items.SlotItemHandler;
import net.tealing.studiocraft.inventory.ContainerBeamLamp;
import net.tealing.studiocraft.item.Items;
public class TileEntityBeamLamp extends TileEntity implements IItemHandler, ITickable {
public final AxisAlignedBB BEAM_LAMP_AABB = new AxisAlignedBB(-65536.0D, -65536.0D, -65536.0D, 65536.0D, 65536.0D, 65536.0D);
private ItemStackHandler inventory = new ItemStackHandler(3);
protected Slot lensSlot = new SlotItemHandler(inventory, 0, 8, 18) {
public boolean isItemValid(ItemStack stack) {
return stack != null && stack.getItem() == Items.LENS && super.isItemValid(stack);
};
public int getItemStackLimit(ItemStack stack) {
return 16;
};
};
protected Slot diskSlot = new SlotItemHandler(inventory, 1, 8, 18 + 18) {
public boolean isItemValid(ItemStack stack) {
return stack != null && stack.getItem() == Items.DISK && super.isItemValid(stack);
};
public int getItemStackLimit(ItemStack stack) {
return 1;
};
};
private float[] rotateAngle = {0F, 0F, 0F};
private int[] firstColor = {0, 0, 255};
private int[] afterColor = {255, 0, 255};
private double length = 10, angle = 6;
private String customName;
public NBTTagCompound writeToNBT(NBTTagCompound compound) {
super.writeToNBT(compound);
if (this.hasCustomName()) {
compound.setString("CustomName", this.customName);
}
compound.setIntArray("firstColor", firstColor);
compound.setIntArray("afterColor", afterColor);
compound.setFloat("rx", rotateAngle[0]);
compound.setFloat("ry", rotateAngle[1]);
compound.setFloat("rz", rotateAngle[2]);
compound.setDouble("length", length);
compound.setDouble("angle", angle);
compound.setTag("inventory", inventory.serializeNBT());
return compound;
}
public void readFromNBT(NBTTagCompound compound) {
super.readFromNBT(compound);
if (compound.hasKey("CustomName", 8)) {
customName = compound.getString("CustomName");
}
firstColor = compound.getIntArray("firstColor");
afterColor = compound.getIntArray("afterColor");
rotateAngle[0] = compound.getFloat("rx");
rotateAngle[1] = compound.getFloat("ry");
rotateAngle[2] = compound.getFloat("rz");
length = compound.getDouble("length");
angle = compound.getDouble("angle");
this.inventory.deserializeNBT(compound.getCompoundTag("inventory"));
System.out.println(compound.getDouble("length"));
}
@Override
public NBTTagCompound getUpdateTag() {
return writeToNBT(new NBTTagCompound());
}
@Nullable
public SPacketUpdateTileEntity getUpdatePacket()
{
return new SPacketUpdateTileEntity(this.pos, 3, this.getUpdateTag());
}
public String getName() {
return this.hasCustomName() ? this.customName : "container.beam_lamp";
}
public boolean hasCustomName() {
return this.customName != null && !this.customName.isEmpty();
}
public void setCustomName(String customNameIn) {
this.customName = customNameIn;
}
public ITextComponent getDisplayName() {
return (ITextComponent) (this.hasCustomName() ? new TextComponentString(this.getName())
: new TextComponentTranslation(this.getName(), new Object[0]));
}
public Container createContainer(InventoryPlayer playerInventory, EntityPlayer playerIn) {
return new ContainerBeamLamp(playerIn, this);
}
public String getGuiID() {
return "studiocraft:beam_lamp";
}
public float[] getRotateAngle() {
return rotateAngle;
}
public int[] getFirstColor() {
return firstColor;
}
public int[] getAfterColor() {
return afterColor;
}
public double getLength() {
return length;
}
public double getAngle() {
return angle;
}
public void setRotateAngle(float x, float y, float z) {
rotateAngle[0] = x;
rotateAngle[1] = y;
rotateAngle[2] = z;
}
public void setFirstColor(int red, int green, int blue) {
firstColor[0] = red;
firstColor[1] = green;
firstColor[2] = blue;
}
public void setAfterColor(int red, int green, int blue) {
afterColor[0] = red;
afterColor[1] = green;
afterColor[2] = blue;
}
public void setLength(double newLength) {
if (0 < newLength && newLength < 65536.0D) {
length = newLength;
}
else {
length = 10.0D;
}
}
@Override
public boolean hasCapability(Capability<?> capability, EnumFacing facing) {
if (CapabilityItemHandler.ITEM_HANDLER_CAPABILITY.equals(capability)) {
return true;
}
return super.hasCapability(capability, facing);
}
@Override
public <T> T getCapability(Capability<T> capability, EnumFacing facing) {
if (CapabilityItemHandler.ITEM_HANDLER_CAPABILITY.equals(capability)) {
}
return super.getCapability(capability, facing);
}
public ItemStackHandler getInventory() {
return inventory;
}
public Slot getSlot(int index) {
switch (index) {
case 0:
return lensSlot;
case 1:
return diskSlot;
default:
return null;
}
}
@Override
public AxisAlignedBB getRenderBoundingBox() {
return BEAM_LAMP_AABB;
}
@Override
@SideOnly(Side.CLIENT)
public double getMaxRenderDistanceSquared() {
return 65536.0D;
}
@Override
public int getSlots() {
return inventory.getSlots();
}
@Override
public ItemStack getStackInSlot(int slot) {
return inventory.getStackInSlot(slot);
}
@Override
public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) {
return inventory.insertItem(slot, stack, simulate);
}
@Override
public ItemStack extractItem(int slot, int amount, boolean simulate) {
return inventory.extractItem(slot, amount, simulate);
}
@Override
public int getSlotLimit(int slot) {
return inventory.getSlotLimit(slot);
}
int updateTick = 0;
@Override
public void update() {
if (updateTick == 20) {
readFromNBT(getUpdateTag());
updateTick = 0;
}
updateTick++;
}
}
<ModelBeamLampBulb>
//TileEntity的模型
package net.tealing.studiocraft.client.model;
import net.minecraft.client.model.ModelBase;
import net.minecraft.client.model.ModelBox;
import net.minecraft.client.model.ModelRenderer;
import net.minecraft.entity.Entity;
public class ModelBeamLampBulb extends ModelBase {
private final ModelRenderer holder;
private final ModelRenderer bulb;
public ModelBeamLampBulb() {
holder = new ModelRenderer(this);
holder.setRotationPoint(0.0F, 20.0F, 0.0F);
holder.cubeList.add(new ModelBox(holder, 0, 0, -3.0F, 0.0F, -3.0F, 6, 1, 6, 0.0F, false));
holder.cubeList.add(new ModelBox(holder, 10, 7, 3.0F, -5.0F, -2.0F, 1, 6, 4, 0.0F, false));
holder.cubeList.add(new ModelBox(holder, 0, 7, -4.0F, -5.0F, -2.0F, 1, 6, 4, 0.0F, false));
bulb = new ModelRenderer(this);
bulb.setRotationPoint(0.0F, 17.0F, 0.0F);
bulb.cubeList.add(new ModelBox(bulb, 0, 17, -3.0F, -6.0F, -3.0F, 6, 8, 1, 0.0F, false));
bulb.cubeList.add(new ModelBox(bulb, 14, 17, -3.0F, -6.0F, 2.0F, 6, 8, 1, 0.0F, false));
bulb.cubeList.add(new ModelBox(bulb, 24, 0, 2.0F, -6.0F, -2.0F, 1, 8, 4, 0.0F, false));
bulb.cubeList.add(new ModelBox(bulb, 34, 0, -3.0F, -6.0F, -2.0F, 1, 8, 4, 0.0F, false));
bulb.cubeList.add(new ModelBox(bulb, 0, 26, -2.0F, 1.0F, -2.0F, 4, 1, 4, 0.0F, false));
bulb.cubeList.add(new ModelBox(bulb, 28, 12, -2.0F, -5.5F, -2.0F, 4, 1, 4, 0.0F, false));
}
public void render(Entity entity, float[] rotateAngle, float scale) {
holder.rotateAngleY = rotateAngle[1];
bulb.rotateAngleX = rotateAngle[0];
bulb.rotateAngleY = rotateAngle[1];
bulb.rotateAngleZ = rotateAngle[2];
holder.render(scale);
bulb.render(scale);
}
}
详情图片
x/y/z旋转角度:0, 0, 0
x/y/z旋转角度:60, 0, 0
x/y/z旋转角度:90, 60, 30