Jump to content

Problems with rendering a line (1.15.2)


thebear

Recommended Posts

Hi, im fairly new to forge modding, so please forgive for asking such a stupid question.

Now for my problem. Im trying to draw a line between two positions. Drawing the line works, but when I change pitch or yaw, the line doesn't adjust, it just stays in the same position on screen.

I want it to adjust it's position,  just like a normal block would.

 

What happens: https://imgur.com/EwpOGuo

 

What I tried:

 

Main class:

@Mod("path")
public class path
{
    public path() {
        FMLJavaModLoadingContext.get().getModEventBus().addListener(this::setup);
    }

    private void setup(final FMLCommonSetupEvent event) {
        MinecraftForge.EVENT_BUS.register(new PathRenderer());
    }
}

 

Renderer:

public class PathRenderer {

    private Minecraft mc;

    public PathRenderer() {
        mc = Minecraft.getInstance();
    }

    @SubscribeEvent
    public void render(RenderWorldLastEvent event){

        double x = mc.player.getPositionVec().x;
        double y = mc.player.getPositionVec().y;
        double z = mc.player.getPositionVec().z;

        Vec3d p1 = new Vec3d(0, 57, 0);
        Vec3d p2 = new Vec3d(5, 57, 0);

        GL11.glPushMatrix();
        GL11.glTranslated(-x, -y, -z);
        GL11.glLineWidth(6.0f);
        GL11.glColor3ub((byte)255,(byte)0,(byte)0);
        GL11.glBegin(GL11.GL_LINES);
        GL11.glVertex3d(p1.x, p1.y, p1.z);
        GL11.glVertex3d(p2.x, p2.y, p2.z);
        GL11.glEnd();
        GL11.glPopMatrix();
    }
}

 

Edited by thebear
  • Like 1
Link to comment
Share on other sites

1 hour ago, thebear said:

Hi, im fairly new to forge modding, so please forgive for asking such a stupid question.

Now for my problem. Im trying to draw a line between two positions. Drawing the line works, but when I change pitch or yaw, the line doesn't adjust, it just stays in the same position on screen.

I want it to adjust it's position,  just like a normal block would.

 

https://imgur.com/EwpOGuo

 

What I tried:

 

Main class:


@Mod("path")
public class path
{
    public path() {
        FMLJavaModLoadingContext.get().getModEventBus().addListener(this::setup);
    }

    private void setup(final FMLCommonSetupEvent event) {
        MinecraftForge.EVENT_BUS.register(new PathRenderer());
    }
}

 

Renderer:


public class PathRenderer {

    private Minecraft mc;

    public PathRenderer() {
        mc = Minecraft.getInstance();
    }

    @SubscribeEvent
    public void render(RenderWorldLastEvent event){

        double x = mc.player.getPositionVec().x;
        double y = mc.player.getPositionVec().y;
        double z = mc.player.getPositionVec().z;

        Vec3d p1 = new Vec3d(0, 57, 0);
        Vec3d p2 = new Vec3d(5, 57, 0);

        GL11.glPushMatrix();
        GL11.glTranslated(-x, -y, -z);
        GL11.glLineWidth(6.0f);
        GL11.glColor3ub((byte)255,(byte)0,(byte)0);
        GL11.glBegin(GL11.GL_LINES);
        GL11.glVertex3d(p1.x, p1.y, p1.z);
        GL11.glVertex3d(p2.x, p2.y, p2.z);
        GL11.glEnd();
        GL11.glPopMatrix();
    }
}

 

I really not know GL11 and Java Vectors3, but i would say you that try to get the Position of a Block, then transform it into a 2D Vector, also try to get the Position on the screen (for example: if the position of your Block is (0,0,0), and your Camera perfect loo the Block, then it Position on the Screen should be: Vector2.new(Screen.X/2, Screen.Y/2)). Make the same with the other Block and use a function to write your line. I am more familiar with Lua, and in a Lua engine here was a function that was called „FindPositionOnScreen“, hope it was the same as in java, else try to write your own FindPositionOnScreen.

New in Modding? == Still learning!

Link to comment
Share on other sites

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

Hi

 

yes a lot has changed.  In particular, the code no longer uses the OpenGL transformation matrices, it keeps track of its own in a MatrixStack.  So you need to supply the MatrixStack to the rendering method.

 

Check out this link 

https://gist.github.com/williewillus/30d7e3f775fe93c503bddf054ef3f93e

 

And this example code (from a Tile Entity Renderer, but you should be able to adapt it.)

https://github.com/TheGreyGhost/MinecraftByExample/tree/master - see mbe21 class RenderLines or class DebugBlockVoxelShapeHighlighter

 

 

package minecraftbyexample.mbe21_tileentityrenderer;

import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.vertex.IVertexBuilder;
import minecraftbyexample.usefultools.RenderTypeHelper;
import net.minecraft.client.renderer.*;
import net.minecraft.util.math.Vec3d;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.awt.*;

/**
 * User: The Grey Ghost
 * Date: 12/01/2015
 * This class shows examples of rendering using lines.
 * The lines have position and colour information only  (RenderType.getLines()).  No lightmap information, which means that
 *   they will always be the same brightness regardless of day/night or nearby torches.
 */
public class RenderLines  {

  public static void renderWireframe(TileEntityMBE21 tileEntityMBE21, float partialTicks, MatrixStack matrixStack, IRenderTypeBuffer renderBuffers,
                               int combinedLight, int combinedOverlay) {
    // draw the artifact using lines
    // (Draws an inverted tetrahedron wireframe above the rendered base block (hopper block model))
    // When the TER::render method is called, the origin [0,0,0] is at the current [x,y,z] of the block being rendered.
    // The tetrahedron-drawing method draws the tetrahedron in a cube region from [0,0,0] to [1,1,1] but we want it
    //   to be in the block one above this, i.e. from [0,1,0] to [1,2,1],
    //   so we need to translate up by one block, i.e. by [0,1,0]
    final Vec3d TRANSLATION_OFFSET = new Vec3d(0, 1, 0);

    matrixStack.push(); // push the current transformation matrix + normals matrix
    matrixStack.translate(TRANSLATION_OFFSET.x,TRANSLATION_OFFSET.y,TRANSLATION_OFFSET.z); // translate
    Color artifactColour = tileEntityMBE21.getArtifactColour();

    drawTetrahedronWireframe(matrixStack, renderBuffers, artifactColour);
    matrixStack.pop(); // restore the original transformation matrix + normals matrix
  }

  /**
   * Draw an upside-down wireframe tetrahedron with its tip at [0.5,0,0.5]
   *    and 1x1 square "base" at y = 1 (x= 0 to 1, z = 0 to 1)
   * @param matrixStack transformation matrix and normal matrix
   * @param renderBuffers the renderbuffers we'll be drawing to
   */
  private static void drawTetrahedronWireframe(MatrixStack matrixStack, IRenderTypeBuffer renderBuffers,
                                               Color color) {

      final Vec3d [] BASE_VERTICES = {
              new Vec3d(0, 1, 0),
              new Vec3d(1, 1, 0),
              new Vec3d(1, 1, 1),
              new Vec3d(0, 1, 1),
      };
      final Vec3d APEX_VERTEX = new Vec3d(0.5, 0, 0.5);

    IVertexBuilder vertexBuilderLines = renderBuffers.getBuffer(RenderTypeHelper.MBE_LINE_DEPTH_WRITING_ON);
    // Note that, although RenderType.getLines() might appear to be suitable, it leads to weird rendering if used in
    // tile entity rendering, because it doesn't write to the depth buffer.  In other words, any object in the scene
    // which is drawn after the lines, will render over the top of the line (erase it) even if the object is behind
    //  the lines.  This means that RenderType.getLines() is only suitable for lines which are the last thing drawn in
    //  the scene (such as DrawBlockHighlightEvent)
    // The solution I used here is a custom RenderType for lines which does write to the depth buffer.

    Matrix4f matrixPos = matrixStack.getLast().getMatrix();  //retrieves the current transformation matrix
    // draw the base
    for (int i = 1; i < BASE_VERTICES.length; ++i) {
      drawLine(matrixPos, vertexBuilderLines, color, BASE_VERTICES[i-1], BASE_VERTICES[i]);
    }
    drawLine(matrixPos, vertexBuilderLines, color, BASE_VERTICES[BASE_VERTICES.length - 1], BASE_VERTICES[0]);

    // draw the sides (from the corners of the base to the apex)
    for (Vec3d baseVertex : BASE_VERTICES) {
      drawLine(matrixPos, vertexBuilderLines, color, APEX_VERTEX, baseVertex);
    }
  }

  /**
   * Draw a coloured line from a starting vertex to an end vertex
   * @param matrixPos the current transformation matrix
   * @param renderBuffer the vertex builder used to draw the line
   * @param startVertex
   * @param endVertex
   */
  private static void drawLine(Matrix4f matrixPos, IVertexBuilder renderBuffer,
                               Color color,
                               Vec3d startVertex, Vec3d endVertex) {
    renderBuffer.pos(matrixPos, (float) startVertex.getX(), (float) startVertex.getY(), (float) startVertex.getZ())
            .color(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha())   // there is also a version for floats (0 -> 1)
            .endVertex();
    renderBuffer.pos(matrixPos, (float) endVertex.getX(), (float) endVertex.getY(), (float) endVertex.getZ())
            .color(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha())   // there is also a version for floats (0 -> 1)
            .endVertex();
  }
}

or this one, from the HighlightBlock event

package minecraftbyexample.usefultools.debugging;

import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.vertex.IVertexBuilder;
import minecraftbyexample.usefultools.RenderTypeMBE;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.*;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.world.World;
import net.minecraftforge.client.event.DrawHighlightEvent;
import net.minecraftforge.client.event.RenderTooltipEvent;
import net.minecraftforge.event.entity.living.LivingSpawnEvent;
import net.minecraftforge.eventbus.api.Event;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.ObfuscationReflectionHelper;

import java.awt.*;
import java.lang.reflect.Field;

import static minecraftbyexample.usefultools.debugging.DebugSettings.getDebugParameter;

/**
 * Created by TGG on 27/06/2019.
 */
public class DebugBlockVoxelShapeHighlighter {
  @SubscribeEvent
  public static void onDrawBlockHighlightEvent(DrawHighlightEvent.HighlightBlock event) {
    RayTraceResult rayTraceResult = event.getTarget();
    if (rayTraceResult.getType() != RayTraceResult.Type.BLOCK) return;
    World world;

    try {
      world = getPrivateWorldFromWorldRenderer(event.getContext());
    } catch (IllegalAccessException e) {
      return;
    }

    BlockPos blockpos = ((BlockRayTraceResult) rayTraceResult).getPos();
    BlockState blockstate = world.getBlockState(blockpos);
    if (blockstate.isAir(world, blockpos) || !world.getWorldBorder().contains(blockpos)) return;

    final Color SHAPE_COLOR = Color.RED;
    final Color RENDERSHAPE_COLOR = Color.BLUE;
    final Color COLLISIONSHAPE_COLOR = Color.GREEN;
    final Color RAYTRACESHAPE_COLOR = Color.MAGENTA;

    boolean showshape = DebugSettings.getDebugParameter("showshape").isPresent();
    boolean showrendershapeshape = DebugSettings.getDebugParameter("showrendershape").isPresent();
    boolean showcollisionshape = DebugSettings.getDebugParameter("showcollisionshape").isPresent();
    boolean showraytraceshape = DebugSettings.getDebugParameter("showraytraceshape").isPresent();

    if (!(showshape || showrendershapeshape || showcollisionshape || showraytraceshape)) return;

    ActiveRenderInfo activeRenderInfo = event.getInfo();
    ISelectionContext iSelectionContext = ISelectionContext.forEntity(activeRenderInfo.getRenderViewEntity());
    IRenderTypeBuffer renderTypeBuffers = event.getBuffers();
    MatrixStack matrixStack = event.getMatrix();
    if (showshape) {
      VoxelShape shape = blockstate.getShape(world, blockpos, iSelectionContext);
      drawSelectionBox(event.getContext(), renderTypeBuffers, matrixStack, blockpos, activeRenderInfo, shape, SHAPE_COLOR);
    }
    if (showrendershapeshape) {
      VoxelShape shape = blockstate.getRenderShape(world, blockpos);
      drawSelectionBox(event.getContext(), renderTypeBuffers, matrixStack, blockpos, activeRenderInfo, shape, RENDERSHAPE_COLOR);
    }
    if (showcollisionshape) {
      VoxelShape shape = blockstate.getCollisionShape(world, blockpos, iSelectionContext);
      drawSelectionBox(event.getContext(), renderTypeBuffers, matrixStack, blockpos, activeRenderInfo, shape, COLLISIONSHAPE_COLOR);
    }
    if (showraytraceshape) {
      VoxelShape shape = blockstate.getRaytraceShape(world, blockpos);
      drawSelectionBox(event.getContext(), renderTypeBuffers, matrixStack, blockpos, activeRenderInfo, shape, RAYTRACESHAPE_COLOR);
    }
    event.setCanceled(true);
  }

  private static World getPrivateWorldFromWorldRenderer(WorldRenderer worldRenderer) throws IllegalAccessException {
    if (worldField == null) {
      worldField = ObfuscationReflectionHelper.findField(WorldRenderer.class, "world");
    }
    return (World)worldField.get(worldRenderer);
  }

  private static Field worldField;

  /**
   * copied from WorldRenderer; starting from the code marked with iprofiler.endStartSection("outline");
   *
   * @param activeRenderInfo
   */
  private static void drawSelectionBox(WorldRenderer worldRenderer, IRenderTypeBuffer renderTypeBuffers, MatrixStack matrixStack,
                                      BlockPos blockPos, ActiveRenderInfo activeRenderInfo, VoxelShape shape, Color color) {
    RenderType renderType = RenderTypeMBE.LINES();
    IVertexBuilder vertexBuilder = renderTypeBuffers.getBuffer(renderType);

    double eyeX = activeRenderInfo.getProjectedView().getX();
    double eyeY = activeRenderInfo.getProjectedView().getY();
    double eyeZ = activeRenderInfo.getProjectedView().getZ();
    final float ALPHA = 0.5f;
    drawShapeOutline(matrixStack, vertexBuilder, shape,
            blockPos.getX() - eyeX, blockPos.getY() - eyeY, blockPos.getZ() - eyeZ,
            color.getRed() / 255f, color.getGreen() / 255f, color.getBlue() / 255f, ALPHA);

  }

  private static void drawShapeOutline(MatrixStack matrixStack,
                                       IVertexBuilder vertexBuilder,
                                       VoxelShape voxelShape,
                                       double originX, double originY, double originZ,
                                       float red, float green, float blue, float alpha) {

    Matrix4f matrix4f = matrixStack.getLast().getMatrix();
    voxelShape.forEachEdge((x0, y0, z0, x1, y1, z1) -> {
      vertexBuilder.pos(matrix4f, (float)(x0 + originX), (float)(y0 + originY), (float)(z0 + originZ)).color(red, green, blue, alpha).endVertex();
      vertexBuilder.pos(matrix4f, (float)(x1 + originX), (float)(y1 + originY), (float)(z1 + originZ)).color(red, green, blue, alpha).endVertex();
    });
  }

}

 

 

Cheers

  TGG

 

Edited by TheGreyGhost
  • Like 1
  • Thanks 1
Link to comment
Share on other sites

Thanks for your reply! Finally got it working correctly!

 

new code:

public class PathRenderer {

    private Minecraft mc;

    public PathRenderer() {
        mc = Minecraft.getInstance();
    }

    @SubscribeEvent
    public void render(RenderWorldLastEvent event){
        Tessellator tessellator = Tessellator.getInstance();
        BufferBuilder buffer = tessellator.getBuffer();
        MatrixStack matrixStack = event.getMatrixStack();
        Vec3d pos = mc.player.getPositionVec();

        matrixStack.push();
        matrixStack.translate(-pos.x, -pos.y, -pos.z);
        RenderSystem.color3f(1, 0, 0);
        RenderSystem.lineWidth(6);
        buffer.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION);

        Matrix4f matrix = matrixStack.getLast().getMatrix();
        Color c = new Color(1f, 0f, 0f, 1f);

        drawLine(matrix, buffer, new Vec3d(0, 57, 0), new Vec3d(5, 57, 0));

        tessellator.draw();
        matrixStack.pop();
    }

    private void drawLine(Matrix4f matrix, BufferBuilder buffer, Vec3d p1, Vec3d p2) {
        buffer.pos(matrix, (float)p1.x + 0.5f, (float)p1.y + 0.5f, (float)p1.z + 0.5f).endVertex();
        buffer.pos(matrix, (float)p2.x + 0.5f, (float)p2.y + 0.5f, (float)p2.z + 0.5f).endVertex();
    }
}

 

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

Actually it didn't quite work in the nether, but now it does.

The reason I am posting this is, that if someone has the same problem in the future, they will find this.

I searched for this on google for a good hour, but didn't find anything.

 

New code:

 

@SubscribeEvent
    public void render(RenderWorldLastEvent event) {
        IRenderTypeBuffer.Impl buffer = Minecraft.getInstance().getRenderTypeBuffers().getBufferSource();
        IVertexBuilder builder = buffer.getBuffer(RenderType.LINES);
        MatrixStack matrixStack = event.getMatrixStack();

        PlayerEntity player = Minecraft.getInstance().player;
        double x = player.lastTickPosX + (player.getPosX() - player.lastTickPosX) * event.getPartialTicks();
        double y = player.lastTickPosY + (player.getPosY() - player.lastTickPosY) * event.getPartialTicks();
        double z = player.lastTickPosZ + (player.getPosZ() - player.lastTickPosZ) * event.getPartialTicks();

        matrixStack.push();
        matrixStack.translate(-x, -y, -z);
        Matrix4f matrix = matrixStack.getLast().getMatrix();

        builder.pos(matrix, 0, 0, 0).color(1f, 0, 0, 1f).endVertex();
        builder.pos(matrix, 0, 256, 0).color(1f, 0, 0, 1f).endVertex();

        matrixStack.pop();
        RenderSystem.disableDepthTest();
        buffer.finish(RenderType.LINES);
    }

 

  • Thanks 2
Link to comment
Share on other sites

My modding workspace has just weird names like func_227860_a_() (which I think is the .push method you have) in the MatrixStack class. How did you get yours to have the right names?

 

I did some digging and found that my mappings version in my build.gradle is 20190719-1.14.3, which I assume is an old version. What is the latest version for 1.15.2?

Edited by _NIMJA
Link to comment
Share on other sites

I actually had the same problem in the beginning too. What I did was, I downloaded the latest version from the forge website.

Make sure you download "latest", not "recommended". In the latest version, the function names should be deobfuscated.

The version I used was 1.15.2-31.1.19. Im not sure why, the mapping for it is 20200225-1.15.1.

Hope it helps you!

  • Thanks 1
Link to comment
Share on other sites

Note that 1.15 mappings will probably not work on 1.14

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

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.