Jump to content

RESOLVED: How to a make 2D texture that always faces player.


Flayr

Recommended Posts

EDIT: I actually figured out the solutions to my problems on my own, thanks for all the help though!

 

Okay, so I have been trying to find a way to do this for a while now, but I just can't figure it out.

 

I am trying to make a floating sphere block and to do it I want to make a 2d texture that always appears to face the player (like all of the round enemies in super Mario 64).

 

Is there any possible way to do this, and if so how is it done? Also I want to make it a block, not an entity.

 

Edit:

I was having so much trouble with the suggested rendering code I just decided to write my own.

After writing and debugging it I ran into two different problems. Here is the code to keep in mind while reading them:

package flayr.magiclights.tileentities;

import org.lwjgl.opengl.GL11;

import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ResourceLocation;

public class LightRenderer extends TileEntitySpecialRenderer{
    
    public void renderTileEntityAt(TileEntity tileentity, double x, double y, double z, float f) {

    	ResourceLocation rl = new ResourceLocation("minecraft:assets/magiclights/textures/blocks/light.png");
    	Minecraft.getMinecraft().renderEngine.bindTexture(rl);
    	
        Tessellator tessellator = Tessellator.instance;
        GL11.glPushMatrix();
        GL11.glTranslated(x+0.5, y+0.5, z+0.5);//+1 so that our "drawing" appears 1 block over our block (to get a better view)
        GL11.glNormal3f(0.0F, 1.0F, 0.0F);
        GL11.glRotatef(-this.tileEntityRenderer.playerYaw, 0.0F, 1.0F, 0.0F);
        GL11.glRotatef(this.tileEntityRenderer.playerPitch, 1.0F, 0.0F, 0.0F);
        
        tessellator.startDrawingQuads();
        
        tessellator.addVertex(-0.5, 0.5, 0);
        tessellator.addVertex(0.5, 0.5, 0);
        tessellator.addVertex(-0.5, -0.5, 0);
        tessellator.addVertex(0.5, -0.5, 0);
        
        tessellator.addVertex(0.5, -0.5, 0);
        tessellator.addVertex(-0.5, -0.5, 0);
        tessellator.addVertex(0.5, 0.5, 0);
        tessellator.addVertex(-0.5, 0.5, 0);

        tessellator.draw();
        GL11.glPopMatrix();
    }
}

 

!. In order to render a square with its center as the origin (so I could rotate the square within the block) I had to make two triangles that formed a square (you will see this in the code). I was wondering if anyone had a better way of doing this.

 

2. I cannot get the proper texture for the drawn object (my texture is located in /forge/mcp/src/minecraft/assets/textures/blocks/light.png), how am I supposed to bind the texture because my current method has failed.

Link to comment
Share on other sites

You will need a custom rendering handler.  This is easier to do as a tile entity (think chests) than with a block (think fences).

 

That said, it is possible.

 

Here's some code that will render a flat, rectangular, plane that always faces the player (assuming I didn't leave anything out).

 

    float d = xPos; //location
    float d1 = yPos;
    float d2 = zPos;
    float f1 = 1.6F;
    float f2 = 0.01666667F * f1;
    GL11.glPushMatrix();
    GL11.glTranslatef((float)d, (float)d1, (float)d2);
    GL11.glNormal3f(0.0F, 1.0F, 0.0F);
    GL11.glRotatef(-this.tileEntityRenderer.playerYaw, 0.0F, 1.0F, 0.0F);
    GL11.glRotatef(this.tileEntityRenderer.playerPitch, 1.0F, 0.0F, 0.0F);
    GL11.glScalef(-f2, -f2, f2);
    GL11.glDisable(2896);
    GL11.glDepthMask(false);
    GL11.glDisable(2929);
    GL11.glEnable(3042);
    GL11.glBlendFunc(770, 771);
    Tessellator tessellator = Tessellator.instance;
    byte byte0 = 0;
    GL11.glDisable(3553);
    tessellator.disableColor();
    tessellator.startDrawingQuads();
    int j = width;//set width of plane here
    tessellator.setColorRGBA_F(0.0F, 0.0F, 0.0F, 1F);
    tessellator.addVertex(-j - 1, -1 + byte0, 0.0D);
    tessellator.addVertex(-j - 1, 8 + byte0, 0.0D);
    tessellator.addVertex(j + 1, 8 + byte0, 0.0D);
    tessellator.addVertex(j + 1, -1 + byte0, 0.0D);
    tessellator.draw();
    GL11.glPopMatrix();

 

This code is part of what's used to draw labeles above player's heads (etc.) only without the text portion.

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Link to comment
Share on other sites

You will need a custom rendering handler.  This is easier to do as a tile entity (think chests) than with a block (think fences).

 

That said, it is possible.

 

Here's some code that will render a flat, rectangular, plane that always faces the player (assuming I didn't leave anything out).

 

    float d = xPos; //location
    float d1 = yPos;
    float d2 = zPos;
    float f1 = 1.6F;
    float f2 = 0.01666667F * f1;
    GL11.glPushMatrix();
    GL11.glTranslatef((float)d, (float)d1, (float)d2);
    GL11.glNormal3f(0.0F, 1.0F, 0.0F);
    GL11.glRotatef(-this.tileEntityRenderer.playerYaw, 0.0F, 1.0F, 0.0F);
    GL11.glRotatef(this.tileEntityRenderer.playerPitch, 1.0F, 0.0F, 0.0F);
    GL11.glScalef(-f2, -f2, f2);
    GL11.glDisable(2896);
    GL11.glDepthMask(false);
    GL11.glDisable(2929);
    GL11.glEnable(3042);
    GL11.glBlendFunc(770, 771);
    Tessellator tessellator = Tessellator.instance;
    byte byte0 = 0;
    GL11.glDisable(3553);
    tessellator.disableColor();
    tessellator.startDrawingQuads();
    int j = width;//set width of plane here
    tessellator.setColorRGBA_F(0.0F, 0.0F, 0.0F, 1F);
    tessellator.addVertex(-j - 1, -1 + byte0, 0.0D);
    tessellator.addVertex(-j - 1, 8 + byte0, 0.0D);
    tessellator.addVertex(j + 1, 8 + byte0, 0.0D);
    tessellator.addVertex(j + 1, -1 + byte0, 0.0D);
    tessellator.draw();
    GL11.glPopMatrix();

 

This code is part of what's used to draw labeles above player's heads (etc.) only without the text portion.

 

How would I implement this and how do I specify the texture?

 

Thanks in advance.

Link to comment
Share on other sites

For me, that's in a TileEntitySpecialRenderer, as for a texture, you would just need to bind a texture:

ResourceLocation rl = new ResourceLocation("artifacts:textures/blocks/pedestal.png");
Minecraft.getMinecraft().renderEngine.bindTexture(rl);

(Do that instead of the GL11.glColor(...) call; or rather, do it after and change the color to white)

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Link to comment
Share on other sites

For me, that's in a TileEntitySpecialRenderer, as for a texture, you would just need to bind a texture:

ResourceLocation rl = new ResourceLocation("artifacts:textures/blocks/pedestal.png");
Minecraft.getMinecraft().renderEngine.bindTexture(rl);

(Do that instead of the GL11.glColor(...) call; or rather, do it after and change the color to white)

Okay, it is still not working, here is my code.

 

MagicLights

package flayr.magiclights;

// This Import list will grow longer with each additional tutorial.
// It's not pruned between full class postings, unlike other tutorial code.
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraftforge.common.Configuration;
import net.minecraftforge.common.MinecraftForge;
import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.Mod.EventHandler;
import cpw.mods.fml.common.Mod.Init;
import cpw.mods.fml.common.Mod.Instance;
import cpw.mods.fml.common.Mod.PostInit;
import cpw.mods.fml.common.Mod.PreInit;
import cpw.mods.fml.common.SidedProxy;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.event.FMLPostInitializationEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.network.NetworkMod;
import cpw.mods.fml.common.registry.GameRegistry;
import cpw.mods.fml.common.registry.LanguageRegistry;

@Mod(modid = MagicLights.MOD_ID, name = MagicLights.MOD_NAME, version = MagicLights.MOD_VERSION)
@NetworkMod(clientSideRequired = true, serverSideRequired = false)
public class MagicLights
{
    public static final String MOD_ID = "MagicLights";
    static final String MOD_NAME = "Magic Lights";
    static final String MOD_VERSION = "1.0.3";
    static final String SOURCE_PATH = "flayr.magiclights.";
    private static int lightStaffID;
    private static int lightID;
    public static Item lightStaff;
    public static Block light;
    
public static CreativeTabs tabMagicLights = new CreativeTabs("tabMagicLights"){
	public ItemStack getIconItemStack(){
		return new ItemStack(lightStaff);
	}
};
    
        @Mod.Instance("MOD_ID")
        public static MagicLights instance;

        @SidedProxy(clientSide="flayr.magiclights.client.ClientProxy",
                        serverSide="flayr.magiclights.CommonProxy")
        public static CommonProxy proxy;
        
        @EventHandler
        public void preInit(FMLPreInitializationEvent event) {
            Configuration config = new Configuration(event.getSuggestedConfigurationFile());
       
            config.load();
            lightID = config.getBlock("light", 672).getInt();
            lightStaffID = config.getItem("lightStaff", 2527).getInt();
            config.save();
        }
        
        @EventHandler
        public void load(FMLInitializationEvent event) {
            lightStaff = new LightStaff(lightStaffID);
            
            light = new Light(lightID, Material.rock)
            .setHardness(0.0F).setLightValue(1.0f).setUnlocalizedName("lightStaffBlock").setCreativeTab(MagicLights.tabMagicLights);
            
        	ItemStack starStack = new ItemStack(Item.netherStar);
        	ItemStack stickStack = new ItemStack(Item.stick);
        	ItemStack goldStack = new ItemStack(Item.ingotGold);
        	
        	GameRegistry.addRecipe(new ItemStack(lightStaff, 4), "gng", " s ", " s ",
        	        'n', starStack, 's', stickStack, 'g', goldStack);
        	    
            LanguageRegistry.addName(lightStaff, "Staff of Light");
            LanguageRegistry.addName(light, "Light");
            LanguageRegistry.instance().addStringLocalization("itemGroup.tabMagicLights", "en_US", MOD_NAME);
            GameRegistry.registerBlock(light, "light");
            GameRegistry.registerTileEntity(flayr.magiclights.tileentities.TileEntityLight.class, "lightTileEntity");
        }
        
        @Mod.EventHandler
        public void postInit(FMLPostInitializationEvent event) {
                // Stub Method
        }
}

ClientProxy

package flayr.magiclights.client;

import cpw.mods.fml.client.registry.ClientRegistry;
import flayr.magiclights.CommonProxy;
import net.minecraftforge.client.MinecraftForgeClient;

public class ClientProxy extends CommonProxy {
        
        @Override
        public void registerRenderers() {
        	ClientRegistry.bindTileEntitySpecialRenderer(flayr.magiclights.tileentities.TileEntityLight.class, new flayr.magiclights.tileentities.LightRenderer());
        }
        
}

Light

package flayr.magiclights;

import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import flayr.magiclights.tileentities.TileEntityLight;
import net.minecraft.block.BlockContainer;
import net.minecraft.block.material.Material;
import net.minecraft.client.renderer.texture.IconRegister;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;

public class Light extends BlockContainer 
{
        public Light (int id, Material material) 
        {
        	
                super(id, material);
        }
        @Override
        @SideOnly(Side.CLIENT)
        public boolean shouldSideBeRendered(IBlockAccess iblockaccess, int i, int j, int k, int l)
        {
           return false;
        }

        public boolean isOpaqueCube()
        {
           return false;}

	@Override
	public TileEntity createNewTileEntity(World world) {
		// TODO Auto-generated method stub
		return new TileEntityLight();
	}
}

TileEntityLight


LightRenderer

package flayr.magiclights.tileentities;

import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.AbstractClientPlayer;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ChatMessageComponent;
import net.minecraft.util.ChunkCoordinates;
import net.minecraft.util.ResourceLocation;

import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL12;

import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;

@SideOnly(Side.CLIENT)
public class LightRenderer extends TileEntitySpecialRenderer {
@Override

public void renderTileEntityAt(TileEntity entity, double d, double d1, double d2, float par8) {
	renderTileEntityAt((TileEntityLight)entity, d, d1, d2, par8);

    float f1 = 1.6F;
    float f2 = 0.01666667F * f1;
    GL11.glPushMatrix();
    GL11.glTranslatef((float)d, (float)d1, (float)d2);
    GL11.glNormal3f(0.0F, 1.0F, 0.0F);
    GL11.glRotatef(-this.tileEntityRenderer.playerYaw, 0.0F, 1.0F, 0.0F);
    GL11.glRotatef(this.tileEntityRenderer.playerPitch, 1.0F, 0.0F, 0.0F);
    GL11.glScalef(-f2, -f2, f2);
    GL11.glDisable(2896);
    GL11.glDepthMask(false);
    GL11.glDisable(2929);
    GL11.glEnable(3042);
    GL11.glBlendFunc(770, 771);
    Tessellator tessellator = Tessellator.instance;
    byte byte0 = 0;
    GL11.glDisable(3553);
    tessellator.disableColor();
    tessellator.startDrawingQuads();
    int j = 16;//set width of plane here
    tessellator.setColorRGBA_F(0.0F, 0.0F, 0.0F, 1F);
    ResourceLocation rl = new ResourceLocation("artifacts:textures/blocks/light");
    Minecraft.getMinecraft().renderEngine.bindTexture(rl);
    tessellator.addVertex(-j - 1, -1 + byte0, 0.0D);
    tessellator.addVertex(-j - 1, 8 + byte0, 0.0D);
    tessellator.addVertex(j + 1, 8 + byte0, 0.0D);
    tessellator.addVertex(j + 1, -1 + byte0, 0.0D);
    tessellator.draw();
    GL11.glPopMatrix();
}
package flayr.magiclights.tileentities;

import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.INetworkManager;
import net.minecraft.network.packet.Packet;
import net.minecraft.network.packet.Packet132TileEntityData;
import net.minecraft.tileentity.TileEntity;

public class TileEntityLight extends TileEntity {

public void writeToNBT(NBTTagCompound nbt) {
	super.writeToNBT(nbt);
}

public void readFromNBT(NBTTagCompound nbt) {
	super.readFromNBT(nbt);
}

public Packet getDescriptionPacket() {
	NBTTagCompound nbtTag = new NBTTagCompound();
	this.writeToNBT(nbtTag);
	return new Packet132TileEntityData(this.xCoord, this.yCoord,
			this.zCoord, 1, nbtTag);
}

public void onDataPacket(INetworkManager net, Packet132TileEntityData packet) {
	readFromNBT(packet.data);
}
}
}

Any ideas what I am doing wrong? Sorry for being such a bother, I am relatively new to forge modding and have not worked with custom renders yet.

Link to comment
Share on other sites

First you don't need @SideOnly(Side.CLIENT) on

public boolean shouldSideBeRendered(IBlockAccess iblockaccess, int i, int j, int k, int l)
        {
           return false;
        }

and you don't want

@Override
	public TileEntity createNewTileEntity(World world) {
		// TODO Auto-generated method stub
		return new TileEntityLight();
	}

you want

        public TileEntity createNewTileEntity(World par1World)
        {
                 return new TileCompressionChamber();
        }

you need to override

isOpqueCube

and you need a

@Override
        public boolean renderAsNormalBlock()
        {
        	return false;
        }

method

Link to comment
Share on other sites

Okay, so I used some of your changes and got it to render the entity, the problem is that this happens.

 

width=800 height=449http://i1299.photobucket.com/albums/ag79/jackawrey/2013-10-06_170243_zpsd5a7b341.png[/img]

 

I think the problem is just the custom renderer file. Let me know if there is anything wrong with it.

 

package flayr.magiclights.tileentities;

import org.lwjgl.opengl.GL11;

import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ResourceLocation;

public class LightRenderer extends TileEntitySpecialRenderer{
    

    public void renderTileEntityAt(TileEntity tileentity, double x, double y, double z, float f) {

        float f1 = 1.6F;
        float f2 = 0.01666667F * f1;
        GL11.glPushMatrix();
        GL11.glTranslatef((float)x, (float)y, (float)z);
        GL11.glTranslated(0.5, 0.5, 0.5);
        GL11.glNormal3f(0.0F, 1.0F, 0.0F);
        GL11.glRotatef(-this.tileEntityRenderer.playerYaw, 0.0F, 1.0F, 0.0F);
        GL11.glRotatef(this.tileEntityRenderer.playerPitch, 1.0F, 0.0F, 0.0F);
        GL11.glScalef(-f2, -f2, f2);
        GL11.glDisable(2896);
        GL11.glDepthMask(false);
        GL11.glDisable(2929);
        GL11.glEnable(3042);
        GL11.glBlendFunc(770, 771);
        Tessellator tessellator = Tessellator.instance;
        byte byte0 = 0;
        GL11.glDisable(3553);
        tessellator.disableColor();
        tessellator.startDrawingQuads();
        int j = 3;
        tessellator.setColorRGBA_F(1F, 1F, 1F, 1F);
        ResourceLocation rl = new ResourceLocation("assets:magiclights/textures/blocks/light.png");
        Minecraft.getMinecraft().renderEngine.bindTexture(rl);
        tessellator.addVertex(-j - 1, -1 + byte0, 0.0D);
        tessellator.addVertex(-j - 1, 8 + byte0, 0.0D);
        tessellator.addVertex(j + 1, 8 + byte0, 0.0D);
        tessellator.addVertex(j + 1, -1 + byte0, 0.0D);
        tessellator.draw();
        GL11.glPopMatrix();
    }
}

 

If you want to see the rest of the source here it is: https://github.com/TheJawrey/Magic-Lights.

 

Edit:

How should I link to the file? It is located in /forge/mcp/src/minecraft/assets/magiclights/light.png.

Link to comment
Share on other sites

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.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.