- 62
- 1
- 9
Здравствуйте! Сделал кастомный рендер для оружия(через bakedmodel) если конечно можно назвать это рендером , но суть не в этом , а в translate и rotate , хотелось бы сделать чтобы они всегда выполняли одну и туже "задачу" так сказать , ведь если сделать пару настроек в rotate то в translate по X уже будет смещать не в такие стороны как раньше , как сделать чтобы функционал rotate и translate никогда не "деформировался" ? я думаю это достаточно распространенная проблема , но найти на решение я так и не смог , код рендера прикрепил.
GunRenderer:
package com.deadcraft.deadcraftmod.Renders.Item;
import com.deadcraft.deadcraftmod.Items.Gun.ItemGun;
import com.deadcraft.deadcraftmod.Items.Module.ModuleType;
import com.deadcraft.deadcraftmod.Renders.RenderCustomArms;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.RenderItem;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.block.model.IBakedModel;
import net.minecraft.client.renderer.tileentity.TileEntityItemStackRenderer;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import com.deadcraft.deadcraftmod.client.anim.ReloadAnimation;
import net.minecraft.client.renderer.block.model.ItemCameraTransforms.TransformType;
import com.deadcraft.deadcraftmod.client.model.ItemLayerWrapper;
import com.deadcraft.deadcraftmod.client.model.NoTransformWrapper;
import net.minecraftforge.client.ForgeHooksClient;
import com.deadcraft.deadcraftmod.client.GunRenderTuning;
import com.deadcraft.deadcraftmod.gui.ScopeOverlay;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import org.lwjgl.opengl.GL11;
@SideOnly(Side.CLIENT)
public class GunRenderer extends TileEntityItemStackRenderer {
public static final GunRenderer INSTANCE = new GunRenderer();
private static final float RECOIL_DISTANCE = 0.15f;
private static final int RECOIL_DURATION = 150;
private boolean isRecoiling = false;
private long recoilStartTime = 0;
private float recoilProgress = 0.0f;
private TransformType currentTransformType = TransformType.NONE;
private TransformType lastNonGuiTransformType = TransformType.FIRST_PERSON_RIGHT_HAND;
public void setTransformType(TransformType type) {
this.currentTransformType = (type != null) ? type : TransformType.NONE;
if (type != null && type != TransformType.NONE && type != TransformType.GUI) {
this.lastNonGuiTransformType = type;
}
}
public TransformType getTransformType() {
return this.currentTransformType;
}
@Override
public void renderByItem(ItemStack stack) {
if (!(stack.getItem() instanceof ItemGun)) {
super.renderByItem(stack);
return;
}
Minecraft mc = Minecraft.getMinecraft();
if (mc.player == null || mc.world == null) {
super.renderByItem(stack);
return;
}
updateRecoilAnimation();
GlStateManager.pushMatrix();
GlStateManager.color(1f, 1f, 1f, 1f);
GlStateManager.disableBlend();
GlStateManager.enableDepth();
GlStateManager.depthMask(true);
TransformType type = this.currentTransformType;
if (type == TransformType.NONE) {
type = this.lastNonGuiTransformType != null ? this.lastNonGuiTransformType : TransformType.FIRST_PERSON_RIGHT_HAND;
}
RenderItem renderItem = mc.getRenderItem();
IBakedModel baseModel = renderItem.getItemModelWithOverrides(stack, mc.world, mc.player);
if (baseModel instanceof ItemLayerWrapper) {
baseModel = ((ItemLayerWrapper) baseModel).getInternal();
}
boolean left = (type == TransformType.FIRST_PERSON_LEFT_HAND || type == TransformType.THIRD_PERSON_LEFT_HAND);
ForgeHooksClient.handleCameraTransforms(baseModel, type, left);
if (type == TransformType.FIRST_PERSON_RIGHT_HAND || type == TransformType.FIRST_PERSON_LEFT_HAND) {
applyFirstPersonTransforms(type);
applyRecoilTransform();
applyAnimations(stack, mc);
}
GlStateManager.enableDepth();
GlStateManager.depthMask(true);
GlStateManager.disableBlend();
GlStateManager.color(1f, 1f, 1f, 1f);
GlStateManager.enableTexture2D();
Minecraft.getMinecraft().getTextureManager().bindTexture(net.minecraft.client.renderer.texture.TextureMap.LOCATION_BLOCKS_TEXTURE);
renderItem.renderItem(stack, new NoTransformWrapper(baseModel));
if (type == TransformType.FIRST_PERSON_RIGHT_HAND || type == TransformType.FIRST_PERSON_LEFT_HAND) {
RenderCustomArms.renderFirstPersonArms(type);
}
renderModulesOverlay(stack, type);
GlStateManager.popMatrix();
}
public void triggerRecoil() {
isRecoiling = true;
recoilStartTime = System.currentTimeMillis();
recoilProgress = 0.0f;
}
private void updateRecoilAnimation() {
if (!isRecoiling) {
recoilProgress = 0.0f;
return;
}
long elapsed = System.currentTimeMillis() - recoilStartTime;
if (elapsed >= RECOIL_DURATION) {
isRecoiling = false;
recoilProgress = 0.0f;
return;
}
float t = (float) elapsed / RECOIL_DURATION;
recoilProgress = 1.0f - (float) Math.pow(1.0f - t, 3.0);
}
private void applyRecoilTransform() {
if (recoilProgress <= 0.0f) return;
float offset;
if (recoilProgress < 0.3f) {
offset = (recoilProgress / 0.3f) * RECOIL_DISTANCE;
} else {
float returnProgress = (recoilProgress - 0.3f) / 0.7f;
offset = RECOIL_DISTANCE * (1.0f - returnProgress);
}
//GlStateManager.translate(-offset, 0.0f, 0.0f);
GlStateManager.rotate(-offset * 20.0f, 0.0f, 0.0f, 5.0f);
}
private void applyFirstPersonTransforms(TransformType type) {
boolean isRight = (type == TransformType.FIRST_PERSON_RIGHT_HAND);
float baseScale = isRight ? GunRenderTuning.FP_R_SCALE : GunRenderTuning.FP_L_SCALE;
float adsScale = 1.0f;
if (ScopeOverlay.isScoped) {
adsScale = isRight ? GunRenderTuning.FP_R_ADS_SCALE : GunRenderTuning.FP_L_ADS_SCALE;
}
GlStateManager.scale(baseScale * adsScale, baseScale * adsScale, baseScale * adsScale);
float tx = isRight ? GunRenderTuning.FP_R_TX : GunRenderTuning.FP_L_TX;
float ty = isRight ? GunRenderTuning.FP_R_TY : GunRenderTuning.FP_L_TY;
float tz = isRight ? GunRenderTuning.FP_R_TZ : GunRenderTuning.FP_L_TZ;
if (ScopeOverlay.isScoped) {
tx += isRight ? GunRenderTuning.FP_R_ADS_TX : GunRenderTuning.FP_L_ADS_TX;
ty += isRight ? GunRenderTuning.FP_R_ADS_TY : GunRenderTuning.FP_L_ADS_TY;
tz += isRight ? GunRenderTuning.FP_R_ADS_TZ : GunRenderTuning.FP_L_ADS_TZ;
}
GlStateManager.translate(tx, ty, tz);
float rx = isRight ? GunRenderTuning.FP_R_RX : GunRenderTuning.FP_L_RX;
float ry = isRight ? GunRenderTuning.FP_R_RY : GunRenderTuning.FP_L_RY;
float rz = isRight ? GunRenderTuning.FP_R_RZ : GunRenderTuning.FP_L_RZ;
if (ScopeOverlay.isScoped) {
rx += isRight ? GunRenderTuning.FP_R_ADS_RX : GunRenderTuning.FP_L_ADS_RX;
ry += isRight ? GunRenderTuning.FP_R_ADS_RY : GunRenderTuning.FP_L_ADS_RY;
rz += isRight ? GunRenderTuning.FP_R_ADS_RZ : GunRenderTuning.FP_L_ADS_RZ;
}
if (rz != 0) GlStateManager.rotate(rz, 0, 0, 1);
if (ry != 0) GlStateManager.rotate(ry, 0, 1, 0);
if (rx != 0) GlStateManager.rotate(rx, 1, 0, 0);
}
private void applyAnimations(ItemStack stack, Minecraft mc) {
if (mc.player.isSprinting()) {
GlStateManager.rotate(10, 1, 0, 0);
GlStateManager.rotate(10, 0, 0, 1);
}
ReloadAnimation.apply(stack, mc, Minecraft.getMinecraft().getRenderPartialTicks());
}
private void renderModulesOverlay(ItemStack gunStack, TransformType transformType) {
if (!(gunStack.getItem() instanceof ItemGun)) return;
ItemGun gun = (ItemGun) gunStack.getItem();
Minecraft mc = Minecraft.getMinecraft();
GlStateManager.pushMatrix();
boolean isGuiView = (transformType == TransformType.GUI || transformType == TransformType.GROUND || transformType == TransformType.FIXED);
if (isGuiView) {
GlStateManager.translate(-0.5f, -0.5f, 0.0f);
} else {
GlStateManager.translate(-0.5f, -0.5f, 0.0f);
}
GlStateManager.enablePolygonOffset();
GlStateManager.doPolygonOffset(-1.0f, -10.0f);
GlStateManager.disableLighting();
GlStateManager.enableBlend();
GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
mc.getTextureManager().bindTexture(net.minecraft.client.renderer.texture.TextureMap.LOCATION_BLOCKS_TEXTURE);
for (ModuleType moduleType : ModuleType.values()) {
ItemStack moduleStack = gun.getInstalledModule(gunStack, moduleType);
if (moduleStack.isEmpty()) {
continue;
}
ItemGun.OverlayPos overlayPos = gun.getModuleOverlay(moduleStack.getItem());
if (overlayPos == null) {
continue;
}
TextureAtlasSprite moduleSprite = getItemSprite(moduleStack);
if (moduleSprite == null) {
continue;
}
renderModuleAtPosition(overlayPos, moduleSprite, isGuiView, moduleType);
}
GlStateManager.disableBlend();
GlStateManager.enableLighting();
GlStateManager.doPolygonOffset(0.0f, 0.0f);
GlStateManager.disablePolygonOffset();
GlStateManager.popMatrix();
}
private void renderModuleAtPosition(ItemGun.OverlayPos overlayPos, TextureAtlasSprite sprite, boolean isGuiView, ModuleType moduleType) {
GlStateManager.pushMatrix();
if (isGuiView) {
float pixelSize = 1.0f / 16.0f;
int px = Math.max(0, Math.min(15, overlayPos.x));
int py = Math.max(0, Math.min(15, overlayPos.y));
GlStateManager.translate(px * pixelSize, -py * pixelSize, 0.001f);
drawTexturedQuad(0.0f, 0.0f, pixelSize, pixelSize, sprite, 0.0f);
} else {
float basePixelSize = 1.0f / 16.0f;
float normalizedX = overlayPos.x * basePixelSize;
float normalizedY = -overlayPos.y * basePixelSize;
float moduleWidth = getModuleWidth(moduleType) * basePixelSize;
float moduleHeight = getModuleHeight(moduleType) * basePixelSize;
GlStateManager.translate(normalizedX, normalizedY, 0.001f);
drawTexturedQuad(0.0f, 0.0f, moduleWidth, moduleHeight, sprite, 0.0f);
}
GlStateManager.popMatrix();
}
private float getModuleWidth(ModuleType moduleType) {
switch (moduleType) {
case BARREL: return 1.0f;
case SCOPE: return 1.0f;
case UNDERBARREL: return 1.0f;
case MAGAZINE: return 1.0f;
default: return 1.0f;
}
}
private float getModuleHeight(ModuleType moduleType) {
switch (moduleType) {
case BARREL: return 1.0f;
case SCOPE: return 1.0f;
case UNDERBARREL: return 1.0f;
case MAGAZINE: return 1.0f;
default: return 1.0f;
}
}
private void drawTexturedQuad(float x, float y, float width, float height,
TextureAtlasSprite sprite, float zOffset) {
if (sprite == null) return;
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder buffer = tessellator.getBuffer();
float minU = sprite.getMinU();
float maxU = sprite.getMaxU();
float minV = sprite.getMinV();
float maxV = sprite.getMaxV();
buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);
buffer.pos(x, y, zOffset).tex(minU, maxV).endVertex();
buffer.pos(x + width, y, zOffset).tex(maxU, maxV).endVertex();
buffer.pos(x + width, y + height, zOffset).tex(maxU, minV).endVertex();
buffer.pos(x, y + height, zOffset).tex(minU, minV).endVertex();
tessellator.draw();
}
private static TextureAtlasSprite getItemSprite(ItemStack stack) {
Minecraft mc = Minecraft.getMinecraft();
RenderItem renderItem = mc.getRenderItem();
try {
IBakedModel model = renderItem.getItemModelWithOverrides(stack, mc.world, mc.player);
if (model != null) {
java.util.List<net.minecraft.client.renderer.block.model.BakedQuad> quads =
model.getQuads(null, null, 0L);
if (quads != null && !quads.isEmpty()) {
TextureAtlasSprite quadSprite = quads.get(0).getSprite();
if (quadSprite != null && !"minecraft:missingno".equals(quadSprite.getIconName())) {
return quadSprite;
}
}
TextureAtlasSprite particleSprite = model.getParticleTexture();
if (particleSprite != null && !"minecraft:missingno".equals(particleSprite.getIconName())) {
return particleSprite;
}
}
if (stack.getItem().getRegistryName() != null) {
String domain = stack.getItem().getRegistryName().getResourceDomain();
String path = stack.getItem().getRegistryName().getResourcePath();
String spriteName = domain + ":items/" + path;
TextureAtlasSprite byName = mc.getTextureMapBlocks().getAtlasSprite(spriteName);
if (byName != null && !"minecraft:missingno".equals(byName.getIconName())) {
return byName;
}
}
} catch (Exception e) {
}
return mc.getTextureMapBlocks().getMissingSprite();
}
}
GunRenderTuning(почти безполезный в эом контексте):
package com.deadcraft.deadcraftmod.client;
public class GunRenderTuning {
public static float HAND_R_TX = 0.0f;
public static float HAND_R_TY = 0.0f;
public static float HAND_R_TZ = 0.0f;
public static float HAND_R_RX = 0.0f;
public static float HAND_R_RY = 0.0f;
public static float HAND_R_RZ = 0.0f;
public static float HAND_R_SCALE = 1.10f;
public static float HAND_L_TX = 0.0f;
public static float HAND_L_TY = 0.0f;
public static float HAND_L_TZ = 0.0f;
public static float HAND_L_RX = 0.0f;
public static float HAND_L_RY = 0.0f;
public static float HAND_L_RZ = 0.0f;
public static float HAND_L_SCALE = 1.990f;
public static float FP_R_TX = 0.0f;
public static float FP_R_TY = 0.0f;
public static float FP_R_TZ = 0.0f;
public static float FP_R_RX = 0.0f;
public static float FP_R_RY = 0.0f;
public static float FP_R_RZ = 0.0f;
public static float FP_R_SCALE = 1.340f;
public static float FP_R_ADS_TX = 0.0f;
public static float FP_R_ADS_TY = 0.0f;
public static float FP_R_ADS_TZ = 0.0f;
public static float FP_R_ADS_RX = 0.0f;
public static float FP_R_ADS_RY = 0.0f;
public static float FP_R_ADS_RZ = 0.0f;
public static float FP_R_ADS_SCALE = 1.0f;
public static float FP_L_TX = 0.0f;
public static float FP_L_TY = 0.0f;
public static float FP_L_TZ = 0.0f;
public static float FP_L_RX = 0.0f;
public static float FP_L_RY = 0.0f;
public static float FP_L_RZ = 0.0f;
public static float FP_L_SCALE = 1.0f;
public static float FP_L_ADS_TX = 0.0f;
public static float FP_L_ADS_TY = 0.0f;
public static float FP_L_ADS_TZ = 0.0f;
public static float FP_L_ADS_RX = 0.0f;
public static float FP_L_ADS_RY = 0.0f;
public static float FP_L_ADS_RZ = 0.0f;
public static float FP_L_ADS_SCALE = 1.0f;
public static float MOD_TX = 0.0f;
public static float MOD_TY = 0.00f;
public static float MOD_TZ = 0.00f;
public static float MOD_RX = 0.0f;
public static float MOD_RY = 0.0f;
public static float MOD_RZ = 0.0f;
public static float MOD_SCALE = 1.0f;
}


