Jump to content

Recommended Posts

Posted

Hello, here's the deal:

I am making a custom rendered model for a tile entity. Most parts of it are static and do not need changing, so that's simple. But one part has to change its texture depending on the state of the tile entity. Now, I want to make this as clean and efficient as possible, so I'm asking you, the people of Forge. The model class extends ModelBase and contains a few ModelRenderers. Four of them are static, and one has to have variable textures. Specifically, the Screen. Here is the code:

ModelRenderer Base;
ModelRenderer Controls;
ModelRenderer Body;
ModelRenderer Top;
ModelRenderer Screen;

public ModelArcadeGameTop() {
textureWidth = 64;
textureHeight = 64;

Base = new ModelRenderer(this, 0, 0);
Base.addBox(0F, 0F, 0F, 16, 2, 16);
Base.setRotationPoint(-8F, 22F, -8F);
Base.setTextureSize(64, 64);
Base.mirror = true;
setRotation(Base, 0F, 0F, 0F);

Controls = new ModelRenderer(this, 0, 41);
Controls.addBox(-8F, 0F, 0F, 16, 2, 7);
Controls.setRotationPoint(0F, 22F, -8F);
Controls.setTextureSize(64, 64);
Controls.mirror = true;
setRotation(Controls, 0.2792527F, 0F, 0F);

Body = new ModelRenderer(this, 0, 18);
Body.addBox(0F, 0F, 0F, 16, 13, 10);
Body.setRotationPoint(-8F, 9F, -2F);
Body.setTextureSize(64, 64);
Body.mirror = true;
setRotation(Body, 0F, 0F, 0F);

Top = new ModelRenderer(this, 0, 50);
Top.addBox(0F, 0F, 0F, 16, 1, 11);
Top.setRotationPoint(-8F, 8F, -3F);
Top.setTextureSize(64, 64);
Top.mirror = true;
setRotation(Top, 0F, 0F, 0F);


textureWidth = 32;
textureHeight = 32;

Screen = new ModelRenderer(this, 0, 0);
Screen.addBox(0F, 0F, 0F, 14, 10, 0);
Screen.setRotationPoint(-7F, 10F, -2F);
Screen.setTextureSize(32, 32);
Screen.mirror = true;
setRotation(Screen, 0F, 0F, 0F);
}

As you can see, I've initialized the texture offset for the Screen in the constructor of this ModelBase. It also has different texture size, because it uses a separate texture file to all the other parts.

 

I've come up with two options for changing the texture. The one above only intializes the Screen variable once, but requires more than one texture file for it, since the offset is already set here and I think it can't be changed (correct me if I'm wrong). So, I'd have to make a few ResourceLocations and then swap them in the renderer.

 

The second option would be to create a separate function for the rendering of this one part, like so:

public void renderScreen(int textXOffset, int textYOffset, int sizeX, int sizeY, int sizeZ, float offX, float offY, float offZ, float moveX, float moveY, float moveZ, float rotX, float rotY, float rotZ, int textWidth, int textHeight, float f)
{
textureWidth = textWidth;
textureHeight = textHeight;

Screen = new ModelRenderer(this, textXOffset, textYOffset);
Screen.addBox(offX, offY, offZ, sizeX, sizeY, sizeZ);
Screen.setRotationPoint(moveX, moveY, moveZ);
Screen.setTextureSize(textWidth, textHeight);
Screen.mirror = true;
setRotation(Screen, rotX, rotY, rotZ);
Screen.render(f);
}

However, this option creates a new ModelRenderer every time the model is rendered, so very, very often. On the other hand, it can be set so that there is one texture file, and a few options in it, and I can just change the offset of the Screen. Besides, both options seem kinda dirty, so maybe there is some kinda method for changing the texture offset in the file? So, I'm asking which option is better, and if there are any other ones. Thanks in advance.

Posted

I'd have to do some digging to be sure, but I don't know if method 1 will work.  Have you traced out how the models components use textureWidth/Height.  Is it a static grab or referenced later during the render process.  I'm betting its the latter.

 

If my guess is right, just make them all the same size.  You don't have to use the full 64x64.

 

As far as methods go, I would move where I bind the texture from the renderer class to the model class.

 

Follow a pattern of

1) bind texture

2) Render relevant model components

 

rinse and repeat.

 

There are a few other ways, but this is how I would do it(and have in the past).

 

In your model have everything the same texture size.  Have 4 'Screens' as you have named them. Identical in place, rotation, ect, except that they point to a different part of the texture file.  This way each version of your 'screen' has its own unique texture inside of one file.

 

During the render step, choose which of the 4 'screens' to render.  Very low processing load.  Tradeoff is you will have a bit larger of a model and texture file.

 

Long time Bukkit & Forge Programmer

Happy to try and help

Posted

Method 1 works, because I've already tested it, but I think I'll follow your advice and create a few Screens, each one pointing to a different place in the same texture file.

 

As to moving the texture binding methods into the model, look at my Renderer code. Shouldn't all this GL11 stuff stay in the Renderer?

@Override
public void renderTileEntityAt(TileEntity tileEntity, double x, double y, double z, float f1) {
int dir = tileEntity.getWorldObj().getBlockMetadata(tileEntity.xCoord, tileEntity.yCoord, tileEntity.zCoord);

GL11.glPushMatrix();
GL11.glTranslatef((float)x + 0.5F, (float)y + 1.5F, (float)z + 0.5F);
GL11.glRotatef(180.0F, 0.0F, 0.0F, 1.0F);
GL11.glRotatef(dir * 90.0F, 0.0F, 1.0F, 0.0F);

bindTexture(fileTexture);
modelArcadeGameTop.renderModel(0.0625F);

bindTexture(fileScreenTexture);
modelArcadeGameTop.Screen.render(0.0625F);
GL11.glPopMatrix();
}

Posted

Doesn't have to.  Typically if you are using a vanilla model or renderer, you need to make sure to follow the pattern.

 

If you have a custom render and a custom model, go nutz and do whatever.

 

What you have shown below though should work fine.

Long time Bukkit & Forge Programmer

Happy to try and help

Posted

And now it refuses to work. I have to use 7 different screen versions, so I decided I'll use an array instead of 7 variables, because they are the same. For some reason, Minecraft/GL hates arrays and crashes. Here's how the code looks. Model:

ModelRenderer base;
ModelRenderer controls;
ModelRenderer body;
ModelRenderer top;
ModelRenderer[] screens = new ModelRenderer[7];
ModelRenderer fff;
ModelRenderer fff2;

public ModelArcadeGameTop() {
	textureWidth = 64;
	textureHeight = 256;

	base = new ModelRenderer(this, 0, 0);
	base.addBox(0F, 0F, 0F, 16, 2, 16);
	base.setRotationPoint(-8F, 22F, -8F);
	base.setTextureSize(64, 256);
	base.mirror = true;
	setRotation(base, 0F, 0F, 0F);

	controls = new ModelRenderer(this, 0, 41);
	controls.addBox(-8F, 0F, 0F, 16, 2, 7);
	controls.setRotationPoint(0F, 22F, -8F);
	controls.setTextureSize(64, 256);
	controls.mirror = true;
	setRotation(controls, 0.2792527F, 0F, 0F);

	body = new ModelRenderer(this, 0, 18);
	body.addBox(0F, 0F, 0F, 16, 13, 10);
	body.setRotationPoint(-8F, 9F, -2F);
	body.setTextureSize(64, 256);
	body.mirror = true;
	setRotation(body, 0F, 0F, 0F);

	top = new ModelRenderer(this, 0, 50);
	top.addBox(0F, 0F, 0F, 16, 1, 11);
	top.setRotationPoint(-8F, 8F, -3F);
	top.setTextureSize(64, 256);
	top.mirror = true;
	setRotation(top, 0F, 0F, 0F);

	int textOffsetY = 66;
	for (ModelRenderer screen : screens) {
		screen = new ModelRenderer(this, 0, textOffsetY);
		screen.addBox(0F, 0F, 0F, 28, 20, 0);
		screen.setRotationPoint(-14F, 20F, -4F);
		screen.setTextureSize(64, 256);
		screen.mirror = true;
		setRotation(screen, 0F, 0F, 0F);
		textOffsetY += 21;
		System.out.println(screens.length);
	}

	fff = new ModelRenderer(this, 0, 66);
	fff.addBox(0F, 0F, 0F, 28, 20, 0);
	fff.setRotationPoint(-14F, 20F, -4F);
	fff.setTextureSize(64, 256);
	fff.mirror = true;
	setRotation(fff, 0F, 0F, 0F);

	fff2 = new ModelRenderer(this, 0, 87);
	fff2.addBox(0F, 0F, 0F, 28, 20, 0);
	fff2.setRotationPoint(-14F, 20F, -4F);
	fff2.setTextureSize(64, 256);
	fff2.mirror = true;
	setRotation(fff2, 0F, 0F, 0F);
}

Renderer:

@Override
public void renderTileEntityAt(TileEntity tileEntity, double x, double y, double z, float f1) {
	int dir = tileEntity.getWorldObj().getBlockMetadata(tileEntity.xCoord, tileEntity.yCoord, tileEntity.zCoord);

	GL11.glPushMatrix();
		GL11.glTranslatef((float)x + 0.5F, (float)y + 1.5F, (float)z + 0.5F);
		GL11.glRotatef(180.0F, 0.0F, 0.0F, 1.0F);
		GL11.glRotatef(dir * 90.0F, 0.0F, 1.0F, 0.0F);

		bindTexture(fileTexture);
		modelArcadeGameTop.renderModel(0.0625F);

		GL11.glScalef(0.5F, 0.5F, 0.5F);
		//modelArcadeGameTop.screens[2].render(0.0625F);
		modelArcadeGameTop.fff.render(0.0625F);
		modelArcadeGameTop.fff2.render(0.0625F);
	GL11.glPopMatrix();
}

fff and fff2 are just for testing. When I comment out the rendering call for the screens, everything works fine. However, when I try to access any of the 7 screens in the screens array and render it, the game crashes. Here's the log: https://gist.github.com/anonymous/53c149bc11bebe6f11dd, from line 183.What is up with this, and why won't it work?

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.