Jump to content

[SOLVED] [1.8] ISmartItemModel, IFlexibleBakedModel, IPerspectiveAwareModel


Recommended Posts

Posted

Hi,

I want to be able to render two models together as one based on first person, third person, etc. I know IPerspectiveAwareModel can take care of the camera transformations, but I don't know how I would render another model with my main model based on those camera transformations. What is ISmartItemModel and IFlexibleBakedModel used for - and why is a great number of things deprecated in IPerspectiveAwareModel? Thanks in advance!

Development of Plugins [2012 - 2014] Development of Mods [2012 - Current]

Posted

Thanks for the help, TGG! I'm learning from MBE15 SmartItemChessboardModel I believe it is. Creating the baked quads looks very confusing - is it possible to recreate a 4x4x12 (Length, Width, Height) box (from a model in java) by creating baked quads? Let's say I created those baked quads - would I be able to render them when the player is in first person and de-render them when in third person? I am asking because ISmartItemModel does not include a handlePerspectiveMethod as does IPerspectiveAwareModel (I've seen where both interfaces are implemented). Thanks again.

Development of Plugins [2012 - 2014] Development of Mods [2012 - Current]

Posted

Hi

 

Yeah the whole modelling system takes quite a bit of getting used to.

What you want to do will work fine.

You should create a class that implements both IPerspectiveAwareModel and ISmartItemModel.

 

handleItemState() will be called first, so you return an IPerspectiveAwareModel which saves the itemstate information internally for later reference

Immediately after, Forge will call handlePerspective with your IPerspectiveAwareModel (which has the saved itemstate info), and you can select or generate the correct first vs third person model.

 

-TGG

Posted

I'm getting a crash from handlePerspective. And what exactly am I supposed to do within the switch block to change the model? Here's the code:

@Override
public Pair<IBakedModel, Matrix4f> handlePerspective(TransformType cameraTransformType) 
{
	switch(cameraTransformType)
	{
	case GUI : //do stuff
		break;
	case FIRST_PERSON : //do stuff
		break;
	case THIRD_PERSON : //do stuff
		break;
	default : //do nothing
		break;
	}
	return ((IPerspectiveAwareModel) this.model).handlePerspective(cameraTransformType);
}

Development of Plugins [2012 - 2014] Development of Mods [2012 - Current]

Posted

I'm getting a crash from handlePerspective. And what exactly am I supposed to do within the switch block to change the model? Here's the code:

@Override
public Pair<IBakedModel, Matrix4f> handlePerspective(TransformType cameraTransformType) 
{
	switch(cameraTransformType)
	{
	case GUI : //do stuff
		break;
	case FIRST_PERSON : //do stuff
		break;
	case THIRD_PERSON : //do stuff
		break;
	default : //do nothing
		break;
	}
	return ((IPerspectiveAwareModel) this.model).handlePerspective(cameraTransformType);
}

By crikey dude the logic behind that code is pretty messed up.  Calling handlePerspective from within handlePerspective is not going to end well.

 

The simplest way of doing this is like this

1) in handleItemState(), save your itemstate information into the model and return 'this'

2) in handlePerspective(), save your cameraTransformType into the model and return a new pair of this and

  the Matrix4f corresponding to the selected view, I think you can get this from

  ForgeHooksClient.getMatrix() by supplying it with the correct transform for the cameraTransformType, eg

        model.getItemCameraTransforms().firstPerson

3) in your IBakedModel.getGeneralQuads(), use the stored itemstate and cameraTransformType to generate the appropriate model

 

Haven't tried it in code so it might need tweaking.

 

-TGG

Posted

By crikey dude the logic behind that code is pretty messed up.  Calling handlePerspective from within handlePerspective is not going to end well.

 

The simplest way of doing this is like this

1) in handleItemState(), save your itemstate information into the model and return 'this'

2) in handlePerspective(), save your cameraTransformType into the model and return a new pair of this and

  the Matrix4f corresponding to the selected view, I think you can get this from

  ForgeHooksClient.getMatrix() by supplying it with the correct transform for the cameraTransformType, eg

        model.getItemCameraTransforms().firstPerson

3) in your IBakedModel.getGeneralQuads(), use the stored itemstate and cameraTransformType to generate the appropriate model

 

Haven't tried it in code so it might need tweaking.

 

-TGG

 

Isn't that the same logic used in MBE14 ItemModelFlexibleCamera? (I looked at this considering it implemented IPerspectiveAwareModel):

@Override 
public Pair<IBakedModel, Matrix4f> handlePerspective(ItemCameraTransforms.TransformType cameraTransformType) { 
    IBakedModel baseModel = getIBakedModel(); 
    return ((IPerspectiveAwareModel) baseModel).handlePerspective(cameraTransformType); 
} 
} 

 

I appreciate your help TGG.

Development of Plugins [2012 - 2014] Development of Mods [2012 - Current]

Posted

Hi

 

it's similar, but there's a critical difference (unless I've misunderstood your code)

 

In MBE14, it has the base model and a wrapper model which has the base model inside it.

 

when wrapper.handlePerspective() is called, it then calls basemodel.handlePerspective() to get the perspective matrix from the base model.

 

wrapper.handlePerspective() doesn't call wrapper.handlePerspective(), which is what I think your code is doing?

 

And also, the cast from basemodel to (IPerspectiveAwareModel)basemodel is only possible because the code has previously checked if basemodel implements IPerspectiveAwareModel.  That's not true in your case?

 

-TGG

 

 

Posted

And also, the cast from basemodel to (IPerspectiveAwareModel)basemodel is only possible because the code has previously checked if basemodel implements IPerspectiveAwareModel.  That's not true in your case?

 

Ahh, your right. I didn't previously check the instanceof for IBakedModel, which caused a ClassCastException. I managed to work with what you were saying (returning the Pair) of IBakedModel and Matrix4f. This code works, however, the model is oddly rotated in a weird way. Here is the code used:

@Override
public Pair<IBakedModel, Matrix4f> handlePerspective(TransformType transformType)
{		
switch(transformType)
{
case FIRST_PERSON: return Pair.of(this,  ForgeHooksClient.getMatrix(this.baseModel.getItemCameraTransforms().firstPerson));
case THIRD_PERSON: return Pair.of(this,  ForgeHooksClient.getMatrix(this.baseModel.getItemCameraTransforms().thirdPerson));
case GUI: return Pair.of(this,  ForgeHooksClient.getMatrix(this.baseModel.getItemCameraTransforms().gui));
case HEAD: return Pair.of(this,  ForgeHooksClient.getMatrix(this.baseModel.getItemCameraTransforms().head));
default: return null;
}
}

Development of Plugins [2012 - 2014] Development of Mods [2012 - Current]

Posted

I've decided that there would be an easier way to do this, I don't know if you necessarily need ISmartItemModel, though. I'm pretty sure you can render two models together. I'm thinking that the class should implement IPerspectiveAwareModel and contain two IBakedModels in the constructor, one being the base model and the other being the model you want to merge with the base model. To merge them, you create a new arraylist containing both the baked quads for the base model and the model you want to merge with then return them in the getGeneralQuads() method. For some reason, that theory doesn't seem to work, it only renders the base model fine, not the model I want to merge with it. If anyone can tell me why, here is my code:

IPerspectiveAwareModel Class

public class ItemModelPerspective implements IPerspectiveAwareModel
{
//The model resource locations for the two models (no specific reason to be in this class, but hey)
public static final ModelResourceLocation BASEMODEL = new ModelResourceLocation(Main.ID + ":" + "gun", "inventory");
public static final ModelResourceLocation MODELTOMERGE = new ModelResourceLocation(Main.ID + ":" + "modelarm", "inventory");

//The two models - one as a base, the other to merge with it
private final IBakedModel baseModel;
private final IBakedModel modelToMerge;

public ItemModelPerspective(IBakedModel baseModel, IBakedModel modelToMerge)
{
	this.baseModel = baseModel;
	this.modelToMerge = modelToMerge;
}

@Override
public List getFaceQuads(EnumFacing enumFacing) 
{
	return this.baseModel.getFaceQuads(enumFacing);
}

@Override
public List getGeneralQuads() //Combine the general quads in a list and return as one
{
	List<BakedQuad> combinedQuads = new ArrayList(this.baseModel.getGeneralQuads());
	combinedQuads.addAll(this.modelToMerge.getGeneralQuads());
	return combinedQuads;
}

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

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

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

@Override
public TextureAtlasSprite getTexture() 
{
	return this.baseModel.getTexture();
}

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

@Override
public Pair<IBakedModel, Matrix4f> handlePerspective(TransformType transformType)
{		
	switch(transformType)
	{
	case FIRST_PERSON: return Pair.of(this,  ForgeHooksClient.getMatrix(this.baseModel.getItemCameraTransforms().firstPerson));
	case THIRD_PERSON: return Pair.of(this,  ForgeHooksClient.getMatrix(this.baseModel.getItemCameraTransforms().thirdPerson));
	case GUI: return Pair.of(this,  ForgeHooksClient.getMatrix(this.baseModel.getItemCameraTransforms().gui));
	case HEAD: return Pair.of(this,  ForgeHooksClient.getMatrix(this.baseModel.getItemCameraTransforms().head));
	default: return null;
	}
}

}

 

ModelBakeEvent Class

public class ItemModelBake
{

@SubscribeEvent
public void modelBakeEvent(ModelBakeEvent event)
{
	Object baseModel = event.modelRegistry.getObject(ItemModelPerspective.BASEMODEL);
	Object modelToMerge = event.modelRegistry.getObject(ItemModelPerspective.MODELTOMERGE);

	if(baseModel instanceof IBakedModel && modelToMerge instanceof IBakedModel)
	{
		IBakedModel newBaseModel = (IBakedModel) baseModel;
		IBakedModel newModelToMerge = (IBakedModel) modelToMerge;

		ItemModelPerspective finalModel = new ItemModelPerspective(newBaseModel, newModelToMerge);
		event.modelRegistry.putObject(ItemModelPerspective.BASEMODEL, finalModel);
	}
}

}

 

EDIT: The code works completely, renders both the models perfecly other than the weird rotation it has on it. Can someone explain why the new, odd rotation is added to the item model? Thanks.

Development of Plugins [2012 - 2014] Development of Mods [2012 - Current]

Posted

>Can someone explain why the new, odd rotation is added to the item model?

 

Sorry dude, I have no experience with that.  You might need to resort to inspecting your Matrix4f, comparing it to the vanilla transform, and seeing what's different.  That will be tricky.

 

-TGG

 

Posted

That's fine TGG, it can be fixed with some simple tweaking in the JSON file - that seems to solve the problem. Can you rather show me how to return a list of baked quads vs. another list of baked quads based on the camera transform? I'm confused on if I should do this in the getGeneralQuads() method or somehow handle it in the handlePerspectiveMethod (tell the model which quads to use there somehow). If you can, tell me what method to do this in and what I should call as a boolean to test if it's first person, third, etc. If I can get that working, we should be good to go! Thanks.

Development of Plugins [2012 - 2014] Development of Mods [2012 - Current]

Posted

This works, it may be very incorrect, but it works. The only thing wrong with it is that you can see the extra model when in your survival inventory (when you can see the player - the 2x2 crafting grid with your player next to it):

@Override
public List getFaceQuads(EnumFacing enumFacing) 
{
	List<BakedQuad> combined = new ArrayList<BakedQuad>(this.baseModel.getFaceQuads(enumFacing));
	if(Minecraft.getMinecraft().gameSettings.thirdPersonView == 0) combined.addAll(this.mergeModel.getFaceQuads(enumFacing));
	return combined;
}

@Override
public List getGeneralQuads()
{
	List<BakedQuad> combined = new ArrayList<BakedQuad>(this.baseModel.getGeneralQuads());
	if(Minecraft.getMinecraft().gameSettings.thirdPersonView == 0)     combined.addAll(this.mergeModel.getGeneralQuads());
	return combined;
}

 

EDIT: Just wanted to clarify, the obove code was tested in a class implementing ISmartItemModel only, an earlier post with code contains the IPerspectiveAwareModel code. The IPerspectiveAwareModel class's handlePerspectiveMethod() changes the rotation of the model for some reason, while ISmartItemModel does not (obviously because of Matrix4f).

Development of Plugins [2012 - 2014] Development of Mods [2012 - Current]

Posted

Hi

 

The method you're using for combing faceQuads and generalQuads looks good; I think all you need to do is use your saved perspective (first person, third person, gui) from the IPerspectiveAwareModel code, in place of the .thirdPersonView.  (And fix the rotation change caused by Forge's Matrix4f transformation).  This will let you handle all three cases properly.

 

TGG

Posted

I appreciate your reply, TGG. So should I just null check each perspective to see if the model returns a first person, third person, etc. perspective, like this?:

if(this.baseModel.getItemCameraTransforms().firstPerson != null) combined.addAll(this.mergeModel.getGeneralQuads());

Is there a proper way of checking these? The odd rotation caused by the changed matrix can be fixed by going into the .JSON code - sadly that makes the model incompatible with your great and so very useful ItemCameraTransform tool.

Thanks.

 

EDIT: Above code doesn't work, still renders both models. BTW, does the camera transform "NONE" refer to the entity item when it is on the ground? I'd like to know this because I need to return the third person model model for the entity item as well. Thanks!

Development of Plugins [2012 - 2014] Development of Mods [2012 - Current]

Posted

Hi

 

I suggest-

 

@Override
public Pair<IBakedModel, Matrix4f> handlePerspective(TransformType transformType)
{		
            myRememberedTransformType = transformType); // field in this
	switch (transformType)
	{
	case FIRST_PERSON: return Pair.of(this,  ForgeHooksClient.getMatrix(this.baseModel.getItemCameraTransforms().firstPerson));
	case THIRD_PERSON: return Pair.of(this,  ForgeHooksClient.getMatrix(this.baseModel.getItemCameraTransforms().thirdPerson));
	case GUI: return Pair.of(this,  ForgeHooksClient.getMatrix(this.baseModel.getItemCameraTransforms().gui));
	case HEAD: return Pair.of(this,  ForgeHooksClient.getMatrix(this.baseModel.getItemCameraTransforms().head));
	default: return null;
	}
}

 

and then

 

public List getFaceQuads(EnumFacing enumFacing) 
{
	List<BakedQuad> combined = new ArrayList<BakedQuad>(this.baseModel.getFaceQuads(enumFacing));

	if (myRememberTransformType == FIRST_PERSON) {    // retrieve the remembered value here
                   combined.addAll(this.mergeModel.getFaceQuads(enumFacing));
                }
	return combined;
}

 

-TGG

Posted

That worked, TGG! Thanks! I can't believe all the times I tried to check the transform type I never thought of saving it in a global field like that. There came another problem - when is this ever going to end, haha - the entity item (when you drop the item on the ground) uses the first person model instead of the wanted third person model. That should be the exact last problem, thanks.

Development of Plugins [2012 - 2014] Development of Mods [2012 - Current]

Posted

Hi

 

Keen, getting there.  The field doesn't need to be global (static), it can be an ordinary member variable.

 

Ah.  Items dropped on the ground don't use any transform at all so they never call IPerspectiveAwareModel.  I don't see them calling ISmartItemModel either.

 

I suggest you should add some System.out.println to your methods to check if that's true.

If so, you should refactor your code to

1) your initial model "A" should look like the dropped item.

2) if ISmartItemModel is called on your initial model "A", return a different model "B" with the itemstack information in it

3) when IPerspectiveAwareModel is called on "B", save the perspective info in "B" and return it again

 

That way, EntityItem renders using model A

All other views render using model B with the saved perspective info.

 

-TGG

 

Posted

Keen, getting there.  The field doesn't need to be global (static), it can be an ordinary member variable.

 

Ah.  Items dropped on the ground don't use any transform at all so they never call IPerspectiveAwareModel.  I don't see them calling ISmartItemModel either.

 

Ah, true on that one, yet the class is made for creating many objects because I need to wrap a lot of models. Anyway, you are exacly right on the entity item having no transform, this can be proven with this method I wrote earlier to see if I could change the perspective, thinking that TransofrmTyoe.NONE is the entity item transform - which it isn't:

        @Override
public List getGeneralQuads()
{
	List<BakedQuad> base = new ArrayList<BakedQuad>(this.baseModel.getGeneralQuads());
	List<BakedQuad> merge = new ArrayList<BakedQuad>(this.mergeModel.getGeneralQuads());
	List<BakedQuad> combined = new ArrayList<BakedQuad>();
	combined.addAll(base);
	combined.addAll(merge);
	switch(this.transform)
	{
	case FIRST_PERSON : return combined;
	case THIRD_PERSON : return base;
	case GUI : return base;
	case HEAD : return base;
	case NONE : return base;
	default : return base;
	}
}

 

The odd thing is, the default .JSON model used for the item (not wrapped model - without IPerspectiveAwareModel) is the baseModel E.G. the model not merged with the other model / the third person model is the default model. For some reason when the entity item enters the world, it gets the current transform which leads me to another question - I thought the generalQuads method pre-determined the transform to get ready for rendering, so it looks like when you throw the item down it already wants to use the transfom type first person. Is there any event that can set the model or any other suggestions? TGG I'll be taking a look at your suggestions in the meantime. Cheers!

Development of Plugins [2012 - 2014] Development of Mods [2012 - Current]

Posted

Well what do you know, a few good hours of coding paid off. I got the model to do exaclty what I want. TGG, I did something very similar to your suggestion by using ISmartItemModel and customizing the model base on the handleItemState() method (by NBT, of course). I set NBT in pickup / drop entityitem methods to control entity item rendering. In the SmartItemModel class, I returned "this" if the NBT boolean was true, else I returned an IPerspectiveAwareModel to hande drawing of the new model. The odd rotation from earlier doesn't effect the entityitem model, because it being an ISmartItemModel - though it still effects the first person / IPerspectiveAwareModel due to the Matrix4f - maybe you could ask RainWarrior why and see if he has a better way of grabbing the model's transform matricies. Anyway, thanks for all the help TGG, hope this topic helps others as well!

Development of Plugins [2012 - 2014] Development of Mods [2012 - Current]

Posted

Keen, nice work :) 

 

When I get a spare few hours I might try looking at IPerspectiveAware to see what the problem is.  Could be a bug perhaps.

 

-TGG

 

Thanks, TGG. If you figure out why the matricies are messed up and you know how to fix it, I would greatly appreciate it if you could show me how to fix it - refactoring model transforms in .JSON code is a pain when you've already done it beforehand and IPerspective messes it up. If it turns out to be a bug, maybe you could see to it getting fixed by Forge by reporting the bug - its really making the modeling system more work than it needs to be. Again, thanks!

Development of Plugins [2012 - 2014] Development of Mods [2012 - Current]

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.