Jetug Posted January 21, 2023 Posted January 21, 2023 (edited) I have an entity and I want its head to have the texture of the player's head. I wrote my layer class like this: public class PlayerHeadLayer extends GeoLayerRenderer<PowerArmorEntity> { public PlayerHeadLayer(IGeoRenderer<PowerArmorEntity> entityRenderer) { super(entityRenderer); } @Override public void render(PoseStack matrixStackIn, MultiBufferSource bufferIn, int packedLightIn, PowerArmorEntity entity, float limbSwing, float limbSwingAmount, float partialTicks, float ageInTicks, float netHeadYaw, float headPitch) { if(!entity.isInvisible() && entity.isVehicle() && entity.getControllingPassenger() instanceof AbstractClientPlayer clientPlayer ) { var texture = clientPlayer.getSkinTextureLocation(); int overlay = OverlayTexture.NO_OVERLAY; var cameo = RenderType.armorCutoutNoCull(texture); matrixStackIn.pushPose(); matrixStackIn.scale(1.0f, 1.0f, 1.0f); matrixStackIn.translate(0.0d, 0.0d, 0.0d); this.getRenderer().render( this.getEntityModel().getModel(POWER_ARMOR_MODEL_LOCATION), entity, partialTicks, cameo, matrixStackIn, bufferIn, bufferIn.getBuffer(cameo), packedLightIn, overlay, 1f, 1f, 1f, 1f); matrixStackIn.popPose(); } } } But the player texture scale is too big Texture of my entity: Edited January 21, 2023 by Jetug Quote
ChampionAsh5357 Posted January 21, 2023 Posted January 21, 2023 Render the head and the rest of the model separately. Apply the player texture to the head and your texture to the rest of the model. Currently, the head texture is being applied to the entire model. Quote
Jetug Posted January 21, 2023 Author Posted January 21, 2023 (edited) 49 minutes ago, ChampionAsh5357 said: Render the head and the rest of the model separately. Apply the player texture to the head and your texture to the rest of the model. Currently, the head texture is being applied to the entire model. I understood the logic, but I don't know how to implement it. I'm new to minecraft modding Edited January 21, 2023 by Jetug Quote
ChampionAsh5357 Posted January 22, 2023 Posted January 22, 2023 23 hours ago, Jetug said: I understood the logic, but I don't know how to implement it. Look at how the LivingEntityRenderer sets the texture and repeat the process in your render method. You already have access to the entity model, so you should know how to render it. As how to separate it, either use two separate models or handle the rendering on the same model in two separate methods or implementations. Quote
Jetug Posted January 22, 2023 Author Posted January 22, 2023 (edited) 1 hour ago, ChampionAsh5357 said: Look at how the LivingEntityRenderer sets the texture and repeat the process in your render method. You already have access to the entity model, so you should know how to render it. As how to separate it, either use two separate models or handle the rendering on the same model in two separate methods or implementations. I decided that it would be easier to do this with the resizing of the player texture and wrote this code while waiting for an answer: @Override public void render(PoseStack matrixStackIn, MultiBufferSource bufferIn, int packedLightIn, PowerArmorEntity entity, float limbSwing, float limbSwingAmount, float parti if(!entity.isInvisible() && entity.isVehicle() && entity.getControllingPassenger() instanceof AbstractClientPlayer clientPlayer ) { var texture = getHeadResourceLocation(clientPlayer, entity); if (texture == null) return; var cameo = RenderType.armorCutoutNoCull(texture); int overlay = OverlayTexture.NO_OVERLAY; matrixStackIn.pushPose(); matrixStackIn.scale(1.0f, 1.0f, 1.0f); matrixStackIn.translate(0.0d, 0.0d, 0.0d); this.getRenderer().render( getEntityModel().getModel(POWER_ARMOR_MODEL_LOCATION), entity, partialTicks, cameo, matrixStackIn, bufferIn, bufferIn.getBuffer(cameo), packedLightIn, overlay, 1f, 1f, 1f, 1f); matrixStackIn.popPose(); } } @Nullable private ResourceLocation getHeadResourceLocation(AbstractClientPlayer clientPlayer, PowerArmorEntity entity) { var tag = clientPlayer.getUUID().toString(); if (playerTextures.containsKey(tag)) { return playerTextures.get(tag); } else { var playerHead = getPlayerHead(clientPlayer); var entityTextureRL = entityRenderer.getTextureLocation(entity); var entityTexture = resourceToBufferedImage(entityTextureRL); if (playerHead == null || entityTexture == null) return null; playerHead = extendImage(playerHead, entityTexture.getWidth(), entityTexture.getHeight()); var nativeImage = getNativeImage(playerHead); var dynamicTexture = new DynamicTexture(nativeImage); var finalTextureLocation = new ResourceLocation(Global.MOD_ID, tag); Minecraft.getInstance().getTextureManager().register(finalTextureLocation, dynamicTexture); playerTextures.put(tag, finalTextureLocation); return finalTextureLocation; } } And it actually worked, but Steve looks like he's turned into a vampire I think the problem is in this method: public static NativeImage getNativeImage(BufferedImage img) { NativeImage nativeImage = new NativeImage(img.getWidth(), img.getHeight(), true); for (int x = 0; x < img.getWidth(); x++) { for (int y = 0; y < img.getHeight(); y++) { var color = img.getRGB(x, y); nativeImage.setPixelRGBA(x, y, color); } } return nativeImage; } Full code: https://github.com/Jetug/PowerArmorMod/blob/1.18/src/main/java/com/jetug/power_armor_mod/client/render/layers/PlayerHeadLayer.java Edited January 22, 2023 by Jetug Quote
ChampionAsh5357 Posted January 22, 2023 Posted January 22, 2023 23 minutes ago, Jetug said: I decided that it would be easier to do this with the resizing of the player texture That's a lot harder. You literally just need two models or simply render the head part manually with the applied texture. And then you just need to create the rendertype with the texture twice. It's literally just what the LivingEntityRenderer is doing twice. 26 minutes ago, Jetug said: I think the problem is in this method: The pixel information is stored in BGRA format, so that makes sense. 1 Quote
Jetug Posted January 22, 2023 Author Posted January 22, 2023 2 hours ago, ChampionAsh5357 said: That's a lot harder. You literally just need two models or simply render the head part manually with the applied texture. And then you just need to create the rendertype with the texture twice. It's literally just what the LivingEntityRenderer is doing twice. The pixel information is stored in BGRA format, so that makes sense. Maybe harder but i already did it :) Anyway thank you, I corrected the method and now it works public static NativeImage getNativeImage(BufferedImage img) { NativeImage nativeImage = new NativeImage(img.getWidth(), img.getHeight(), true); for (int x = 0; x < img.getWidth(); x++) { for (int y = 0; y < img.getHeight(); y++) { int clr = img.getRGB(x, y); int alpha = (clr & 0xff000000) >> 24; int red = (clr & 0x00ff0000) >> 16; int green = (clr & 0x0000ff00) >> 8; int blue = clr & 0x000000ff; int rgb = alpha; rgb = (rgb << 8) + blue; rgb = (rgb << 8) + green; rgb = (rgb << 8) + red; nativeImage.setPixelRGBA(x, y, rgb); } } return nativeImage; } Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.