Jump to content

Recommended Posts

Posted

Hi

 

I never really got an actual answer on my last question, so I'm going to ask again:

 

I would like to render a TileEntity Special Render to render fluids in my bucket model:

2019-08-10_20_06_06_2.png.af7d00475cd07c766ffa8671df45947a.png

 

The problem is that I don't know how to "stitch" everything together, and the colour doesn't seem to change either. I realized instead of rendering a whole cuboid I could only render a square only visible from the top, which would reduce the number of vertexes to only four (4). I got something to render in-game, but I couldn't really find any way to have them render as I wanted:

2019-08-14_20_02.59_2.png.8c829cf95d25bc748695217088b99097.png

 

The idea was to make a visual illustration of how full the bucket is. So changing the y value of the square would give the effect of the bucket filling up.

 

bucket_render_example.png.7e69949b9261e7d1772674455dfe1e36.png

 

 

The class with the TESR Fast:

Spoiler

public class TreeTapTileEntityRenderer<T extends TreeTapTileEntity> extends TileEntityRendererFast<T>
{

    @Override
    public void renderTileEntityFast(T te, double x, double y, double z, float partialTicks, int destroyStage, BufferBuilder buffer)
    {

        BlockPos pos = te.getPos();

        net.minecraft.world.IEnviromentBlockReader world = MinecraftForgeClient.getRegionRenderCache(te.getWorld(), pos);
        BlockState state = world.getBlockState(pos);


        if (state.has(BlockProperties.BUCKET))
            if (state.get(BlockProperties.BUCKET) != BucketType.NONE && te.getVolume() > 0) {
                //buffer.setTranslation(x - pos.getX(), y - pos.getY(), z - pos.getZ());

                render(te,x,y,z,buffer,state, te.getFluidType());


            }


    }

    private void render(T te, double x, double y, double z, BufferBuilder buffer, BlockState state, FluidType type)
    {
        buffer.setTranslation(x,y,z);


        buffer.pos(0,0,0).color(0,0,1,1).endVertex();
        buffer.pos(4,0,0).color(0,0,1,1).endVertex();
        buffer.pos(0,0,4).color(0,0,1,1).endVertex();
        buffer.pos(4,0,4).color(0,0,1,1).endVertex();


    }

 

 

 

  • 2 weeks later...
Posted

Some more details:

I have found other pieces of code where a cuboid was rendered, but I feel like it would be a big waste to render all that when only a tiny part of the "fluid" is visible at any time. A square has four (4) vertices while a cuboid has twelve (12) vertices, so it's pretty obvious which one to chose.

Another problem I'm facing is that even the cluttered mess visible on the second image is still black, which is not at all what I'm expecting out of a blue liquid.

Posted

I think there's two things going on here.

 

First, you're not giving it a texture of what to render.  If you look at the pnc-repressurized example you linked, you'll note the TextureAtlasSprite still = Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite(f.getStill().toString()); code, along with the inclusion of .tex() in each of the buffer calls.  You'll want to include something quite similar.  (My suspicion is that this it the step that is needed to bring the rest together for you.)

 

The values you are providing to .color() may or may not need to be fiddled with, depending on the colour of your original texture. 

 

Second, the values you are passing to each buffer() call.  "1" is "one block", so the fours used are, well, four blocks.  To keep the fluid in your bucket, you'll want some fractions in there.

 

I wholly agree that you only need to render the 'top' of the fluid.

 

As an aside, this is in the context of 1.12.2 -- but I very much doubt it has changed any for 1.14.2.

Posted

On 8/26/2019 at 9:04 AM, Ommina said:

I think there's two things going on here.

 

First, you're not giving it a texture of what to render.  If you look at the pnc-repressurized example you linked, you'll note the TextureAtlasSprite still = Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite(f.getStill().toString()); code, along with the inclusion of .tex() in each of the buffer calls.  You'll want to include something quite similar.  (My suspicion is that this it the step that is needed to bring the rest together for you.)

 

The values you are providing to .color() may or may not need to be fiddled with, depending on the colour of your original texture. 

 

Second, the values you are passing to each buffer() call.  "1" is "one block", so the fours used are, well, four blocks.  To keep the fluid in your bucket, you'll want some fractions in there.

 

I wholly agree that you only need to render the 'top' of the fluid.

 

As an aside, this is in the context of 1.12.2 -- but I very much doubt it has changed any for 1.14.2.

 

Alright, I added this to the code, and you can see the result that happened:

 

TextureAtlasSprite sprite = Minecraft.getInstance().getTextureMap().getAtlasSprite("minecraft:water_still");
float u1 = sprite.getMinU(), v1 = sprite.getMinV(), u2 = sprite.getMaxU(), v2 = sprite.getMaxV();

buffer.pos(0,0,0).color(1,1,1,1).tex(u1, v2).endVertex();
buffer.pos(4,0,0).color(1,1,1,1).tex(u1, v2).endVertex();
buffer.pos(0,0,4).color(1,1,1,1).tex(u1, v2).endVertex();
buffer.pos(4,0,4).color(1,1,1,1).tex(u1, v2).endVertex();

 

Spoiler

treetap_test3.gif

 

 

Posted

When you see stuff rendering all over the place like that, the values bring provided to the .pos() function need to be prodded.

 

4 is too large.  Also, pay attention to the order.  It counts.

 

As an aside, when testing the renderer, start with just one instance of the TE in your test world.  It's a lot easier to see the effects of a change when you can be confident that you're not seeing overlap from nearby tiles. 

Posted
12 hours ago, Ommina said:

When you see stuff rendering all over the place like that, the values bring provided to the .pos() function need to be prodded.

 

4 is too large.  Also, pay attention to the order.  It counts.

 

As an aside, when testing the renderer, start with just one instance of the TE in your test world.  It's a lot easier to see the effects of a change when you can be confident that you're not seeing overlap from nearby tiles. 

Umm... ok, so I changed the 4 to 0.1:

buffer.pos(0,0,0).color(1,1,1,1).tex(u1, v2).endVertex();
buffer.pos(0,0,0).color(1,1,1,1).tex(u1, v2).endVertex();
buffer.pos(0.1,0,0).color(1,1,1,1).tex(u1, v2).endVertex();
buffer.pos(0.1,0,0).color(1,1,1,1).tex(u1, v2).endVertex();

 

But I can't seem to get them to all stick together, I tried a bunch of combinations but there are about 64 different combinations. What order were you thinking? None of the combinations I tried gave any hints on what order they should be in.

Posted

Hm.  Well, you want a horizontal plane, so I'd try something to the effect of:

 

buffer.pos(0.06, 0.5, 0.06).color(1,1,1,1).tex(u1, v1).endVertex();
buffer.pos(0.06, 0.5, 0.93).color(1,1,1,1).tex(u2, v1).endVertex();
buffer.pos(0.93, 0.5, 0.93).color(1,1,1,1).tex(u2, v2).endVertex();
buffer.pos(0.93, 0.5, 0.06).color(1,1,1,1).tex(u1, v2).endVertex();

 

and see if it explodes.

Posted
11 minutes ago, Ommina said:

Hm.  Well, you want a horizontal plane, so I'd try something to the effect of:

 


buffer.pos(0.06, 0.5, 0.06).color(1,1,1,1).tex(u1, v1).endVertex();
buffer.pos(0.06, 0.5, 0.93).color(1,1,1,1).tex(u2, v1).endVertex();
buffer.pos(0.93, 0.5, 0.93).color(1,1,1,1).tex(u2, v2).endVertex();
buffer.pos(0.93, 0.5, 0.06).color(1,1,1,1).tex(u1, v2).endVertex();

 

and see if it explodes.

2019-08-28_10_20_04.thumb.png.1945649d5e20b553141fe095f41bcd81.png

Posted

It feels like there should be a "stitch" function or something I've missed. Something I discovered just now is that the server crashes when I attach the renderer:

ClientRegistry.bindTileEntitySpecialRenderer(TreeTapTileEntity.class, new TreeTapTileEntityRenderer());

 

java.lang.RuntimeException: Attempted to load class net/minecraft/client/renderer/tileentity/TileEntityRenderer for invalid dist DEDICATED_SERVER

Posted
15 minutes ago, diesieben07 said:

Read the documentation on bindTileEntitySpecialRenderer as to when it must be called.

"In order to register a TESR, call ClientRegistry#bindTileEntitySpecialRenderer passing the tile entity class to be renderer with this TER and the instance of the TER to use to render all TEs of this class."

 

Pretty sure that's everything I'm doing:

 

Spoiler

public IntercraftCore()
{

  FMLJavaModLoadingContext.get().getModEventBus().addListener(this::onClientSetup);
  
}

public void onClientSetup(final FMLClientSetupEvent event)
{
    ClientRegistry.bindTileEntitySpecialRenderer(TreeTapTileEntity.class, new TreeTapTileEntityRenderer());
}

 

 

 

Posted

As for the rendering explosion, post the updated code and I'll give it a go locally.  I've got a block to port from 1.12 that has pretty much identical rendering, so I'll work on that and see where it leads.

Posted
7 hours ago, Ommina said:

As for the rendering explosion, post the updated code and I'll give it a go locally.  I've got a block to port from 1.12 that has pretty much identical rendering, so I'll work on that and see where it leads.

I have everything on Github, here is where the TileEntity and renderer is.

  • 2 months later...
Posted

So yeah, still not an answer to this, I'm not even close to having this work. What I finished doing though is the network message to change the values of the TileEntity for the client, so the renderer is what still remains. My code is pretty much the same and the idea too.

Posted (edited)

(I'm the author of the code in PneumaticCraft: Repressurized).

 

I think where you're going wrong here is order of quad definitions.  It looks like you're trying to render the top face of the block, right?  (And skipping the others because they aren't visible in your block).  So, looking at my code for EnumFacing.UP, the vertex order goes:

  • minX, maxZ
  • maxX, maxZ
  • maxX, minZ
  • minX, minZ

... which is not the order you're using.  The vertex order is vitally important, and should wind clockwise if you're looking at the face from the outside (e.g. for the UP face, when you're facing downward).  Get the order wrong and the quad will look screwy.  The same applies to the UV coordinates; they also have to wind in the same way.

 

Finally, you probably do need to light the quad; the PNC:R code shows you how (with the .lightmap() method).

Edited by desht
Posted
49 minutes ago, desht said:

(I'm the author of the code in PneumaticCraft: Repressurized).

 

I think where you're going wrong here is order of quad definitions.  It looks like you're trying to render the top face of the block, right?  (And skipping the others because they aren't visible in your block).  So, looking at my code for EnumFacing.UP, the vertex order goes:

  • minX, maxZ
  • maxX, maxZ
  • maxX, minZ
  • minX, minZ

... which is not the order you're using.  The vertex order is vitally important, and should wind clockwise if you're looking at the face from the outside (e.g. for the UP face, when you're facing downward).  Get the order wrong and the quad will look screwy.  The same applies to the UV coordinates; they also have to wind in the same way.

 

Finally, you probably do need to light the quad; the PNC:R code shows you how (with the .lightmap() method).

Ok, I changed the order of them now to this:

TextureAtlasSprite sprite = Minecraft.getInstance().getTextureMap().getAtlasSprite("minecraft:water_still");
float u1 = sprite.getMinU(), v1 = sprite.getMinV(), u2 = sprite.getMaxU(), v2 = sprite.getMaxV();


buffer.pos(0.06, 0.5, 0.93).color(1,1,1,te.fluidType.getAlpha()).tex(u1, v2).endVertex();
buffer.pos(0.93, 0.5, 0.93).color(1,1,1,te.fluidType.getAlpha()).tex(u2, v2).endVertex();
buffer.pos(0.93, 0.5, 0.06).color(1,1,1,te.fluidType.getAlpha()).tex(u2, v1).endVertex();
buffer.pos(0.06, 0.5, 0.06).color(1,1,1,te.fluidType.getAlpha()).tex(u1, v1).endVertex();

 

Not sure if this is the right order or if the other part in your code is important. The thing I do not understand about your code is the shouldRender function here:

...
if (tankRenderInfo.shouldRender(EnumFacing.UP)) { // <-- This part.
            int upCombined = getWorld().getCombinedLight(te.getPos().up(), 0);
            int upLMa = upCombined >> 16 & 65535;
            int upLMb = upCombined & 65535;
            buffer.pos(bounds.minX, bounds.maxY, bounds.maxZ).color(1.0f, 1.0f, 1.0f, FLUID_ALPHA).tex(u1, v2).lightmap(upLMa, upLMb).endVertex();
            buffer.pos(bounds.maxX, bounds.maxY, bounds.maxZ).color(1.0f, 1.0f, 1.0f, FLUID_ALPHA).tex(u2, v2).lightmap(upLMa, upLMb).endVertex();
            buffer.pos(bounds.maxX, bounds.maxY, bounds.minZ).color(1.0f, 1.0f, 1.0f, FLUID_ALPHA).tex(u2, v1).lightmap(upLMa, upLMb).endVertex();
            buffer.pos(bounds.minX, bounds.maxY, bounds.minZ).color(1.0f, 1.0f, 1.0f, FLUID_ALPHA).tex(u1, v1).lightmap(upLMa, upLMb).endVertex();
        }
...

 

The EnumFacing.UP is most likely the one I need as you mentioned, but I have no idea in what context. In your code, you use a class getTanksToRender with a function including a BitSet object, which I do not know is used for.

Posted

Ok, turns out the lightmap is pretty important:

2019-11-04_20_24_46.thumb.png.9c00b9a9542062caf8e990acf1a3b4e8.png

 

TextureAtlasSprite sprite = Minecraft.getInstance().getTextureMap().getAtlasSprite("minecraft:block/water_still");
float u1 = sprite.getMinU(), v1 = sprite.getMinV(), u2 = sprite.getMaxU(), v2 = sprite.getMaxV();

int upCombined = getWorld().getCombinedLight(te.getPos().up(), 0);
int upLMa = upCombined >> 16 & 65535;
int upLMb = upCombined & 65535;

float xMin = 0.06f,xMax = 0.93f,yLev = 0.125f,zMin = 0.06f,zMax = 0.93f;

buffer.pos(xMin, yLev, zMax).color(1,1,1,te.fluidType.getAlpha()).tex(u1, v2).lightmap(upLMa, upLMb).endVertex();
buffer.pos(xMax, yLev, zMax).color(1,1,1,te.fluidType.getAlpha()).tex(u2, v2).lightmap(upLMa, upLMb).endVertex();
buffer.pos(xMax, yLev, zMin).color(1,1,1,te.fluidType.getAlpha()).tex(u2, v1).lightmap(upLMa, upLMb).endVertex();
buffer.pos(xMin, yLev, zMin).color(1,1,1,te.fluidType.getAlpha()).tex(u1, v1).lightmap(upLMa, upLMb).endVertex();

 

Posted
16 hours ago, Simon_kungen said:

The EnumFacing.UP is most likely the one I need as you mentioned, but I have no idea in what context. In your code, you use a class getTanksToRender with a function including a BitSet object, which I do not know is used for

The TankRenderInfo class just tells the rendering code where the tanks are in the model and which faces of the fluid AABB to render.  That bitset is just a compact way of storing which of the 6 faces need to be rendered; the FastFluidTESR class is abstract and implemented by the renderers for various tile entities, each of which have differing rendering requirements (e.g. some only need to render the top face of the fluid, some need to render the sides too since the block model has transparent sides, and some have multiple tanks to render, like the Refinery with both an input and output tank).  You don't really need that extra code if you're only ever planning to render the top face of the fluid.

  • Thanks 1

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.