Jump to content

[SOLVED] [1.7] Rotate textures on a block


Jhary

Recommended Posts

Hi!

 

I want to rotate the textures of some block faces based of the orientation of the block. The problem is, I don't want to setup a texture for every possible state, that would be too much :D

 

I know I can achieve this with using an ISimpleBlockRenderingHandler and registering it with my custom block.

 

But I can't really figure out how to properly write the

public boolean renderWorldBlock(IBlockAccess world, int x, int y, int z, Block block, int modelId, RenderBlocks renderer) { }

method in my custom rendering class.

 

More details of what I want to achieve:

The TileEntity can already face in any of the six minecraft directions. Based on its orientation the textures that are not "front" and "back" have to be

rotated properly because of their visuals.

 

I searched a bit here and there but I did not find a source I could work with. Maybe I did not understand something the right way. The problem is, I don't really know

how to setup the renderWorldBlock method. Only thing that I think I am knowing is that I have to use the "uveRotate*" methods of the RenderBlocks class..

 

Regards,

 

Jhary

Link to comment
Share on other sites

That could work. Not really sure what that is though.

 

This question is making me think tessellator. With it you can render a basic cube and depending on the state, start at different points and draw the same texture. Viola, textures rotated. But yeah... That could be inefficient.

We all stuff up sometimes... But I seem to be at the bottom of that pot.

Link to comment
Share on other sites

Hmm ok I can't really wrap my head around this tessellator stuff, but it seems to be exactly what I need.

Sadly I can't find a good example of someone using this with 1.7.

I understand how to first setup the tessellator and that I have to do for each side of a block 4 times the "addVertexWithUV(x, y, z, u, v)" method.

 

But I don't really understand how to setup the parameters.

Lets say my block has the in world coordinates [10 ; 10 ; 10].

 

How would I setup the first four addVertexWithUV calls, lets say for the south side?

 

In this article (http://greyminecraftcoder.blogspot.com.au/2013/08/the-tessellator.html) there are four points  defined as A, B, C and D

 

I would understand this as follows according to the picture in the article :

A: .addVertexWithUV(11, 10, 10, u, v)

B: .addVertexWithUV(11, 11, 10, u, v)

C: .addVertexWithUV(10, 11, 10, u, v)

D: .addVertexWithUV(10, 10, 10, u, v)

 

Would here x, y, z be correct? And if yes, how would I now find out what I have to use for u and v ?

 

Link to comment
Share on other sites

Hi

 

If you are doing the z = 10 positive face (south), then yes that's right, except that in an IBSRH it has already translated the coordinates for you, so you should draw between [0,0,0] and [1,1,1] instead, i.e.

A: .addVertexWithUV(1, 0, 0, u, v)

B: .addVertexWithUV(1, 1, 0, u, v)

etc

regarding u,v: if you have bound the texture yourself and the face is the whole texture, then your u,v coordinates are 0 -> 1 with the v axis pointing in the opposite direction to y, so in your case

A: .addVertexWithUV(1, 0, 0, 1, 1)

B: .addVertexWithUV(1, 1, 0, 1, 0)

etc

 

If each of your faces is an icon (the usual way to do it),  use

icon.getMinU(), icon.getMaxU(), icon.getMinV(), icon.getMaxV()

 

-TGG

Link to comment
Share on other sites

ok I got it now working that it renders correctly. Here is my method so far:

 

@Override
    public boolean renderWorldBlock(IBlockAccess world, int x, int y, int z, Block block, int modelId, RenderBlocks renderer) {

    	Tessellator tessellator = Tessellator.instance;

    	IIcon up = block.getIcon(world, x, y, z, 1);
    	IIcon down = block.getIcon(world, x, y, z, 0);
    	IIcon north = block.getIcon(world, x, y, z, 2);
    	IIcon south = block.getIcon(world, x, y, z, 3);
    	IIcon west = block.getIcon(world, x, y, z, 4);
    	IIcon east = block.getIcon(world, x, y, z, 5);
    	
    	//Down 0
    	tessellator.addVertexWithUV(x+1, y  , z  , (double)down.getMaxU(), (double)down.getMaxV());
    	tessellator.addVertexWithUV(x+1, y  , z+1, (double)down.getMaxU(), (double)down.getMinV());
    	tessellator.addVertexWithUV(x  , y  , z+1, (double)down.getMinU(), (double)down.getMinV());
    	tessellator.addVertexWithUV(x  , y  , z  , (double)down.getMinU(), (double)down.getMaxV());
    	
    	//Up 1
    	tessellator.addVertexWithUV(x+1, y+1, z+1, (double)up.getMaxU(), (double)up.getMaxV());
    	tessellator.addVertexWithUV(x+1, y+1, z  , (double)up.getMaxU(), (double)up.getMinV());
    	tessellator.addVertexWithUV(x  , y+1, z  , (double)up.getMinU(), (double)up.getMinV());
    	tessellator.addVertexWithUV(x  , y+1, z+1, (double)up.getMinU(), (double)up.getMaxV());
    	
    	//North 2
    	tessellator.addVertexWithUV(x  , y  , z  , (double)north.getMaxU(), (double)north.getMaxV());
    	tessellator.addVertexWithUV(x  , y+1, z  , (double)north.getMaxU(), (double)north.getMinV());
    	tessellator.addVertexWithUV(x+1, y+1, z  , (double)north.getMinU(), (double)north.getMinV());
    	tessellator.addVertexWithUV(x+1, y  , z  , (double)north.getMinU(), (double)north.getMaxV());
    	
    	//South 3
    	tessellator.addVertexWithUV(x+1, y  , z+1, (double)south.getMaxU(), (double)south.getMaxV());
    	tessellator.addVertexWithUV(x+1, y+1, z+1, (double)south.getMaxU(), (double)south.getMinV());
    	tessellator.addVertexWithUV(x  , y+1, z+1, (double)south.getMinU(), (double)south.getMinV());
    	tessellator.addVertexWithUV(x  , y  , z+1, (double)south.getMinU(), (double)south.getMaxV());
    	
    	//West 4
    	tessellator.addVertexWithUV(x  , y  , z+1, (double)west.getMaxU(), (double)west.getMaxV());
    	tessellator.addVertexWithUV(x  , y+1, z+1, (double)west.getMaxU(), (double)west.getMinV());
    	tessellator.addVertexWithUV(x  , y+1, z  , (double)west.getMinU(), (double)west.getMinV());
    	tessellator.addVertexWithUV(x  , y  , z  , (double)west.getMinU(), (double)west.getMaxV());
    	
    	//East 5
    	tessellator.addVertexWithUV(x+1, y  , z  , (double)east.getMaxU(), (double)east.getMaxV());
    	tessellator.addVertexWithUV(x+1, y+1, z  , (double)east.getMaxU(), (double)east.getMinV());
    	tessellator.addVertexWithUV(x+1, y+1, z+1, (double)east.getMinU(), (double)east.getMinV());
    	tessellator.addVertexWithUV(x+1, y  , z+1, (double)east.getMinU(), (double)east.getMaxV());
    	       
        return true;
    }

 

It does not rotate the textures at this point. But it seems to work so far, but with one problem. Depending on different angles when moving around the block,

the textures seem to flicker some times between just a black pane and the expected texture... does anyone know why?

 

Next question would be, where in this method do I have to do the rotation with the renderer.uvRotate* thingy?

 

Edit: the "flickering" does occur on all placed blocks at the same time when looking at them from some angles

Link to comment
Share on other sites

Hi

 

The black is probably because you haven't set up the lighting and brightness, so it is using the settings from the last thing it rendered.

 

This is typically done using something like

            tessellator.setBrightness(par1Block.getMixedBrightnessForBlock(this.blockAccess, wx, wy, wz); // wx,wy,wz = world coordinates
            tessellator.setColorOpaque_F(red, green, blue);  // from 0.0 - 1.0

 

If you want to rotate the faces using uvRotate, you need to call RenderBlocks.renderStandardBlock or  RenderBlocks.render after setting the flags.

 

See vanilla RenderBlocks.renderBlockLog for a good example.  The rotation is a bit strange, sometimes it flips the faces.  But if that doesn't bother you then you don't need the Tessellator at all.

 

-TGG

Link to comment
Share on other sites

Ok finally had the time to give it a try and it works like a charm if I just don't use the tessellator and therefore use the RenderBlocks object.

 

Rotation is easily done and for the lighting is no additional setup neccessary.

 

I will post the code here if anyone else needs a reference :)

 

Thanks again!

 

@Override
    public boolean renderWorldBlock(IBlockAccess world, int x, int y, int z, Block block, int modelId, RenderBlocks renderer) {

    	IIcon up = block.getIcon(world, x, y, z, 1);
    	IIcon down = block.getIcon(world, x, y, z, 0);
    	IIcon north = block.getIcon(world, x, y, z, 2);
    	IIcon south = block.getIcon(world, x, y, z, 3);
    	IIcon west = block.getIcon(world, x, y, z, 4);
    	IIcon east = block.getIcon(world, x, y, z, 5);
    	
    	renderer.renderFaceXNeg(block, x, y, z, west);
    	renderer.renderFaceXPos(block, x, y, z, east);
    	renderer.renderFaceYNeg(block, x, y, z, down);
    	renderer.renderFaceYPos(block, x, y, z, up);
    	renderer.renderFaceZNeg(block, x, y, z, north);
    	renderer.renderFaceZPos(block, x, y, z, south);
    	
    	TileEntity tile = world.getTileEntity(x, y, z);
    	if(tile instanceof TileEntityMyTile){
    		//wonky rendering incoming
    		switch(((TileEntityMyTile)tile).orientation.ordinal()){
    			case 0: //Bottom
    				renderer.uvRotateNorth=2; //west
    				renderer.uvRotateSouth=1; //east
    				renderer.uvRotateWest=2; //south
    				renderer.uvRotateEast=1; //north
    				break;
    			case 1: //Top
    				renderer.uvRotateNorth=1;
    				renderer.uvRotateSouth=2;
    				renderer.uvRotateWest=1;
    				renderer.uvRotateEast=2;
    				break;				
    			case 2: //North
    				renderer.uvRotateTop = 1;
    				renderer.uvRotateBottom = 2;
    				
    				break;
    			case 3: //South
    				renderer.uvRotateTop=2;
    				renderer.uvRotateBottom=1;
    				renderer.uvRotateNorth=3; 
    				renderer.flipTexture=true; //east
    				break;
    			case 4: //West
    				renderer.uvRotateTop=4;
    				renderer.uvRotateBottom=4;
    				break;
    			case 5: //East
    				renderer.uvRotateTop=3;
    				renderer.uvRotateBottom=3;
    				renderer.flipTexture=true;
    				break;
    		}
    	}
    	
    	boolean flag = renderer.renderStandardBlock(block, x, y, z);
    	//important reset afterwards!
    	renderer.flipTexture=false; 
    	renderer.uvRotateNorth=0; //west
	renderer.uvRotateSouth=0; //east
	renderer.uvRotateWest=0; //south
	renderer.uvRotateEast=0; //north
	renderer.uvRotateTop=0;
	renderer.uvRotateBottom=0;
	return flag;
}

 

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



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • They were already updated, and just to double check I even did a cleanup and fresh update from that same page. I'm quite sure drivers are not the problem here. 
    • i tried downloading the drivers but it says no AMD graphics hardware has been detected    
    • Update your AMD/ATI drivers - get the drivers from their website - do not update via system  
    • As the title says i keep on crashing on forge 1.20.1 even without any mods downloaded, i have the latest drivers (nvidia) and vanilla minecraft works perfectly fine for me logs: https://pastebin.com/5UR01yG9
    • Hello everyone, I'm making this post to seek help for my modded block, It's a special block called FrozenBlock supposed to take the place of an old block, then after a set amount of ticks, it's supposed to revert its Block State, Entity, data... to the old block like this :  The problem I have is that the system breaks when handling multi blocks (I tried some fix but none of them worked) :  The bug I have identified is that the function "setOldBlockFields" in the item's "setFrozenBlock" function gets called once for the 1st block of multiblock getting frozen (as it should), but gets called a second time BEFORE creating the first FrozenBlock with the data of the 1st block, hence giving the same data to the two FrozenBlock :   Old Block Fields set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=head] BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@73681674 BlockEntityData : id:"minecraft:bed",x:3,y:-60,z:-6} Old Block Fields set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=foot] BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@6d1aa3da BlockEntityData : {id:"minecraft:bed",x:2,y:-60,z:-6} Frozen Block Entity set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=foot] BlockPos{x=3, y=-60, z=-6} BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@6d1aa3da BlockEntityData : {id:"minecraft:bed",x:2,y:-60,z:-6} Frozen Block Entity set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=foot] BlockPos{x=2, y=-60, z=-6} BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@6d1aa3da BlockEntityData : {id:"minecraft:bed",x:2,y:-60,z:-6} here is the code inside my custom "freeze" item :    @Override     public @NotNull InteractionResult useOn(@NotNull UseOnContext pContext) {         if (!pContext.getLevel().isClientSide() && pContext.getHand() == InteractionHand.MAIN_HAND) {             BlockPos blockPos = pContext.getClickedPos();             BlockPos secondBlockPos = getMultiblockPos(blockPos, pContext.getLevel().getBlockState(blockPos));             if (secondBlockPos != null) {                 createFrozenBlock(pContext, secondBlockPos);             }             createFrozenBlock(pContext, blockPos);             return InteractionResult.SUCCESS;         }         return super.useOn(pContext);     }     public static void createFrozenBlock(UseOnContext pContext, BlockPos blockPos) {         BlockState oldState = pContext.getLevel().getBlockState(blockPos);         BlockEntity oldBlockEntity = oldState.hasBlockEntity() ? pContext.getLevel().getBlockEntity(blockPos) : null;         CompoundTag oldBlockEntityData = oldState.hasBlockEntity() ? oldBlockEntity.serializeNBT() : null;         if (oldBlockEntity != null) {             pContext.getLevel().removeBlockEntity(blockPos);         }         BlockState FrozenBlock = setFrozenBlock(oldState, oldBlockEntity, oldBlockEntityData);         pContext.getLevel().setBlockAndUpdate(blockPos, FrozenBlock);     }     public static BlockState setFrozenBlock(BlockState blockState, @Nullable BlockEntity blockEntity, @Nullable CompoundTag blockEntityData) {         BlockState FrozenBlock = BlockRegister.FROZEN_BLOCK.get().defaultBlockState();         ((FrozenBlock) FrozenBlock.getBlock()).setOldBlockFields(blockState, blockEntity, blockEntityData);         return FrozenBlock;     }  
  • Topics

×
×
  • Create New...

Important Information

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