Луч с неба

Версия Minecraft
1.12.2
API
Forge

sk9zist :l

Исправился
981
18
157
Как сделать красный луч, который ведет от одного блока к другому с помощью GlStateManager ?
 
7,099
324
1,510

sk9zist :l

Исправился
981
18
157
Спасибо, попробую. Кстати, translateToZeroCoord полезный метод, я возможно тоже буду его использовать
 

sk9zist :l

Исправился
981
18
157
@hohserg Извиняюсь, а что за переменная entity.curve?
TestItem.java:
public static void translateToZeroCoord(float partialTicks)
    {
        Entity player = Minecraft.getMinecraft().player;
        double x = player.lastTickPosX + (player.posX - player.lastTickPosX) * partialTicks;
        double y = player.lastTickPosY + (player.posY - player.lastTickPosY) * partialTicks;
        double z = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * partialTicks;
        GlStateManager.translate(-x, -y, -z);
    }
    
    private void drawLine(Vec3d first, Color color, BufferBuilder buffer)
    {
        buffer.pos(first.x, first.y, first.z).color(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()).endVertex();
    }
    
    private void drawPolyChain(List<Vec3d> path, Color color)
    {
        Tessellator tessellator = Tessellator.getInstance();
        BufferBuilder buffer = tessellator.getBuffer();
        buffer.begin(3, DefaultVertexFormats.POSITION_COLOR);

        for (Vec3d vec3d : path)
            drawLine(vec3d, color, buffer);

        tessellator.draw();
    }
    
    private List<Vec3d> makePath(World worldIn, Vec3d startPos, BlockPos targetPos)
    {
        Vec3d finalPos = new Vec3d(targetPos.getX() + 0.5, targetPos.getY() + 0.75, targetPos.getZ() + 0.5);

        List<Vec3d> r = new ArrayList<>();
        r.add(startPos);

        Vec3d aboveFrame = new Vec3d(targetPos.getX() + 0.5, targetPos.getY() + 3, targetPos.getZ() + 0.5);
        double height = aboveFrame.y - startPos.y;
        if (height > 1 && startPos.squareDistanceTo(finalPos) > 25) {
            Vector2d direction = new Vector2d(aboveFrame.x, aboveFrame.z);
            direction.sub(new Vector2d(startPos.x, startPos.z));
            direction.normalize();
            r.add(new Vec3d(
                    startPos.x + height * direction.x,
                    startPos.y + height,
                    startPos.z + height * direction.y
            ));
        }
        r.add(aboveFrame);

        r.add(finalPos);
        return r;
    }
    
    public static Function<Double, Vec3d> bezierCurve(List<Vec3d> path)
    {
        Vec3d first = path.get(0);
        Vec3d last = path.get(path.size() - 1);
        float angle = (float) Math.atan2(last.x - first.x, last.z - first.z);

        List<Vec3d> rotatedPath = path.stream().map(v -> v.rotateYaw(-angle)).collect(Collectors.toList());

        return t -> {
            double z = 0;
            double y = 0;

            int n = rotatedPath.size() - 1;

            Vec3d vec = rotatedPath.get(0);
            double pow_1_minus_t_n = Math.pow((1 - t), n);
            z += vec.z * pow_1_minus_t_n;
            y += vec.y * pow_1_minus_t_n;

            double factorial_n = factorial(n);

            for (int index = 1; index < rotatedPath.size(); index++) {
                Vec3d item = rotatedPath.get(index);
                z += factorial_n / factorial(index) / factorial(n - index) * item.z * Math.pow((1 - t), n - index) * Math.pow(t, index);
                y += factorial_n / factorial(index) / factorial(n - index) * item.y * Math.pow((1 - t), n - index) * Math.pow(t, index);
            }
            return new Vec3d(vec.x, y, z).rotateYaw(angle);
        };
    }
    
    private static Int2IntMap factorialCache = new Int2IntOpenHashMap();
    
    private static double factorial(int num)
    {
        return factorialCache.computeIfAbsent(num, num1 -> factorial(num1, 1));
    }
    
    private static int factorial(int num, int acc)
    {
        if (num <= 1) {
            return acc;
        } else {
            return factorial(num - 1, acc * num);
        }
    }
    
    @Override
    public void onUpdate(ItemStack stack, World worldIn, Entity entity, int itemSlot, boolean isSelected)
    {
        if(entity instanceof EntityPlayer)
        {
            GlStateManager.pushMatrix();
            translateToZeroCoord(Minecraft.getMinecraft().getRenderPartialTicks());
            GlStateManager.disableLighting();
            GlStateManager.depthMask(false);
            GlStateManager.glLineWidth(2.0F);
            GlStateManager.disableTexture2D();

            List<Vec3d> path = makePath(worldIn, entity.getPositionVector(), entity.getPosition().east(50));
            
            drawPolyChain(path, Color.green);
            drawPolyChain(IntStream.range(0, 100).mapToDouble(i -> ((double) i) / 100).mapToObj(entity.curve::apply).collect(Collectors.toList()), Color.red);

            GlStateManager.enableLighting();
            GlStateManager.depthMask(true);
            GlStateManager.enableTexture2D();
            GlStateManager.popMatrix();
        }
    }
    
    @Override
    public ActionResult<ItemStack> onItemRightClick(World worldIn, EntityPlayer playerIn, EnumHand handIn)
    {
        
        
        return new ActionResult<ItemStack>(EnumActionResult.PASS, playerIn.getHeldItem(handIn));
    }
 
7,099
324
1,510
Это только для безье. Если прямые линии - просто забей на это
 

sk9zist :l

Исправился
981
18
157
Я уже перенес в RenderWorldLastEvent и сделал проверку глобальную переменную, которую я создал для этого предмета (так как он чисто клиентский, +луч все равно на клиенте)
 

sk9zist :l

Исправился
981
18
157
@hohserg ну, как-бэ)
2021-07-10_18.01.01.png
(Линия приходит куда надо, т.e. на 10 блоков от меня на восток как я и задал. Но почему-то она какая-то кривая)

RenderHelper.java:
public class RenderHelper
{
    public static Function<Double, Vec3d> curve;
    public static List<Vec3d> path;
    
    public static void debugDrawing(Entity entity, float partialTicks, World world)
    {
        GlStateManager.pushMatrix();
        translateToZeroCoord(Minecraft.getMinecraft().getRenderPartialTicks());
        GlStateManager.disableLighting();
        GlStateManager.depthMask(false);
        GlStateManager.glLineWidth(2.0F);
        GlStateManager.disableTexture2D();

        path = makePath(world, entity.getPositionVector(), entity.getPosition().east(10));
        
        drawPolyChain(path, Color.green);

        GlStateManager.enableLighting();
        GlStateManager.depthMask(true);
        GlStateManager.enableTexture2D();
        GlStateManager.popMatrix();
    }
    
    public static void translateToZeroCoord(float partialTicks)
    {
        Entity player = Minecraft.getMinecraft().player;
        double x = player.lastTickPosX + (player.posX - player.lastTickPosX) * partialTicks;
        double y = player.lastTickPosY + (player.posY - player.lastTickPosY) * partialTicks;
        double z = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * partialTicks;
        GlStateManager.translate(-x, -y, -z);
    }
    
    public static void drawLine(Vec3d first, Color color, BufferBuilder buffer)
    {
        buffer.pos(first.x, first.y, first.z).color(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()).endVertex();
    }
    
    public static void drawPolyChain(List<Vec3d> path, Color color)
    {
        Tessellator tessellator = Tessellator.getInstance();
        BufferBuilder buffer = tessellator.getBuffer();
        buffer.begin(3, DefaultVertexFormats.POSITION_COLOR);

        for (Vec3d vec3d : path)
            drawLine(vec3d, color, buffer);

        tessellator.draw();
    }
    
    public static List<Vec3d> makePath(World worldIn, Vec3d startPos, BlockPos targetPos)
    {
        Vec3d finalPos = new Vec3d(targetPos.getX() + 0.5, targetPos.getY() + 0.75, targetPos.getZ() + 0.5);

        List<Vec3d> r = new ArrayList<>();
        r.add(startPos);

        Vec3d aboveFrame = new Vec3d(targetPos.getX() + 0.5, targetPos.getY() + 3, targetPos.getZ() + 0.5);
        double height = aboveFrame.y - startPos.y;
        if (height > 1 && startPos.squareDistanceTo(finalPos) > 25) {
            Vector2d direction = new Vector2d(aboveFrame.x, aboveFrame.z);
            direction.sub(new Vector2d(startPos.x, startPos.z));
            direction.normalize();
            r.add(new Vec3d(
                    startPos.x + height * direction.x,
                    startPos.y + height,
                    startPos.z + height * direction.y
            ));
        }
        r.add(aboveFrame);

        r.add(finalPos);
        return r;
    }
    
    public static Function<Double, Vec3d> bezierCurve(List<Vec3d> path)
    {
        Vec3d first = path.get(0);
        Vec3d last = path.get(path.size() - 1);
        float angle = (float) Math.atan2(last.x - first.x, last.z - first.z);

        List<Vec3d> rotatedPath = path.stream().map(v -> v.rotateYaw(-angle)).collect(Collectors.toList());

        return t -> {
            double z = 0;
            double y = 0;

            int n = rotatedPath.size() - 1;

            Vec3d vec = rotatedPath.get(0);
            double pow_1_minus_t_n = Math.pow((1 - t), n);
            z += vec.z * pow_1_minus_t_n;
            y += vec.y * pow_1_minus_t_n;

            double factorial_n = factorial(n);

            for (int index = 1; index < rotatedPath.size(); index++) {
                Vec3d item = rotatedPath.get(index);
                z += factorial_n / factorial(index) / factorial(n - index) * item.z * Math.pow((1 - t), n - index) * Math.pow(t, index);
                y += factorial_n / factorial(index) / factorial(n - index) * item.y * Math.pow((1 - t), n - index) * Math.pow(t, index);
            }
            return new Vec3d(vec.x, y, z).rotateYaw(angle);
        };
    }
    
    public static Int2IntMap factorialCache = new Int2IntOpenHashMap();
    
    public static double factorial(int num)
    {
        return factorialCache.computeIfAbsent(num, num1 -> factorial(num1, 1));
    }
    
    public static int factorial(int num, int acc)
    {
        if (num <= 1) {
            return acc;
        } else {
            return factorial(num - 1, acc * num);
        }
    }
}
EventsHandler.java:
@SubscribeEvent
public void onUpdate(RenderWorldLastEvent e)
{
    RenderHelper.debugDrawing(Minecraft.getMinecraft().player, e.getPartialTicks(), Minecraft.getMinecraft().world);
}
Да, я пропустил часть с безье. Просто у меня ошибка на этой строчке curve::apply
Java:
drawPolyChain(IntStream.range(0, 100).mapToDouble(i -> ((double) i) / 100).mapToObj(curve::apply).collect(Collectors.toList()), Color.red);
 

sk9zist :l

Исправился
981
18
157
Сделал как мне надо исходя из своих базовых знаний OpenGL:
EventsHandler.java:
@SubscribeEvent
public void onUpdate(RenderWorldLastEvent e)
{
    float x = -231;
    float y = 4;
    float z = 218;
       
    GlStateManager.pushMatrix();
    RenderHelper.translateToZeroCoord(Minecraft.getMinecraft().getRenderPartialTicks());
    GlStateManager.disableLighting();
    GlStateManager.depthMask(false);
    GlStateManager.glLineWidth(2.0F);
    GlStateManager.disableTexture2D();
       
    GlStateManager.glBegin(GL11.GL_LINES);
    GlStateManager.color(255, 0, 0);
    GlStateManager.glVertex3f((float) Minecraft.getMinecraft().player.posX, (float) Minecraft.getMinecraft().player.posY + 1, (float) Minecraft.getMinecraft().player.posZ);
    GlStateManager.glVertex3f((float) (x + 0.5), (float) (y + 0.5), (float) (z + 0.5));
    GlStateManager.glEnd();

    GlStateManager.enableLighting();
    GlStateManager.depthMask(true);
    GlStateManager.enableTexture2D();
    GlStateManager.popMatrix();
}
2021-07-10_18.44.06.png2021-07-10_18.44.13.png
Но луч дёргается при движении, на скрине не видно но есть жесткие подёргивания. Как это исправить?
 
7,099
324
1,510
дёргается при движении
Про partialTicks не забывай
GlStateManager.glVertex3f((float) Minecraft.getMinecraft().player.posX, (float) Minecraft.getMinecraft().player.posY + 1, (float) Minecraft.getMinecraft().player.posZ);
posX/Y/Z у игрока - это с точностью до тика. Посмотри, как в translateToZeroCoord вычисляется позиция игрока с учетом partialTicks

Но почему-то она какая-то кривая)
Потому что надо не тупо копипастить все, а взять только то, что нужно для твоей задачи. У мя там кривые безье рисовались.
 

sk9zist :l

Исправился
981
18
157
Спасибо-с) Теперь всё гладко.
Заменил получение getPartialTicks из эвента и сделал как ты сказал. Вот готовый код кому будет нужно:
Java:
@SubscribeEvent
    public void onUpdate(RenderWorldLastEvent e)
    {
        float x = -231;
        float y = 4;
        float z = 218;
       
        GlStateManager.pushMatrix();
        RenderHelper.translateToZeroCoord(e.getPartialTicks());
        GlStateManager.disableLighting();
        GlStateManager.depthMask(false);
        GlStateManager.glLineWidth(2.0F);
        GlStateManager.disableTexture2D();
       
        GlStateManager.glBegin(GL11.GL_LINES);
        GlStateManager.color(255, 0, 0);
        GlStateManager.glVertex3f((float) (Minecraft.getMinecraft().player.lastTickPosX + (Minecraft.getMinecraft().player.posX - Minecraft.getMinecraft().player.lastTickPosX) * e.getPartialTicks()),
                                  (float) (Minecraft.getMinecraft().player.lastTickPosY + (Minecraft.getMinecraft().player.posY - Minecraft.getMinecraft().player.lastTickPosY) * e.getPartialTicks()),
                                  (float) (Minecraft.getMinecraft().player.lastTickPosZ + (Minecraft.getMinecraft().player.posZ - Minecraft.getMinecraft().player.lastTickPosZ) * e.getPartialTicks()));
        GlStateManager.glVertex3f((float) (x + 0.5), (float) (y + 0.5), (float) (z + 0.5));
        GlStateManager.glEnd();

        GlStateManager.enableLighting();
        GlStateManager.depthMask(true);
        GlStateManager.enableTexture2D();
        GlStateManager.popMatrix();
    }
Тебе заслуженный - Лучший ответ.
 
Сверху