Jump to content

[1.7.10] [SOLVED] Directional Models


Whyneb360

Recommended Posts

So I made a post not long ago about a similar issue, but neglected to mention that my tile entity was a model, and so the usual getIcon method doesn't do much. I have seen models be rotated depending on where the player is/is looking in Mr. Crayfish's Furniture mod (so it is possible), and was wondering how to get a similar effect.

 

Thanks in advance,

 

-Whyneb360

Link to comment
Share on other sites

I did this a little while ago in a since-abandoned mod, so maybe take it with a grain of salt, but looking back at my code, in my Renderer class right before the actual model.render, I rotated it with:

[embed=425,349]GL11.glRotatef(/*some rotation variable*/, 0.0F, 1.0F, 0.0F);[/embed]

As far as getting that rotation variable, you'd probably base it off of the metadata like normal. If you have trouble like that, I'm willing to bet that in your earlier post that you mentioned people explain it. The only real difference is rather than picking an image based off of metadata, you pick a rotation angle (in degrees).

Link to comment
Share on other sites

I have been messing around with this idea a bit, but all I have is this - doesn't work yet:

 

Block Class

public static int metadir = 1;

public void onBlockPlacedBy(World p_149689_1_, int p_149689_2_, int p_149689_3_, int p_149689_4_, EntityLivingBase p_149689_5_, ItemStack p_149689_6_)
    {
        int l = MathHelper.floor_double((double)(p_149689_5_.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3;
        int i1 = p_149689_1_.getBlockMetadata(p_149689_2_, p_149689_3_, p_149689_4_) & 4;

        if (l == 0)
        {
            p_149689_1_.setBlockMetadataWithNotify(p_149689_2_, p_149689_3_, p_149689_4_, 2 | i1, 2);
            metadir = 1;
        }

        if (l == 1)
        {
            p_149689_1_.setBlockMetadataWithNotify(p_149689_2_, p_149689_3_, p_149689_4_, 1 | i1, 2);
            metadir = 2;
        }

        if (l == 2)
        {
            p_149689_1_.setBlockMetadataWithNotify(p_149689_2_, p_149689_3_, p_149689_4_, 3 | i1, 2);
            metadir = 3;
        }

        if (l == 3)
        {
            p_149689_1_.setBlockMetadataWithNotify(p_149689_2_, p_149689_3_, p_149689_4_, 0 | i1, 2);
            metadir = 4;
        }
        
        switch (metadir) {
        case 1:            System.out.println("1");
        break;
        case 2:            System.out.println("2");
        break;
        case 3:            System.out.println("3");
        break;
        case 4:            System.out.println("4");
        break;
        default: break;

        }
    }

 

Render Class

public class RenderBoard extends TileEntitySpecialRenderer {

private static final ResourceLocation texture = new ResourceLocation(Main.modID + ":" + "textures/props/BoardTexture.png");

private ModelBoard model;

int dir = BoardProp.metadir;

public RenderBoard() {
	this.model = new ModelBoard();
}

@Override
public void renderTileEntityAt(TileEntity tileentity, double x, double y, double z, float f) {
	GL11.glPushMatrix();
		GL11.glTranslatef((float)x + 0.5F, (float)y + 1.5F, (float)z + 0.5F);
		GL11.glRotatef(180, 0F, 0F, 1F);
		GL11.glRotatef(dir * (-90F), 0F, 1F, 0F);



		this.bindTexture(texture);

		GL11.glPushMatrix();
			this.model.renderModel(0.0625F);
		GL11.glPopMatrix();

	GL11.glPopMatrix();
}
}

 

Any help would be appreciated

 

-Whyneb360

Link to comment
Share on other sites

That is not what static is for.  If you want to save the direction as metadata, save it as metadata, which you're doing and then ignoring in favor of the static variable.

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

Use

world.getBlockMetadata(x,y,z)

to get the metadata. You can get the world with

tileEntity.getWorldObj()

  Also, while this doesn't have to do with your block not being the proper direction,  why do you have a switch statement to figure out what to print for your metadata? You can just do

System.out.println(metadir)

Link to comment
Share on other sites

So with the world.getBlockMetadata, does that replace the getBlockNotify thing or is it meant to go somewhere else? Also, where would I put the tileEntity.getWorldObj() as I already have a parameter 'World world' for getting the world. And sorry, the switch statement was just me trying out some different ideas when I was testing

 

Here is my code now (Forgive me if I placed the world.getBlockMetadata in the wrong place):

 

public int metadir;

public void onBlockPlacedBy(World world, int x, int y, int z, EntityLivingBase player, ItemStack itemstack)
    {
        int l = MathHelper.floor_double((double)(player.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3;
        int i1 = world.getBlockMetadata(x, y, z) & 4;

        if (l == 0)
        {
        	world.getBlockMetadata(x,y,z);
            metadir = 0;
            System.out.println("0");
        }

        if (l == 1)
        {
        	world.getBlockMetadata(x,y,z);
            metadir = 1;
            System.out.println("1");
        }

        if (l == 2)
        {
        	world.getBlockMetadata(x,y,z);
            metadir = 2;
            System.out.println("2");
        }

        if (l == 3)
        {
        	world.getBlockMetadata(x,y,z);
            metadir = 3;
            System.out.println("3");
        }
    }

 

And:

 

public class RenderBoard extends TileEntitySpecialRenderer {

private static final ResourceLocation texture = new ResourceLocation(Main.modID + ":" + "textures/props/BoardTexture.png");

private ModelBoard model;

public RenderBoard() {
	this.model = new ModelBoard();
}	

@Override
public void renderTileEntityAt(TileEntity tileentity, double x, double y, double z, float f) {
	GL11.glPushMatrix();
		GL11.glTranslatef((float)x + 0.5F, (float)y + 1.5F, (float)z + 0.5F);
		GL11.glRotatef(180, 0F, 0F, 1F);
		GL11.glRotatef(metadir * (-90F), 0F, 1F, 0F);



		this.bindTexture(texture);

		GL11.glPushMatrix();
			this.model.renderModel(0.0625F);
		GL11.glPopMatrix();

	GL11.glPopMatrix();
}

 

Though I still haven't figured out how to reference the metadir from my directional methods into my class with the GL11.glRotatef stuff.

 

Thanks,

 

-Whyneb360

Link to comment
Share on other sites

Get rid of

public int metadir;

Use setBlockMetadata when placing the block.  A call to getBlockMetadata that you do nothing with is useless.

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

Getting the metadata while in the render class is precisely what world.getBlockMetadata() is for. Your block class was fine, except for the odd choice of switch statement. GET block metadata is, as one might expect, for GETTING the metadata. So first you SET it form the Block class, like you originally did, with the SETBlockMetadataWithNotify method. Then, in  your renderer class, you GET it with the world.GETBlockMetadata method. In your renderer class, you don't already have a world variable, so that's what tileEntity.getWorldObj() is for. So this way, by setting the metadad when you place it in the block class then getting it in the renderer class, you pass your directional information from your block to your renderer.

Link to comment
Share on other sites

Again, sorry if I have made a rookie mistake, but should I be putting the tileEntity.getWorldObj() in the renderTileEntityAt method and then have the world.getBlockMetadata stright after that? If so, how should I tell the Java that world is the above tileEntity line? This is what I have now (Block class unchanged):

 

public class RenderBoard extends TileEntitySpecialRenderer {

private static final ResourceLocation texture = new ResourceLocation(Main.modID + ":" + "textures/props/BoardTexture.png");

private ModelBoard model;

public RenderBoard() {
	this.model = new ModelBoard();
}	

@Override
public void renderTileEntityAt(TileEntity tileEntity, double x, double y, double z, float f) {
	tileEntity.getWorldObj();
	int dir = world.getBlockMetadata(x, y, z);

	GL11.glPushMatrix();
		GL11.glTranslatef((float)x + 0.5F, (float)y + 1.5F, (float)z + 0.5F);
		GL11.glRotatef(180, 0F, 0F, 1F);
		GL11.glRotatef(dir * (-90F), 0F, 1F, 0F);


		this.bindTexture(texture);

		GL11.glPushMatrix();
			this.model.renderModel(0.0625F);
		GL11.glPopMatrix();

	GL11.glPopMatrix();
}


}

 

Thanks for all your help so far

Link to comment
Share on other sites

World world = tileEntity.getWorldObj(). Or World potato = tileEntity.getWorldObj(), it doesn't really matter, as long as you then put potato.getBlockMetadata(). Its just a variable assignment :/ . You'll also need to actually set dir equal to world.getBlockMetadata(). world.getBlockMetadata() is just a method that returns a value (an integer in this case, which is equal to the block's metadata). It doesn't actually change dir on its own- you need to right dir = world.getBlockMetadata(x,y,z); . It seems you are a little unfamiliar with Java, so I suggest looking at at least a few general purpose Java tutorials before going much further with your mod. You can find a million free ones on the internet.

Link to comment
Share on other sites

Seeing the kind of stuff I want to do in my mod, and given my limited understanding of the environment, I will definitely be taking up some Java courses to get the basics down. Until I do though, I am getting an error here:

 

@Override
public void renderTileEntityAt(TileEntity tileEntity, double x, double y, double z, float f) {
	World world = tileEntity.getWorldObj();
	int dir = world.getBlockMetadata(x, y, z);


	GL11.glPushMatrix();
		GL11.glTranslatef((float)x + 0.5F, (float)y + 1.5F, (float)z + 0.5F);
		GL11.glRotatef(180, 0F, 0F, 1F);
		GL11.glRotatef(dir * (-90F), 0F, 1F, 0F);


		this.bindTexture(texture);

		GL11.glPushMatrix();
			this.model.renderModel(0.0625F);
		GL11.glPopMatrix();

	GL11.glPopMatrix();
}

 

at int dir = world.getBlockMetadata(x, y, z) it wants me to change getBlockMetadata to getBlock. Specifically it says that getBlockMetadata (int, int, int) is not applicable for the arguments double, double, double. Any ideas?

Link to comment
Share on other sites

x, y, and z are doubles. world.getBlockMetadata expects integer parameters. You can solve this just by casting x, y and z to integers. If you don't know how, look at how you cast them to floats in the GL11.glTranslatef() method and, again, I really suggest looking at a java tutorial or two.

Link to comment
Share on other sites

Okay, at this point, I have this code:

 

Render:

 

public class RenderBoard extends TileEntitySpecialRenderer {

private static final ResourceLocation texture = new ResourceLocation(Main.modID + ":" + "textures/props/BoardTexture.png");

private ModelBoard model;

public RenderBoard() {
	this.model = new ModelBoard();
}	

@Override
public void renderTileEntityAt(TileEntity tileEntity, double x, double y, double z, float f) {
	World world = tileEntity.getWorldObj();
	int dir = world.getBlockMetadata((int)x, (int)y, (int)z);


	GL11.glPushMatrix();
		GL11.glTranslatef((float)x + 0.5F, (float)y + 1.5F, (float)z + 0.5F);
		GL11.glRotatef(180, 0F, 0F, 1F);
		GL11.glRotatef(dir * (90F), 0F, 1F, 0F);


		this.bindTexture(texture);

		GL11.glPushMatrix();
			this.model.renderModel(0.0625F);
		GL11.glPopMatrix();

	GL11.glPopMatrix();
}
}

 

Block Class:

 

public class BoardProp extends BlockContainer {

public BoardProp(Material material) {
	super(material);

	this.setCreativeTab(DesconCreativeTabs.tabGeneral);
	this.setHarvestLevel("axe", 1);
	this.setHardness(1F);
	this.setBlockBounds(0F, 0F, 1F, 1F, 1F, 0.875F);
	this.setBlockTextureName(Main.modID + ":" + "textures/blocks/board.png");
}

public int getRenderType() {
	return -1;
}

public boolean isOpaqueCube() {
	return false;
}

public boolean renderAsNormalBlock() {
	return false;
}

@Override
public TileEntity createNewTileEntity(World var1, int var2) {
	return new TileEntityBoard();
}

@SideOnly(Side.CLIENT)
public void registerBlockIcons(IIconRegister iconRegister) {
	this.blockIcon = iconRegister.registerIcon(Main.modID + ":" + this.getUnlocalizedName().substring(5));
}

//Directional Bollocks

public void onBlockPlacedBy(World world, int x, int y, int z, EntityLivingBase player, ItemStack itemstack)
    {
        int l = MathHelper.floor_double((double)(player.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3;
        int i1 = world.getBlockMetadata(x, y, z) & 4;

        if (l == 0)
        {
            world.setBlockMetadataWithNotify(x, y, z, 1 | i1, 2);
            System.out.println("0");
        }

        if (l == 1)
        {
            world.setBlockMetadataWithNotify(x, y, z, 2 | i1, 2);
            System.out.println("1");
        }

        if (l == 2)
        {
            world.setBlockMetadataWithNotify(x, y, z, 3 | i1, 2);
            System.out.println("2");
        }

        if (l == 3)
        {
            world.setBlockMetadataWithNotify(x, y, z, 4 | i1, 2);
            System.out.println("3");
        }
    }
}

 

But it still doesn't work. Anything look wrong?

Link to comment
Share on other sites

Hm. Well, at this point I'm basically just comparing your code to mine, because I'm not exactly an expert on openGL myself. With that in mind, I call GL11.glPushMatrix() before I do either of the rotations, rather than after both of them, which you do. Also, I don't think this would really affect anything, but I don't think your i1 variable in your block class does anything. The metadata for the block before you set it is presumably 0, and 0&4=0. Any number | 0 should be the original number. So I'm pretty sure it doesn't do anything but take up some infinitesimal amount of extra processing power. Again, though, because it doesn't actually do anything, it doesn't do anything BAD either. It just exists, when it probably doesn't have to.

Link to comment
Share on other sites

What "doesn't work"?

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

So I have attempted some debugging to help determine the error, and it seems that in the code below, the Sysout on the onBlockPlacedBy method is all good, but the Sysout for the 'dir' integer in the Render class is only printing continuous 0s. I imagine this means that the rotation stuff is working, but the metadata isn't being set (that or I got the Sysout wrong). My problem is still that the block placed with no errors, but the model doesn't rotate when it's placed from different directions. The game sometimes gives off an error about the tile entity missing a mapping, but I'm not sure if that has anything to do with it.

 

BoardProp:

public class BoardProp extends BlockContainer {

public BoardProp(Material material) {
	super(material);

	this.setCreativeTab(DesconCreativeTabs.tabGeneral);
	this.setHarvestLevel("axe", 1);
	this.setHardness(1F);
	this.setBlockBounds(0F, 0F, 1F, 1F, 1F, 0.875F);
	this.setBlockTextureName(Main.modID + ":" + "textures/blocks/board.png");
}

public int getRenderType() {
	return -1;
}

public boolean isOpaqueCube() {
	return false;
}

public boolean renderAsNormalBlock() {
	return false;
}

@Override
public TileEntity createNewTileEntity(World var1, int var2) {
	return new TileEntityBoard();
}

@SideOnly(Side.CLIENT)
public void registerBlockIcons(IIconRegister iconRegister) {
	this.blockIcon = iconRegister.registerIcon(Main.modID + ":" + this.getUnlocalizedName().substring(5));
}

//Directional Bollocks

public void onBlockPlacedBy(World world, int x, int y, int z, EntityLivingBase player, ItemStack itemstack)
    {
        int l = MathHelper.floor_double((double)(player.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3;

        if (l == 0)
        {
            world.setBlockMetadataWithNotify(x, y, z, 0, l);
            System.out.println("0");
        }

        if (l == 1)
        {
            world.setBlockMetadataWithNotify(x, y, z, 1, l);
            System.out.println("1");
        }

        if (l == 2)
        {
            world.setBlockMetadataWithNotify(x, y, z, 2, l);
            System.out.println("2");
        }

        if (l == 3)
        {
            world.setBlockMetadataWithNotify(x, y, z, 3, l);
            System.out.println("3");
        }
    }
}

 

RenderBoard:

public class RenderBoard extends TileEntitySpecialRenderer {

private static final ResourceLocation texture = new ResourceLocation(Main.modID + ":" + "textures/props/BoardTexture.png");

private ModelBoard model;

public RenderBoard() {
	this.model = new ModelBoard();
}	

@Override
public void renderTileEntityAt(TileEntity tileEntity, double x, double y, double z, float f) {
	World world = tileEntity.getWorldObj();
	int dir = world.getBlockMetadata((int)x, (int)y, (int)z);

	System.out.println(dir);

	GL11.glPushMatrix();
		GL11.glTranslatef((float)x + 0.5F, (float)y + 1.5F, (float)z + 0.5F);
		GL11.glRotatef(180, 0F, 0F, 1F);
		GL11.glRotatef(dir * (-90F), 0F, 1F, 0F);

		this.bindTexture(texture);

		this.model.renderModel(0.0625F);

	GL11.glPopMatrix();
}
}

 

Thanks,

 

-Whyneb360

Link to comment
Share on other sites

I believe the issue now is in your block code, where you do

world.setBlockMetadataWithNotify(x, y, z, 0, l);

The last parameter of the setBlockMetadataWithNotify method is a flag that tells minecraft what to notify about the change to metadata. As a general rule, you usually want it to be 2 (so it notifies the client), and here, where you're dealing with a client-side thing like the direction a model is rendered in, you DEFINITELY want to. Instead, you're setting it to l, which could be 0,1,2, or 3. So what's probably happening is the metadata is set correctly server side, but never passed to the client. So when the renderer class, which only runs on the client side iirc, tries to get the block metadata, it gets the block metadata for the client version of the world, which hasn't changed. Also, because you only ever set the metadata to the value of l in the first place, you can just replace the whole if (l == x) {} set of if statements with

world.setBlockMetadataWithNotify(x,y,z,l,2);
System.out.println(l); //System.out.println is more than robust enough to deal with integers on its own, without you converting them to strings first.

It's much cleaner.

Link to comment
Share on other sites

Usually you want to pass 3 so that the change notifies neighbors.  In this case a 2 is sufficient as the block placement alerted neighbors anyway.

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

Thanks for the help, but it still isn't placing the way I am facing. I only changed the render class, so I will re-post that (in case I messed something up)

 

public void onBlockPlacedBy(World world, int x, int y, int z, EntityLivingBase player, ItemStack itemstack)
    {
        int l = MathHelper.floor_double((double)(player.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3;
        
        world.setBlockMetadataWithNotify(x, y, z, l, 2);
        System.out.println(l);
        
    }
}

Link to comment
Share on other sites

Is there any other way you would be able to do it? If not, what do I have to change in my code to make it work. Like I said in one of my above posts, the Sysout in:

public void onBlockPlacedBy(World world, int x, int y, int z, EntityLivingBase player, ItemStack itemstack)
    {
        int l = MathHelper.floor_double((double)(player.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3;
        
        world.setBlockMetadataWithNotify(x, y, z, l, 2);
        System.out.println(l);
        
    }
}

works, but the Sysout in:

public class RenderBoard extends TileEntitySpecialRenderer {

private static final ResourceLocation texture = new ResourceLocation(Main.modID + ":" + "textures/props/BoardTexture.png");

private ModelBoard model;

public RenderBoard() {
	this.model = new ModelBoard();
}	

@Override
public void renderTileEntityAt(TileEntity tileEntity, double x, double y, double z, float f) {
	World world = tileEntity.getWorldObj();
	int dir = world.getBlockMetadata((int)x, (int)y, (int)z);

	System.out.println(dir);

	GL11.glPushMatrix();
		GL11.glTranslatef((float)x + 0.5F, (float)y + 1.5F, (float)z + 0.5F);
		GL11.glRotatef(180, 0F, 0F, 1F);
		GL11.glRotatef(dir * (-90F), 0F, 1F, 0F);

		this.bindTexture(texture);

		this.model.renderModel(0.0625F);

	GL11.glPopMatrix();
}
}

Doesn't work (just puts out a constant stream of 0s when one of the blocks is placed in the world. I'm not exactly sure, but I would hazard a guess that the metadata is being stored or read properly.

 

Thanks,

 

-Whyneb360

Link to comment
Share on other sites

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

 

x, y and z are referring to the rendering location, which is not centered on the world center 0,0,0, but actually on the player position.

 

Use tileEntity.xCoord, .yCoord and .zCoord to get the correct world coordinates of your TileEntity.

 

The renderer still needs to be translated with the rendering coords x, y, z, though, so keep

GL11.glTranslatef((float)x + 0.5F, (float)y + 1.5F, (float)z + 0.5F);

as it is!

Don't ask for support per PM! They'll get ignored! | If a post helped you, click the "Thank You" button at the top right corner of said post! |

mah twitter

This thread makes me sad because people just post copy-paste-ready code when it's obvious that the OP has little to no programming experience. This is not how learning works.

Link to comment
Share on other sites

I apolologise in advance, but as I am new to forge, I am not quite sure where to put the tileEntity.xCoord, .yCoord and .zCoord. I tried replacing the double x, y and z, but it didn't work, and I didn't think that would be right. If it was for World world = tileEntrity.xCoord, it throws and error when written like that. Sorry if I am missing something obvious, but I am eager to learn how to do this.

 

EDIT: Okay, got it to work, so thanks. Do you have any suggestions for making the hitbox rotate as well?

this.setBlockBounds(0F, 0F, 1F, 1F, 1F, 0.875F);

is what I have at the moment

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.

Announcements



×
×
  • Create New...

Important Information

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