Posted March 1, 20178 yr 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?
March 1, 20178 yr 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.
March 1, 20178 yr 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?
March 2, 20178 yr 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.
March 2, 20178 yr 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).
March 2, 20178 yr 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.
March 2, 20178 yr 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.
March 2, 20178 yr 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(); }
March 2, 20178 yr 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?
March 3, 20178 yr 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.
March 3, 20178 yr 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 March 3, 20178 yr by Awesome_Spider
March 6, 20178 yr 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.