Jump to content
View in the app

A better way to browse. Learn more.

Forge Forums

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

Featured Replies

Posted

I'm working on a TileEntitySpecialRender for my robot. I'm wondering, since I have little experience with them in this version, how I should render my TileEntity? Would a Techne model be acceptable, or would I use a tessellator?

Yes, I'm pretty sure. The TileEntity would have a model where different parts rotate depending on which inventory around the TileEntity it is interacting with, if that makes sense. Code in an ItemStack (last topic) would tell it where to move/which inventory to interact with. I'm thinking this might be way more complex than a IBakedModel or something along those lines could provide.

Yes, it would have an animation.

Ok. Thanks. :)

Would I have to define something in a blockstate/model json file?

What format would the int array passed to VertexBuffer#addVertexData use?

Thank you. I now have this basic code for my renderer:

protected static BlockRendererDispatcher blockRenderer;

    @Override
    public void renderTileEntityFast(TileEntityRobot te, double x, double y, double z, float partialTicks, int destroyStage, VertexBuffer renderer) {
        if(blockRenderer == null) blockRenderer = Minecraft.getMinecraft().getBlockRendererDispatcher();
        BlockPos pos = te.getPos();
        IBlockAccess world = MinecraftForgeClient.getRegionRenderCache(te.getWorld(), pos);
        IBlockState state = world.getBlockState(pos);

        IBakedModel model = blockRenderer.getBlockModelShapes().getModelForState(state);

        renderer.setTranslation(x - pos.getX(), y - pos.getY(), z - pos.getZ());

        blockRenderer.getBlockModelRenderer().renderModel(world, model, state, pos, renderer, false);
    }

 

I have tested it by adding an offset to the translation (for testing), and it works. It renders the model I defined in my blockstate file. Now how would I add rotation/change the position of some of the parts of the model?

Does anyone know how I could do this?

 

PS: Kind of off-topic but these spammers are getting really annoying. So glad the moderators are working on getting it fixed. I translated one of their user names on google translate from Chinese and it meant "Make a Fortune". They are obviously gaining something from this.

Does anyone know how I could add rotation?

well you need to extract the posotion floats from the int[] you are passing an manualy change them with sin and cos

catch(Exception e)

{

 

}

Yay, Pokémon exception handling, gotta catch 'em all (and then do nothing with 'em).

Ok.

I know this is probably fairly easy to do, but I'm struggling a little bit. Which vertexes use cos and which use sin? I've taken trigonometry but this is way beyond me. All I want is a basic rotation on the x axis.

Thanks , I'll read that.

I don't completely understand matrices yet, as I am only in grade 12 math currently. I tried it and got this code in my Renderer:

    protected static BlockRendererDispatcher blockRenderer;

    @Override
    public void renderTileEntityFast(TileEntityRobot te, double x, double y, double z, float partialTicks, int destroyStage, VertexBuffer renderer) {
        if(blockRenderer == null) blockRenderer = Minecraft.getMinecraft().getBlockRendererDispatcher();
        BlockPos pos = te.getPos();
        IBlockAccess world = MinecraftForgeClient.getRegionRenderCache(te.getWorld(), pos);
        IBlockState state = world.getBlockState(pos);

        IBakedModel model = blockRenderer.getBlockModelShapes().getModelForState(state);

        renderer.setTranslation(x - pos.getX() + 2.0f, y - pos.getY(), z - pos.getZ() + 2.0f);

        BakedQuad bq = model.getQuads(state, null, 0L).get(0);

        int[] vertexData = handleXRotation(bq.getVertexData(), 45);

        model.getQuads(state, null, 0L).set(0, new BakedQuad(vertexData, bq.getTintIndex(), bq.getFace(), bq.getSprite(), bq.shouldApplyDiffuseLighting(), bq.getFormat()));

        blockRenderer.getBlockModelRenderer().renderModel(world, model, state, pos, renderer, false);
    }

    public int[] handleXRotation(int[] vertexData, double rot) {
        int vx = vertexData[0];
        int vy = vertexData[1];

        vx = (int)((vx * Math.cos(Math.toRadians(rot))) - (vy * Math.sin(Math.toRadians(rot))));
        vy = (int)((vx * Math.sin(Math.toRadians(rot))) + (vy * Math.cos(Math.toRadians(rot))));

        vertexData[0] = vx;
        vertexData[1] = vy;

        //Next Vertex
        vx = vertexData[8];
        vy = vertexData[9];

        vx = (int)((vx * Math.cos(Math.toRadians(rot))) - (vy * Math.sin(Math.toRadians(rot))));
        vy = (int)((vx * Math.sin(Math.toRadians(rot))) + (vy * Math.cos(Math.toRadians(rot))));

        vertexData[8] = vx;
        vertexData[9] = vy;

        //Next Vertex
        vx = vertexData[14];
        vy = vertexData[15];

        vx = (int)((vx * Math.cos(Math.toRadians(-rot))) - (vy * Math.sin(Math.toRadians(-rot))));
        vy = (int)((vx * Math.sin(Math.toRadians(-rot))) + (vy * Math.cos(Math.toRadians(-rot))));

        vertexData[14] = vx;
        vertexData[15] = vy;

        //Next Vertex
        vx = vertexData[20];
        vy = vertexData[21];

        vx = (int)((vx * Math.cos(Math.toRadians(-rot))) - (vy * Math.sin(Math.toRadians(-rot))));
        vy = (int)((vx * Math.sin(Math.toRadians(-rot))) + (vy * Math.cos(Math.toRadians(-rot))));

        vertexData[20] = vx;
        vertexData[21] = vy;

        return vertexData;
    }

 

The method handleXRotation only handles the top face so far. I'm probably doing this way wrong, but this what I got. When I test this code the top face disappears.

here's a screenshot of it:

Spoiler

oEY5D1N.png

 

Ok, I now have the following code, and it isn't rotating like I wanted it to.

Spoiler

    protected static BlockRendererDispatcher blockRenderer;

    @Override
    public void renderTileEntityFast(TileEntityRobot te, double x, double y, double z, float partialTicks, int destroyStage, VertexBuffer renderer) {
        if(blockRenderer == null) blockRenderer = Minecraft.getMinecraft().getBlockRendererDispatcher();
        BlockPos pos = te.getPos();
        IBlockAccess world = MinecraftForgeClient.getRegionRenderCache(te.getWorld(), pos);
        IBlockState state = world.getBlockState(pos);

        IBakedModel model = blockRenderer.getBlockModelShapes().getModelForState(state);

        renderer.setTranslation(x - pos.getX() + 2.0f, y - pos.getY(), z - pos.getZ() + 2.0f);

        BakedQuad bq = model.getQuads(state, null, 0L).get(0);

        transform(bq, new TRSRTransformation(new Vector3f(0, 0, 0), new Quat4f(-0.49f, 0, 0, -0.87f), new Vector3f(1, 1, 1), new Quat4f(0.49f, 0, 0, 0.87f)));

        model.getQuads(state, null, 0L).set(0, bq);

        blockRenderer.getBlockModelRenderer().renderModel(world, model, state, pos, renderer, false);
    }

    public static BakedQuad transform(BakedQuad quad, final TRSRTransformation transform) {
        UnpackedBakedQuad.Builder builder = new UnpackedBakedQuad.Builder(DefaultVertexFormats.BLOCK);
        final IVertexConsumer consumer = new VertexTransformer(builder) {
            @Override
            public void put(int element, float... data) {
                VertexFormatElement formatElement = DefaultVertexFormats.BLOCK.getElement(element);
                switch(formatElement.getUsage()) {
                    case POSITION: {
                        float[] newData = new float[3];
                        Vector3f vec = new Vector3f(data);
                        transform.getMatrix().transform(vec);
                        vec.get(newData);
                        parent.put(element, newData);
                        break;
                    }
                    default: {
                        parent.put(element, data);
                        break;
                    }
                }
            }
        };

        quad.pipe(consumer);
        return builder.build();
    }

 

 

It's still not working.

Spoiler

protected static BlockRendererDispatcher blockRenderer;

    public int curStep = 0;
    public int totalSteps = 0;

    @Override
    public void renderTileEntityFast(TileEntityRobot te, double x, double y, double z, float partialTicks, int destroyStage, VertexBuffer renderer) {
        if(blockRenderer == null) blockRenderer = Minecraft.getMinecraft().getBlockRendererDispatcher();
        BlockPos pos = te.getPos();
        IBlockAccess world = MinecraftForgeClient.getRegionRenderCache(te.getWorld(), pos);
        IBlockState state = world.getBlockState(pos);

        IBakedModel model = blockRenderer.getBlockModelShapes().getModelForState(state);

        renderer.setTranslation(x - pos.getX() + 2.0f, y - pos.getY(), z - pos.getZ() + 2.0f);

        List<BakedQuad> quadList = model.getQuads(state, null, 0L);

        for(BakedQuad quad : quadList) {
            transform(quad, new TRSRTransformation(new Vector3f(0, 0, 0), new Quat4f(-0.49f, 0, 0, -0.87f), new Vector3f(1, 1, 1), new Quat4f(0.49f, 0, 0, 0.87f)));
        }

        blockRenderer.getBlockModelRenderer().renderModel(world, model, state, pos, renderer, false);
    }

    public static BakedQuad transform(BakedQuad quad, final TRSRTransformation transform) {
        UnpackedBakedQuad.Builder builder = new UnpackedBakedQuad.Builder(DefaultVertexFormats.BLOCK);
        final IVertexConsumer consumer = new VertexTransformer(builder) {
            @Override
            public void put(int element, float... data) {
                VertexFormatElement formatElement = DefaultVertexFormats.BLOCK.getElement(element);
                switch(formatElement.getUsage()) {
                    case POSITION: {
                        float[] newData = new float[3];
                        Vector3f vec = new Vector3f(data);
                        transform.getMatrix().transform(vec);
                        vec.get(newData);
                        parent.put(element, newData);
                        break;
                    }
                    default: {
                        parent.put(element, data);
                        break;
                    }
                }
            }
        };

        quad.pipe(consumer);
        return builder.build();
    }

 

 

10 minutes ago, diesieben07 said:
  • Don't try to modify the model's quads, this is a terrible idea.

Isn't that what I'm doing? I'm rotating one of the cubes?

Ok. I tried that and it only renders the top face (unrotated). I'm probably still doing it wrong.

    protected static BlockRendererDispatcher blockRenderer;

    public int curStep = 0;
    public int totalSteps = 0;

    @Override
    public void renderTileEntityFast(TileEntityRobot te, double x, double y, double z, float partialTicks, int destroyStage, VertexBuffer renderer) {
        if(blockRenderer == null) blockRenderer = Minecraft.getMinecraft().getBlockRendererDispatcher();
        BlockPos pos = te.getPos();
        IBlockAccess world = MinecraftForgeClient.getRegionRenderCache(te.getWorld(), pos);
        IBlockState state = world.getBlockState(pos);

        final IBakedModel model = blockRenderer.getBlockModelShapes().getModelForState(state);

        renderer.setTranslation(x - pos.getX() + 2.0f, y - pos.getY(), z - pos.getZ() + 2.0f);

        final List<BakedQuad> quadList = model.getQuads(state, null, 0L);

        for(BakedQuad quad : quadList) {
            transform(quad, new TRSRTransformation(new Vector3f(0, 0, 0), new Quat4f(-0.49f, 0, 0, -0.87f), new Vector3f(1, 1, 1), new Quat4f(0.49f, 0, 0, 0.87f)));
        }

        final IBakedModel newModel = new IBakedModel() {
            @Override
            public List<BakedQuad> getQuads(IBlockState state, EnumFacing side, long rand) {
                return quadList;
            }

            @Override
            public boolean isAmbientOcclusion() {
                return model.isAmbientOcclusion();
            }

            @Override
            public boolean isGui3d() {
                return model.isGui3d();
            }

            @Override
            public boolean isBuiltInRenderer() {
                return model.isBuiltInRenderer();
            }

            @Override
            public TextureAtlasSprite getParticleTexture() {
                return model.getParticleTexture();
            }

            @Override
            public ItemCameraTransforms getItemCameraTransforms() {
                return model.getItemCameraTransforms();
            }

            @Override
            public ItemOverrideList getOverrides() {
                return model.getOverrides();
            }
        };

        blockRenderer.getBlockModelRenderer().renderModel(world, newModel, state, pos, renderer, false);
    }

    //This method was borrowed from Vazkii's mod called Botania. It was modified to work for a block instead of an item.
    public static BakedQuad transform(BakedQuad quad, final TRSRTransformation transform) {
        UnpackedBakedQuad.Builder builder = new UnpackedBakedQuad.Builder(DefaultVertexFormats.BLOCK);
        final IVertexConsumer consumer = new VertexTransformer(builder) {
            @Override
            public void put(int element, float... data) {
                VertexFormatElement formatElement = DefaultVertexFormats.BLOCK.getElement(element);
                switch(formatElement.getUsage()) {
                    case POSITION: {
                        float[] newData = new float[3];
                        Vector3f vec = new Vector3f(data);
                        transform.getMatrix().transform(vec);
                        vec.get(newData);
                        parent.put(element, newData);
                        break;
                    }
                    default: {
                        parent.put(element, data);
                        break;
                    }
                }
            }
        };

        quad.pipe(consumer);
        return builder.build();
    }

 

Mind you, I am creating a new instance of the model every rendering tick. Not sure how to get around that.

Thanks for pointing that out. Now it isn't rendering.

protected static BlockRendererDispatcher blockRenderer;

    @Override
    public void renderTileEntityFast(TileEntityRobot te, double x, double y, double z, float partialTicks, int destroyStage, VertexBuffer renderer) {
        if(blockRenderer == null) blockRenderer = Minecraft.getMinecraft().getBlockRendererDispatcher();
        BlockPos pos = te.getPos();
        IBlockAccess world = MinecraftForgeClient.getRegionRenderCache(te.getWorld(), pos);
        IBlockState state = world.getBlockState(pos);

        final IBakedModel model = blockRenderer.getBlockModelShapes().getModelForState(state);

        renderer.setTranslation(x - pos.getX() + 2.0f, y - pos.getY(), z - pos.getZ() + 2.0f);

        final List<BakedQuad> quadList = model.getQuads(state, null, 0L);
        final List<BakedQuad> newQuadList = Lists.newArrayList();


        for(BakedQuad quad : quadList) {
            newQuadList.add(transform(quad, new TRSRTransformation(new Vector3f(0, 0, 0), new Quat4f(-0.49f, 0, 0, -0.87f), new Vector3f(1, 1, 1), new Quat4f(0.49f, 0, 0, 0.87f))));
        }

        final IBakedModel newModel = new IBakedModel() {
            @Override
            public List<BakedQuad> getQuads(IBlockState state, EnumFacing side, long rand) {
                return newQuadList;
            }

            @Override
            public boolean isAmbientOcclusion() {
                return model.isAmbientOcclusion();
            }

            @Override
            public boolean isGui3d() {
                return model.isGui3d();
            }

            @Override
            public boolean isBuiltInRenderer() {
                return model.isBuiltInRenderer();
            }

            @Override
            public TextureAtlasSprite getParticleTexture() {
                return model.getParticleTexture();
            }

            @Override
            public ItemCameraTransforms getItemCameraTransforms() {
                return model.getItemCameraTransforms();
            }

            @Override
            public ItemOverrideList getOverrides() {
                return model.getOverrides();
            }
        };

        blockRenderer.getBlockModelRenderer().renderModel(world, newModel, state, pos, renderer, false);
    }

    //This method was borrowed from Vazkii's mod called Botania. It was modified to work for a block instead of an item.
    public static BakedQuad transform(BakedQuad quad, final TRSRTransformation transform) {
        UnpackedBakedQuad.Builder builder = new UnpackedBakedQuad.Builder(DefaultVertexFormats.BLOCK);
        final IVertexConsumer consumer = new VertexTransformer(builder) {
            @Override
            public void put(int element, float... data) {
                VertexFormatElement formatElement = DefaultVertexFormats.BLOCK.getElement(element);
                switch(formatElement.getUsage()) {
                    case POSITION: {
                        float[] newData = new float[3];
                        Vector3f vec = new Vector3f(data);
                        transform.getMatrix().transform(vec);
                        vec.get(newData);
                        parent.put(element, newData);
                        break;
                    }
                    default: {
                        parent.put(element, data);
                        break;
                    }
                }
            }
        };

        quad.pipe(consumer);
        return builder.build();
    }

 

Did I get the Quat4fs right? I haven't really worked with them. I used this to get the numbers for them.

Edited by Awesome_Spider

How else would I do it?

Ok. I think I'm doing that now. But it isn't rendering.

 

protected static BlockRendererDispatcher blockRenderer;

    @Override
    public void renderTileEntityFast(TileEntityRobot te, double x, double y, double z, float partialTicks, int destroyStage, VertexBuffer renderer) {
        if(blockRenderer == null) blockRenderer = Minecraft.getMinecraft().getBlockRendererDispatcher();
        BlockPos pos = te.getPos();
        IBlockAccess world = MinecraftForgeClient.getRegionRenderCache(te.getWorld(), pos);
        IBlockState state = world.getBlockState(pos);

        final IBakedModel model = blockRenderer.getBlockModelShapes().getModelForState(state);

        renderer.setTranslation(x - pos.getX() + 2.0f, y - pos.getY(), z - pos.getZ() + 2.0f);

        for(int i = 0; i > model.getQuads(state, null, 0L).size(); i++) {
            BakedQuad quad = model.getQuads(state, null, 0L).get(i);
            quad = transform(quad, new TRSRTransformation(new Vector3f(0, 0, 0), new Quat4f(-0.49f, 0, 0, -0.87f), new Vector3f(1, 1, 1), new Quat4f(0.49f, 0, 0, 0.87f)));

            renderer.addVertexData(quad.getVertexData());
        }
    }

    //This method was borrowed from Vazkii's mod called Botania. It was modified to work for a block instead of an item.
    public static BakedQuad transform(BakedQuad quad, final TRSRTransformation transform) {
        UnpackedBakedQuad.Builder builder = new UnpackedBakedQuad.Builder(DefaultVertexFormats.BLOCK);
        final IVertexConsumer consumer = new VertexTransformer(builder) {
            @Override
            public void put(int element, float... data) {
                VertexFormatElement formatElement = DefaultVertexFormats.BLOCK.getElement(element);
                switch(formatElement.getUsage()) {
                    case POSITION: {
                        float[] newData = new float[3];
                        Vector3f vec = new Vector3f(data);
                        transform.getMatrix().transform(vec);
                        vec.get(newData);
                        parent.put(element, newData);
                        break;
                    }
                    default: {
                        parent.put(element, data);
                        break;
                    }
                }
            }
        };

        quad.pipe(consumer);
        return builder.build();
    }

 

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...

Important Information

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

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.