Jump to content

Recommended Posts

Posted (edited)

I'm wondering how I can render fixed lines between tile entities in a simular way to buildcraft markers or immersive engineering wires.

The actual rendering and render types i've figured out and I have it rendering from a single tile to a player mostly using mcjtys tutorial https://wiki.mcjty.eu/modding/index.php?title=Tut15_Ep15 for tile entity rendering.

the issue is that I essentially have a kind of linked list of a bunch of points that are all linked together using real world positions but to draw this on the clientside relative to the player seems incredibly difficult since the only event I can think of
is the client tick events and then I don't know how I would grab the matrix stack equivalent positions relative to the player from the actual positions within the world. I'm not sure if thats even possible.

 

The vast majority of the code is essentially very simular to mcjtys tutorial code with a few very minor edits so for a better reference: https://wiki.mcjty.eu/modding/index.php?title=Tut15_Ep15 for tile entity rendering.


Tile > player method (currently works)

static void drawTileToPlayer(TileEntity tile, ClientPlayerEntity player, MatrixStack matrixStack){
        IRenderTypeBuffer.Impl buffer = Minecraft.getInstance().getRenderTypeBuffers().getBufferSource();
        IVertexBuilder lineBuilder = buffer.getBuffer(CustomRenderTypes.THICK_LINES);

        BlockPos playerPos = player.getPosition();
        BlockPos tilePos = tile.getPos();
        int px = playerPos.getX();
        int py = playerPos.getY();
        int pz = playerPos.getZ();

        float[] lineColour = getLineColour(tile.getBlockState().getBlock());
        drawLine(lineBuilder, generateProjectedMatrix(matrixStack),tilePos.getX() + 0.5f,tilePos.getY() + 0.6f,tilePos.getZ() + 0.5f, px + 0.5f, py + 0.5f, pz + 0.5f, lineColour);

        matrixStack.pop();
        buffer.finish(CustomRenderTypes.THICK_LINES);
    }

This draws a line from the tile to the player position using a matrix stack from the renderworldlastevent event.

Generate projected matrix

private static Matrix4f generateProjectedMatrix(MatrixStack matrixStack){
        //  Begin pushing to the matrix stack.
        matrixStack.push();

        //  Get actual position of player and translate back to the actual location. E.g. blockpos is discrete integers. projected view isn't.
        Vec3d projectedView = Minecraft.getInstance().gameRenderer.getActiveRenderInfo().getProjectedView();
        matrixStack.translate(-projectedView.x, -projectedView.y, -projectedView.z);

        return matrixStack.getLast().getMatrix();
    }

 

Drawline method

private static void drawLine(IVertexBuilder builder, Matrix4f posMatrix, float x1, float y1, float z1, float x2, float y2, float z2, float[] colour){
        builder.pos(posMatrix, x1, y1, z1)
                .color(colour[0], colour[1], colour[2], colour[3])
                .endVertex();
        builder.pos(posMatrix, x2, y2, z2)
                .color(colour[0], colour[1], colour[2], colour[3])
                .endVertex();
    }


I did think of using blocks simular to string that would generate between the marker points as they are placed but unlike buildcraft i'm fixing where you can place the markers in the X & Z planes but not in the Y plane so that wont work.
 

Edited by profjb58
Posted

So i've managed to get it working (partially). I've attached an image of it.
Essentially it kinda works. It renders properly but say if another render event happens during when I place the markers down, this line gets broken. It also produces a random pattern when logging back in and out. This is acctually kinda cool and i'm guessing is because the render world last event is essentially pretty much random.

 

static void drawTileToTile(TileEntity tileStart, TileEntity tileEnd, ClientPlayerEntity player, MatrixStack matrixStack){
        IRenderTypeBuffer.Impl buffer = Minecraft.getInstance().getRenderTypeBuffers().getBufferSource();
        IVertexBuilder lineBuilder = buffer.getBuffer(CustomRenderTypes.THICK_LINES);
        
        BlockPos tileStartPos = tileStart.getPos();
        BlockPos tileEndPos = tileEnd.getPos();

        float[] lineColour = getLineColour(tileStart.getBlockState().getBlock());
        drawLine(lineBuilder, generateProjectedMatrix(matrixStack),tileStartPos.getX() + 0.5f,tileStartPos.getY() + 0.6f,tileStartPos.getZ() + 0.5f,
                tileEndPos.getX() + 0.5f, tileEndPos.getY() + 0.5f, tileEndPos.getZ() + 0.5f, lineColour);

        matrixStack.pop();
        buffer.finish(CustomRenderTypes.THICK_LINES);
    }

Modified code for drawing between tiles. I included

2020-07-06_23.57.25.jpg

2020-07-07_00.02.07.jpg

Posted

I also have all the positions I need for the next and previous tiles (markers) within the NBT storage of each marker so i'm wondering if using the TER approach would be better since I don't need the position of the player.

Posted

Howdy

I would suggest that you should use the TER to render your lines.

Since your TileEntity stores the position of the next marker, just draw a line to the next position (relative to the position of the TE being drawn, of course).  Very simple, very scaleable.  renderworldlastevent should be a last resort I think.

The only likely issue is that lines will disappear when the TE is unloaded (goes out of chunk range), which may become very noticeable if the markers are far apart from each other, i.e. you are close to one of the markers when the next marker goes off the edge of the chunk limit.

 

You could probably work around this by drawing to both the previous and the next markers; if necessary keeping track of which lines have already been drawn during that frame so that you don't draw the same line twice.

 

-TGG

 

 

  • Thanks 1
Posted (edited)

I had a quick go last night thinking that might be the best approach. I'm almost certain it's the only approach that would be scaleable now.
The idea of drawing 2 lines from either marker so either one is unlikely to stop rendering upon unloading a chunk is a brilliant idea, thank you. Since I have previous and next positions that is entirely possible for every marker as well.

The only problems i'm having now is the ability to update the rendering based upon the information of the connected tile entities (markers) updating. E.g. one being removed or added. I have the correct methods overrided and sending data, e.g. onDataPacket, getUpdatePacket. I think I might be missing something here. I'll send the code for it.
There is also a weird effect whereby once the player stops looking at the tile the connecting tiles lines dissapear. Thinking about it though drawing 2 lines between the markers would fix this I think.


gist link: https://gist.github.com/profjb58/3b7960e437386228c3f472bd05e49764
(A lot of code, didn't want to spam this thread)


I think i'm limiting the amount of data I sync to the client from what I can tell to only include

  • 'connectedFacing > direction the marker is pointing'
  • 'isTail' > is this marker the tail of the list.
  • prevMarker & nextMarker' *

* The only variables required for the TER. everything else used for drawing a line from the tail (end marker) to the player.


p.s. the gist code is a bit of a mess. It works but i'm sure there is a better way of laying it out.
 

Edited by profjb58
pastebin sucks
  • 2 weeks later...

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.