Jump to content

[1.8] Time for some NBT-Rendering.


Ernio

Recommended Posts

I know that there are at least few people here who dealt with this thing. *Looks at TGG*

 

Now, I've alredy looked (read code/notes) at all MCByExample Item tutorials and I am "still" wondering if what I am doing it supported and how should I archieve it.

 

Examples are best: Let's say player wants to make Longsword.

Player crafts 3 items: Hilt, Guard, Blade.

Those items can be crafted from like literally anything, they have their factors and most importantly (in this case) - texture key.

 

Putting together those 3 items in next crafting process creates custom sword - that holds 3 texture keys.

 

In order: Hilt, Guard, Blade

98sf3t.jpg

a2afdt.jpg

16238qs.jpg

 

Partial textures are alredy offset to not deal with translations.

Hilt and Blade should be placed 1st, then on top of them (overlap) there should be "connecting" Guard (to not leve glitches where e.g blade is rendered on top of Guard).

 

System was designed and was working on 1.7.10 with IItemRenderer, which was like the best thing that has ever happened to "smart" rendering, ever. *Looks at ISmartItemModel with hesitancy*

 

Now - how would I get that working in 1.8?

 

Goals:

- Put Guard on top of Hilt and Blade (with no texture overlapping glitching)

 

- Allow any .png input (read from stacks's NBT) - texture keys look like this:

String key = nbt.getString("K")

Then: MODID + ":items/" + key

System know which one is which (e.g Hilt/Guard/Blade).

 

- Texture-resolution-compatible, so that it works with x16, x32, x64, etc.

Note: I am not talking about that Guard would be 16x16, and Blade 64x64, no need for that, all parts are always same-resolution.

 

Additional:

In 1.7.10 I also made "bigger" weapon rendering (so that your item is rendered twice the size), so 32x32 texture looked like 16x16 resolution after rendering (item was twice size in-game).

Is it possible in 1.8 and how would I approach it?

 

I am seriously thinking about reimplementing IItemRenderer on my own, just to not deal with all those models...

 

Well, that's it, any hints - appreciated :D

 

Thanks :D

1.7.10 is no longer supported by forge, you are on your own.

Link to comment
Share on other sites

Hi

 

I think there are a couple of key points

- you will need to load in all the textures in advance; a custom ModelLoader can do this for you (MBE05 - ModelLoader3DWeb and WebModel) so long as it has all the paths from your NBTs.  If you add an item with a new NBT later, you will need to refresh/restitch the texture sheet.  This is probably the biggest difference from IItemRenderer, i.e. it's rather difficult to bind your own texture just for the rendering of your item.  (I tried, gave up because it was too glitchy for me).

- assuming all hilts have the same shape, and all guards the same shape, and all blades the same shape, have a model for each (i.e. 3 models total) and make sure they overlap nicely.

- in your ISmartItemModel, use the NBT to pick the three models, work through each BakedQuad to modify the uv coordinates to match the target texture coordinates.  MBE15 - ChessboardSmartItemModel does something very similar  in createBakedQuadForFace / vertextToInts

 

You can make your weapons appear double size by giving them a larger scale in the model json or by modifying IBakedModel.getItemCameraTransform (similar to how MBE14 does it)

 

-TGG

Link to comment
Share on other sites

- you will need to load in all the textures in advance; a custom ModelLoader can do this for you (MBE05 - ModelLoader3DWeb and WebModel) so long as it has all the paths from your NBTs.  If you add an item with a new NBT later, you will need to refresh/restitch the texture sheet.

 

I alredy some experiments, but I have to ask:

What do you mean by above?

Particulary:

"you will need to load in all the textures in advance"

- My textures (like one shown in op post) are loaded on startup (are simply all inside assets). E.g.: "weaponpart_shortsword_blade_demonic.png"

Whole "weaponpart_shortsword_blade_" is derived from Class, only "demonic" is read from NBT.

 

"If you add an item with a new NBT later, you will need to refresh/restitch the texture sheet"

I mean, there will be like hundreds of different guards and blades. What exacly are we talking about here? Isn't .png being in assets folder enough? I have to manually add it in code?

1.7.10 is no longer supported by forge, you are on your own.

Link to comment
Share on other sites

I think the TGG's example: https://github.com/TheGreyGhost/MinecraftByExample/blob/master/src/main/java/minecraftbyexample/mbe15_item_smartitemmodel/ChessboardSmartItemModel.java#L61

would be fine to use for the case. It seems that you can just simply use that with your own textures.

I. Stellarium for Minecraft: Configurable Universe for Minecraft! (WIP)

II. Stellar Sky, Better Star Rendering&Sky Utility mod, had separated from Stellarium.

Link to comment
Share on other sites

- you will need to load in all the textures in advance; a custom ModelLoader can do this for you (MBE05 - ModelLoader3DWeb and WebModel) so long as it has all the paths from your NBTs.  If you add an item with a new NBT later, you will need to refresh/restitch the texture sheet.

 

I alredy some experiments, but I have to ask:

What do you mean by above?

Particulary:

"you will need to load in all the textures in advance"

- My textures (like one shown in op post) are loaded on startup (are simply all inside assets). E.g.: "weaponpart_shortsword_blade_demonic.png"

Whole "weaponpart_shortsword_blade_" is derived from Class, only "demonic" is read from NBT.

 

"If you add an item with a new NBT later, you will need to refresh/restitch the texture sheet"

I mean, there will be like hundreds of different guards and blades. What exacly are we talking about here? Isn't .png being in assets folder enough? I have to manually add it in code?

It's not enough to just have your png file inside assets, you need to register its ResourceLocation so that it gets stitched into the texture sheet.

Basically: the textures for all items and blocks are stitched together into a single big texture, kind of like a patchwork quilt. 

See the "Texture Coordinates" image on this page for an idea of what it looks like.

http://greyminecraftcoder.blogspot.co.at/2014/12/the-tessellator-and-worldrenderer-18.html

Once your png file is stitched into the texture sheet you can make BakedQuads which refer to it and render it like a normal item does.

 

-TGG

 

Link to comment
Share on other sites

Well, I must say I don't know next shit about what am I supposed to be doing.

 

Could you maybe walk me through how those things even work? (not Tess, that I know how to do).

 

1. How to put ResourceLocation into TextureMap, when and with what (I know there is some event regarding stitching).

2. Inside My ISmartItemModel I have ready-to-use ArrayList<ResourceLocation> that points (in order) on textures that should be rendered.

- What now? I assume I have to:

TextureAtlasSprite one = Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite("roa:items/firstTextureFromMyList");
TextureAtlasSprite two = Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite("roa:items/secondTextureFromMyList");
TextureAtlasSprite three = Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite("roa:items/thirdTextureFromMyList");

And somehow put them together.

 

You said that I need to have model for each weapon part. The whole point was to NOT have model.

I want to generate model in runtime.

 

1. Get 3 textures

2. Put them together

3. Stretch thickness

4. Return created new model

5. Render

 

Hulp me doctor, it hurtz.

 

Thanks.

1.7.10 is no longer supported by forge, you are on your own.

Link to comment
Share on other sites

Well, I must say I don't know next shit about what am I supposed to be doing.

 

Could you maybe walk me through how those things even work? (not Tess, that I know how to do).

 

1. How to put ResourceLocation into TextureMap, when and with what (I know there is some event regarding stitching).

2. Inside My ISmartItemModel I have ready-to-use ArrayList<ResourceLocation> that points (in order) on textures that should be rendered.

- What now? I assume I have to:

TextureAtlasSprite one = Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite("roa:items/firstTextureFromMyList");
TextureAtlasSprite two = Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite("roa:items/secondTextureFromMyList");
TextureAtlasSprite three = Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite("roa:items/thirdTextureFromMyList");

And somehow put them together.

 

You said that I need to have model for each weapon part. The whole point was to NOT have model.

I want to generate model in runtime.

 

1. Get 3 textures

2. Put them together

3. Stretch thickness

4. Return created new model

5. Render

The way I was thinking, you would need three models only, to define the shape of the hilt, the guard, and the blade. 

 

But it sounds like you want the hilt, guard and blade to have different shapes instead of just different colours/patterns.  In that case, you will need to generate a model from the .png files, like vanilla does with the vanilla sword.  That's trickier stuff, but not impossible.  It has the advantage you don't need to mess around with registering your textures in the TextureMap, but is also a lot more complicated.

Your five step process above looks about right to me in that case.  You will need to read the texel values from the textures, and turn each texel into a cube using 6 quads.  So your sword effectively becomes a flat layer of cubes, up to 16x16 in total, one for each texel in your sword's 2D picture.

The vanilla code for generating item models from 2D textures is in ItemModelGenerator, but I should warn you it's pretty hard going.

If you're doing it this way, you don't need to stitch your textures into the TextureMap, you can read your texture into a BufferedImage instead (see SimpleTexture.loadTexture) and just read out the texels one by one using code, but it does mean a lot more effort in your model baking.

 

I think step 1 for you is probably to master generating a small cube from quads using ISmartItemModel to bake your own- similar to how MBE15 does it for the chessboard pieces, except all 6 faces instead of just the one.

Once you've done that, I'd suggest you then add the texel reading from png, with one cube per quad (make the cubes just slightly smaller than 1/16, so they don't overlap)

Once that works, figure out how to cache it so you don't have to regenerate up to 256*6 quads for every single sword, for every single frame... :)

 

Hulp me doctor, it hurtz.

yeah learning minecraft rendering had that effect on me too...

 

-TGG

Link to comment
Share on other sites

As to caching I will probably create model map (String+String+String = key, model = value).

 

As to generating - pretty much what I was afraid to do (make cubes on my own).

 

Thanks for class-references, gonna look there.

 

One question tho: When MC bakes models it doesnt care about resolution, you said I should draw 16x16 cubes, so if I'd want resolution support do I actually have to generate e.g 256x256 (shitload of cubes)? Was trying to find (in MC) where exacly that happens (reading pixels and making cubes) - do you know by any chance? I did like 30+ callbacks and shit is leading nowhere, probably got lost ;_;

 

Thanks for all help :D

(Btw. I actually managed to render sword from 3 other models, that is easy, but generating it whole different level).

1.7.10 is no longer supported by forge, you are on your own.

Link to comment
Share on other sites

> Was trying to find (in MC) where exacly that happens (reading pixels and making cubes) - do you know by any chance?

It is in ItemModelGenerator, the whole class is dedicated to doing that.

It uses some optimisations so it doesn't actually draw cubes for all sides, only the ones at the edge of the image (i.e. where you have two cubes next to each other, it doesn't create the two quads that are between the cubes.)  If your image doesn't have many holes, this will save you up to 2/3 of the quads.

But otherwise, yes that's essentially how it does it, for the "edges with thickness" anyway. 

 

Once you've got the basic idea working, you can optimise further -

eg by drawing the two flat faces with one quad each (with transparent holes) - in which case you are back to stitching your texture into the TextureMap again.  This is how vanilla does the flat faces.

There is probably also a way to only use the 'thickness' model with first person and  third person views, and switch to a simple 2D model for inventory views, which will save a lot of rendering.  (But I'm not sure how, you'd need to hunt around for it)

 

-TGG

256x256 is probably too big in either case :)

 

 

Link to comment
Share on other sites

Well, this shit turned out to be more challenging (and fun) than I expected.

After a while (days) I decided to redesign system and actually simplify process to rendering item from few models.

 

Basically:

combinedQuadsList.addAll(iBakedModel.getGeneralQuads());

 

Now, the problem is that item to be rendered from few other models is like super-parent to them, meaning that the offset and thickness for partial models is derived from those defined in the item-to-be-rendered model file (json).

Explanation:

 

 

In 'assets/mod/models/item' , there are:

weapon_base.json

part_blade.json

part_guard.json

part_hilt.json

 

In-game item uses weapon_base.json transformations and applies them on those sub-models, added with:

combinedQuadsList.addAll(iBakedModel.getGeneralQuads());

 

 

 

Okay, so while it is NOT that bad (considering that I alredy rewrote everything I had), I'd like to manipulate those BakedQuads a bit. For example to make guard thicker than hilt and blade (obviously).

 

Problems:

1. I have no clue (can't track down code) where the json transformation happens.

- On the one end it seems like models are generated on startup, BUT when I look at it - that would mean that if'd put together BakedQuads of few different models the transformations would stay and they don't. So I think - the transformations for given .json MUST be stored somewhere, BUT WHERE? I am planning to get them (for specific part) and apply (partially) on the BakedQuads I'll be adding to the to-render-model. (ofc. caching stuff)

 

2. How to manipulate vertexes? (tuts, explanation)

Useful info is around FaceBakery#storeVertexData. Now I'd like to know what is what (I meam, I can read names of vars but I don't quite get which represents what).

Plan is "simple":

- get all "front" and "back" quads and move them a bit "forward" (thicken model)

- get all rest (the "vertical" ones) and expand them to fit thickening.

- cache ready-to-use list of BakedQuads and use it for rest of renders.

While it might be an overkill, I feel safer doing this than making models on my own.

 

3. In RenderItem:

private void renderModel(IBakedModel model, int color, ItemStack stack)
    {
        Tessellator tessellator = Tessellator.getInstance();
        WorldRenderer worldrenderer = tessellator.getWorldRenderer();
        worldrenderer.startDrawingQuads();
        worldrenderer.setVertexFormat(DefaultVertexFormats.ITEM);
        EnumFacing[] aenumfacing = EnumFacing.values();
        int j = aenumfacing.length;

        for (int k = 0; k < j; ++k)
        {
            EnumFacing enumfacing = aenumfacing[k];
            this.renderQuads(worldrenderer, model.getFaceQuads(enumfacing), color, stack);
        }

        this.renderQuads(worldrenderer, model.getGeneralQuads(), color, stack);
        tessellator.draw();
    }

Question: Difference between general and face quads. I mean, names are pretty self-exp, but while:

combinedQuadsList.addAll(iBakedModel.getGeneralQuads());

...adds everything to model, the iteration over all faces and quads with 'model.getFaceQuads(enumfacing)' adds nothing. (Shouldn't those lists be the 'parent' and 'children'?)

 

Damn, it's a lot :D Thanks for any help :D

1.7.10 is no longer supported by forge, you are on your own.

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.