Jump to content

Recommended Posts

Posted

Yes, that is exactly what I meant -- create scale fields and add the scaling before the actual rendering/calllist.

 

I'll probably add another constructor that passes the scale factors in at time of construction, but that is just a style thing.

 

I think the additional cool thing about this is that it will allow you to dynamically scale any piece parts without having to separate the model -- seems that would be useful for many interesting or improved animations (real animators actually squash and stretch their models quite a bit (i.e. imagine something jumping and landing).

 

The other thing I plan to do: for the actual Model class create a convertToChild() method to use instead of addChild().  Imagine if you could take the Techne output and not have to adjust the rotation points and rotations when making them into children.  The only trick is that in order to support multiple levels I think you have to crawl up the parent hierarchy to calculate the absolute values of the parent's rotation point and rotation angle.

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Posted

I skipped the constructor at first because I didn't look around to make sure nothing else was calling it.  There probably isn't, but the minecraft coders are an odd bunch.

 

However, nothing wrong with setting two constructors.

Long time Bukkit & Forge Programmer

Happy to try and help

Posted

Ok, I did some curvefitting, but can't figure out the basis for the value.

 

The formula is offset = 1.5 - (1.5 * shrink). 

 

I tested various values from 0.5 down to 0.25 and it works well. 

 

What I can't figure out is the 1.5.  Why is it that number?  Tried relating it to pixel size and the original height of the mob, but that didn't work.

Long time Bukkit & Forge Programmer

Happy to try and help

Posted

What I can't figure out is the 1.5.  Why is it that number?  Tried relating it to pixel size and the original height of the mob, but that didn't work.

 

I think I just figured it out -- the model 0, 0, 0 position is actually 24 pixels above ground (to prove this go to Techne and create a block at 0, 0, 0.  Since a block is 16 pixels, 24 would be 1.5 blocks high.

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Posted

You can use glScalef before rendering to change overall model size.

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

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

Posted

Abastro,

that is part of what we are talking about.  The discussion you are seeing now is how to get the feet to be on the ground again.  There is always the brute force way, but we were looking for an automatic way to do it so that the code scaled easily.

Long time Bukkit & Forge Programmer

Happy to try and help

Posted

Delpi, do you agree that the 1.5 probably is explained by the explanation I proposed?  (1.5 is due to 0, 0, 0 point of model being at 24 pixels above ground.)

 

The thing we need to think through is where this offset is in the order of the actual operations.  Does the scale happen around the 0, 0, 0 point of the model?  I kind of expect that it does not because otherwise the model wouldn't "move" so much when scaled.  So is the scaling actually happening around the point on the ground (1.5 down in Y direction)?

 

In other words, should you scale then translate, or translate then scale?  I've always just mucked around to correct the offset manually ...

 

What's your understanding?

 

I'm also wondering if doing the scaling in the preRenderCallback() behaves any differently.  It's possible (I haven't had time to trace the implementation) that that is called inside the translation.

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Posted

Agree on the basis of the 1.5.

 

The translate has to be before the scale.  I tried it the other way and the math is different.  Could proably figure it out but probably not worth it.  Can't think of a reason why would care which order it was in.

 

Haven't looked at the rendercallback at all yet.

Long time Bukkit & Forge Programmer

Happy to try and help

Posted

Can't think of a reason why would care which order it was in.

 

It matters because any point away from the origin of the scale will also get scaled.  If you have a model that is 1 pixel offset from the origin and call the scale for 2x, the model will then be 2 pixels away (in addition to being bigger).  If you want to scale something but keep it in its current postion you need to translate to origin of the scaling reference, scale, then translate back.  Otherwise the model's relative origin will move during the scaling.  Basically, scaling something that isn't at the origin of the scaling system will also cause translation.  Not sure if that was clear ...

 

Note that we have an additional problem to consider in our case -- we want the feet/base of our model to still touch the ground after the scaling.  So we can't just move the model back to original translation, but rather we need to do the scaled translation.  This is what you found in your formula -- i.e. you had to scale the second translation.

 

So what I think we need to do:

- original model starts at 1.5blocks above ground.

- need to move model down 1.5blocks such that origin is at the ground

- scale the model

- move the model up by 1.5*scaleFactor (since you're trying to get the feet of the scaled model back up to the ground level)

 

That is pretty much what you found out, and so I'm just explaining why it makes sense.  I think.

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Posted

You are right.  If you don't use the same center of 24 would cause issues, but could just change the 1.5 to what makes sense.

 

 

I'm not sure about that last line in the order.

 

I used the formula, scaled it, and things looked good.

 

On close inspection, the feet might have been slightly in the ground, but was very very slight.  When I get home tonight, i'll test if raising it by what you said fixes it.

Long time Bukkit & Forge Programmer

Happy to try and help

Posted

Then why you are trying to scale the each model, not just scale up the whole model?

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

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

Posted

I appreciate the interest, but if you would go back and read the chain from the start.  I don't think you have a complete picture yet.

 

I am scaling the entire entity and res positioning its feet on the ground.

 

I am scaling certain individual parts to avoid skin ripples.

Long time Bukkit & Forge Programmer

Happy to try and help

Posted

Here is my current version after all the discussion.  Works great.

 

 

 

@SideOnly(Side.CLIENT)

public class ModelRaptor extends ModelBase {

 

// Setup Tail angles

float tail_angle = 0.0F;

float tail_angle_incriment = 0.0005F;

float tail_angle_limit = 0.05F;

float tail_angle_growth = 0.2F;

int tail_angle_direction = 1;

 

// Setup Camo

boolean camo = false;

 

// Setup models

ModelRenderer head;

    ModelRenderer headb;

    ModelRenderer headuppera;

    ModelRenderer headupperb;

    MyModelRenderer headlowera;

    MyModelRenderer headlowerb;

    ModelRenderer tongue;

    ModelRenderer body;

    MyModelRenderer neck;

    ModelRenderer rightarm;

    ModelRenderer righthanda;

    ModelRenderer righthandb;

    ModelRenderer leftarm;

    ModelRenderer lefthanda;

    ModelRenderer lefthandb;

    ModelRenderer leftleg;

    MyModelRenderer leftlegb;

    ModelRenderer leftlegc;

    ModelRenderer leftfoottoe2b;

    ModelRenderer leftfoottoe1b;

    ModelRenderer leftfoottoe2a;

    ModelRenderer leftfoottoe1a;

    ModelRenderer leftfoot;

    ModelRenderer rightleg;

    MyModelRenderer rightlegb;

    ModelRenderer rightlegc;

    ModelRenderer rightfoottoe1a;

    ModelRenderer rightfoottoe2b;

    ModelRenderer rightfoottoe2a;

    ModelRenderer rightfoottoe1b;

    ModelRenderer rightfoot;

    ModelRenderer taila;

    ModelRenderer tailb;

    ModelRenderer tailc;

    ModelRenderer taild;

    ModelRenderer taile;

    ModelRenderer tooth1a;

    ModelRenderer tooth2a;

    ModelRenderer tooth1b;

    ModelRenderer tooth2b;

    ModelRenderer tooth1c;

    ModelRenderer tooth2c;

    ModelRenderer tooth1d;

    ModelRenderer tooth2d;

    ModelRenderer tooth1e;

    ModelRenderer tooth2e;

    ModelRenderer tooth1f;

    ModelRenderer tooth2f;

    ModelRenderer tooth1g;

    ModelRenderer tooth2g;

    ModelRenderer tooth1h;

    ModelRenderer tooth2h;

    ModelRenderer tooth1i;

    ModelRenderer tooth2i;

    ModelRenderer tooth1j;

    ModelRenderer tooth2j;

    ModelRenderer tooth1k;

    ModelRenderer tooth2k;

    ModelRenderer tooth1l;

    ModelRenderer tooth2l;

    ModelRenderer tooth1m;

    ModelRenderer tooth2m;

    ModelRenderer tooth1n;

    ModelRenderer tooth2n;

    ModelRenderer tooth1o;

    ModelRenderer tooth2o;

 

    public ModelRaptor() {

   

    textureWidth = 256;

        textureHeight = 256;

       

       

        // Head

       

        head = new ModelRenderer(this, 0, 0);

        head.addBox(-4F, -13F, -9F, 8, 7, 8);

        head.setRotationPoint(0F, 0F, -15F);

        head.setTextureSize(256, 256);

        head.mirror = true;

        setRotation(head, 0F, 0F, 0F);

       

        headb = new ModelRenderer(this, 40, 0);

        headb.addBox(-3F, -14F, -8F, 6, 1, 6);

        headb.setRotationPoint(0F, 0F, 0F);

        headb.setTextureSize(256, 256);

        headb.mirror = true;

        setRotation(headb, 0F, 0F, 0F);

        head.addChild(headb);

 

        neck = new MyModelRenderer(this, 50, 55);

        neck.addBox(-4F, -11F, -2F, 8, 12, 6);

        neck.setRotationPoint(0F, 0F, 0F);

        neck.setTextureSize(64, 32);

        neck.mirror = true;

        setRotation(neck, 0.4363323F, 0F, 0F);

        neck.MyScale(0.995F, 1.0F, 1.0F);

        head.addChild(neck);

       

       

        // Upper Jaw

       

        headuppera = new ModelRenderer(this, 0, 20);

        headuppera.addBox(-4F, -12F, -20F, 8, 1, 11);

        headuppera.setRotationPoint(0F, 0F, 0F);

        headuppera.setTextureSize(256, 256);

        headuppera.mirror = true;

        setRotation(headuppera, 0F, 0F, 0F);

        head.addChild(headuppera);

       

        headupperb = new ModelRenderer(this, 45, 20);

        headupperb.addBox(-4F, -11F, -21F, 8, 1, 12);

        headupperb.setRotationPoint(0F, 0F, 0F);

        headupperb.setTextureSize(256, 256);

        headupperb.mirror = true;

        setRotation(headupperb, 0F, 0F, 0F);

        headuppera.addChild(headupperb);

       

       

        // Lower Jaw       

        headlowera = new MyModelRenderer(this, 0, 35);

        headlowera.addBox(-4F, -9.5F, -19.2F, 8, 1, 12);

        headlowera.setRotationPoint(0F, 0F, 0F);

        headlowera.setTextureSize(256, 256);

        headlowera.mirror = true;

        setRotation(headlowera, 0.1919862F, 0F, 0F);

        headlowera.MyScale(0.995F, 1.0F, 1.0F);

        head.addChild(headlowera);

       

        headlowerb = new MyModelRenderer(this, 45, 35);

        headlowerb.addBox(-4F, -8.5F, -13.2F, 8, 1, 6);

        headlowerb.setRotationPoint(0F, 0, 0F);

        headlowerb.setTextureSize(256, 256);

        headlowerb.mirror = true;

        setRotation(headlowerb, 0.1919862F - headlowera.rotateAngleX, 0F, 0F);

        headlowera.addChild(headlowerb);

        headlowerb.MyScale(0.995F, 1.0F, 1.0F);

       

        tongue = new ModelRenderer(this, 80, 35);

        tongue.addBox(-2F, -9.7F, -17.2F, 4, 1, 10);

        tongue.setRotationPoint(0F, 0F, 0F);

        tongue.setTextureSize(256, 256);

        tongue.mirror = true;

        setRotation(tongue, 0.1919862F - headlowera.rotateAngleX, 0F, 0F);

        headlowera.addChild(tongue);

       

       

        // Body

       

        body = new ModelRenderer(this, 0, 55);

        body.addBox(-6F, -17F, -8F, 12, 21, 8);

        body.setRotationPoint(0F, 0F, 0F);

        body.setTextureSize(256, 256);

        body.mirror = true;

        setRotation(body, 1.308997F, 0F, 0F);     

       

        // Right Arm

       

        rightarm = new ModelRenderer(this, 150, 50);

        rightarm.addBox(-2F, -1F, -1F, 2, 12, 2);

        rightarm.setRotationPoint(-6F, 0F, -16F);

        rightarm.setTextureSize(256, 256);

        rightarm.mirror = true;

        setRotation(rightarm, -0.7853982F, 0F, 0F);

               

        righthanda = new ModelRenderer(this, 170, 50);

        righthanda.addBox(-4.5F, 9F, -0.5F, 1, 4, 1);

        righthanda.setRotationPoint(0F, 0F, 0F);

        righthanda.setTextureSize(256, 256);

        righthanda.mirror = true;

        setRotation(righthanda, degToRad(0), degToRad(6), degToRad(-21));

        rightarm.addChild(righthanda);

       

        righthandb = new ModelRenderer(this, 180, 50);

        righthandb.addBox(1.0F, 10F, 0F, 1, 4, 1);

        righthandb.setRotationPoint(0F, 0F, 0F);

        righthandb.setTextureSize(256, 256);

        righthandb.mirror = true;

        setRotation(righthandb, degToRad(0), degToRad(0), degToRad(16));

        rightarm.addChild(righthandb);

       

       

        // Left Arm

       

        leftarm = new ModelRenderer(this, 150, 80);

        leftarm.addBox(0F, -1F, -1F, 2, 12, 2);

        leftarm.setRotationPoint(6F, 0F, -16F);

        leftarm.setTextureSize(256, 256);

        leftarm.mirror = true;

        setRotation(leftarm, -0.7853982F, 0F, 0F);

       

        lefthanda = new ModelRenderer(this, 170, 80);

        lefthanda.addBox(3F, 9F, 0F, 1, 4, 1);

        lefthanda.setRotationPoint(0F, 0F, 0F);

        lefthanda.setTextureSize(256, 256);

        lefthanda.mirror = true;

        setRotation(lefthanda, degToRad(0), degToRad(0), degToRad(16));

        leftarm.addChild(lefthanda);

       

        lefthandb = new ModelRenderer(this, 180, 80);

        lefthandb.addBox(-3F, 10F, -0.5F, 1, 4, 1);

        lefthandb.setRotationPoint(0F, 0F, 0F);

        lefthandb.setTextureSize(256, 256);

        lefthandb.mirror = true;

        setRotation(lefthandb, degToRad(0), degToRad(6), degToRad(-21));

        leftarm.addChild(lefthandb);

       

       

        // Left Leg

       

        leftleg = new ModelRenderer(this, 0, 120);

        leftleg.addBox(-3F, -2F, -2.5F, 3, 7, 5);

        leftleg.setRotationPoint(-6F, 2F, -3F);

        leftleg.setTextureSize(256, 256);

        leftleg.mirror = true;

        setRotation(leftleg, 0F, 0F, 0F);

       

        leftlegb = new MyModelRenderer(this, 0, 140);

        leftlegb.addBox(-3F, 0F, -5F, 3, 15, 4);

        leftlegb.setRotationPoint(0F, 0F, 0F);

        leftlegb.setTextureSize(256, 256);

        leftlegb.mirror = true;

        setRotation(leftlegb, 1.134464F - leftleg.rotateAngleX, 0F, 0F);

        leftlegb.MyScale(0.995F, 1.0F, 1.0F);

        leftleg.addChild(leftlegb);

       

        leftlegc = new ModelRenderer(this, 0, 165);

        leftlegc.addBox(-3F, 2.1F, 12F, 3, 15, 3);

        leftlegc.setRotationPoint(0F, 0F, 0F);

        leftlegc.setTextureSize(256, 256);

        leftlegc.mirror = true;

        setRotation(leftlegc, -0.4363323F, 0F, 0F);

        leftleg.addChild(leftlegc);

       

        leftfoottoe2b = new ModelRenderer(this, 37, 175);

        leftfoottoe2b.addBox(-4F, 20F, 0F, 1, 2, 1);

        leftfoottoe2b.setRotationPoint(0F, 0F, 0F);

        leftfoottoe2b.setTextureSize(256, 256);

        leftfoottoe2b.mirror = true;

        setRotation(leftfoottoe2b, 0F, 0F, 0F);

        leftleg.addChild(leftfoottoe2b);

       

        leftfoottoe1b = new ModelRenderer(this, 37, 165);

        leftfoottoe1b.addBox(0F, 20F, -2F, 1, 2, 2);

        leftfoottoe1b.setRotationPoint(0F, 0F, 0F);

        leftfoottoe1b.setTextureSize(256, 256);

        leftfoottoe1b.mirror = true;

        setRotation(leftfoottoe1b, 0F, 0F, 0F);

        leftleg.addChild(leftfoottoe1b);

       

        leftfoottoe2a = new ModelRenderer(this, 20, 175);

        leftfoottoe2a.addBox(-5F, 20F, 1F, 3, 2, 3);

        leftfoottoe2a.setRotationPoint(0F, 0F, 0F);

        leftfoottoe2a.setTextureSize(256, 256);

        leftfoottoe2a.mirror = true;

        setRotation(leftfoottoe2a, 0F, 0F, 0F);

        leftleg.addChild(leftfoottoe2a);

       

        leftfoottoe1a = new ModelRenderer(this, 20, 165);

        leftfoottoe1a.addBox(-1F, 20F, 0F, 3, 2, 4);

        leftfoottoe1a.setRotationPoint(0F, 0F, 0F);

        leftfoottoe1a.setTextureSize(256, 256);

        leftfoottoe1a.mirror = true;

        setRotation(leftfoottoe1a, 0F, 0F, 0F);

        leftleg.addChild(leftfoottoe1a);

       

        leftfoot = new ModelRenderer(this, 20, 140);

        leftfoot.addBox(-5F, 20F, 4F, 7, 2, 3);

        leftfoot.setRotationPoint(0F, 0F, 0F);

        leftfoot.setTextureSize(256, 256);

        leftfoot.mirror = true;

        setRotation(leftfoot, 0F, 0F, 0F);

        leftleg.addChild(leftfoot);

       

       

        // Right Leg

       

        rightleg = new ModelRenderer(this, 50, 120);

        rightleg.addBox(0F, -2F, -2.5F, 3, 7, 5);

        rightleg.setRotationPoint(6F, 2F, -3F);

        rightleg.setTextureSize(256, 256);

        rightleg.mirror = true;

        setRotation(rightleg, 0F, 0F, 0F);

       

        rightlegb = new MyModelRenderer(this, 50, 140);

        rightlegb.addBox(0F, 0F, -5F, 3, 15, 4);

        rightlegb.setRotationPoint(0F, 0F, 0F);

        rightlegb.setTextureSize(256, 256);

        rightlegb.mirror = true;

        setRotation(rightlegb, 1.134464F - rightleg.rotateAngleX, 0F, 0F);

        rightlegb.MyScale(0.995F, 1.0F, 1.0F);

        rightleg.addChild(rightlegb);

       

        rightlegc = new ModelRenderer(this, 50, 165);

        rightlegc.addBox(0F, 2.1F, 12F, 3, 15, 3);

        rightlegc.setRotationPoint(0F, 0F, 0F);

        rightlegc.setTextureSize(256, 256);

        rightlegc.mirror = true;

        setRotation(rightlegc, -0.4363323F, 0F, 0F);

        rightleg.addChild(rightlegc);

       

        rightfoottoe1a = new ModelRenderer(this, 70, 165);

        rightfoottoe1a.addBox(-2F, 20F, 0F, 3, 2, 4);

        rightfoottoe1a.setRotationPoint(0F, 0F, 0F);

        rightfoottoe1a.setTextureSize(256, 256);

        rightfoottoe1a.mirror = true;

        setRotation(rightfoottoe1a, 0F, 0F, 0F);

        rightleg.addChild(rightfoottoe1a);

       

        rightfoottoe2b = new ModelRenderer(this, 87, 175);

        rightfoottoe2b.addBox(3F, 20F, 0F, 1, 2, 1);

        rightfoottoe2b.setRotationPoint(0F, 0F, 0F);

        rightfoottoe2b.setTextureSize(256, 256);

        rightfoottoe2b.mirror = true;

        setRotation(rightfoottoe2b, 0F, 0F, 0F);

        rightleg.addChild(rightfoottoe2b);

       

        rightfoottoe2a = new ModelRenderer(this, 70, 175);

        rightfoottoe2a.addBox(2F, 20F, 1F, 3, 2, 3);

        rightfoottoe2a.setRotationPoint(0F, 0F, 0F);

        rightfoottoe2a.setTextureSize(256, 256);

        rightfoottoe2a.mirror = true;

        setRotation(rightfoottoe2a, 0F, 0F, 0F);

        rightleg.addChild(rightfoottoe2a);

       

        rightfoottoe1b = new ModelRenderer(this, 87, 165);

        rightfoottoe1b.addBox(-1F, 20F, -2F, 1, 2, 2);

        rightfoottoe1b.setRotationPoint(0F, 0F, 0F);

        rightfoottoe1b.setTextureSize(256, 256);

        rightfoottoe1b.mirror = true;

        setRotation(rightfoottoe1b, 0F, 0F, 0F);

        rightleg.addChild(rightfoottoe1b);

       

        rightfoot = new ModelRenderer(this, 70, 140);

        rightfoot.addBox(-2F, 20F, 4F, 7, 2, 3);

        rightfoot.setRotationPoint(0F, 0F, 0F);

        rightfoot.setTextureSize(256, 256);

        rightfoot.mirror = true;

        setRotation(rightfoot, 0F, 0F, 0F);

        rightleg.addChild(rightfoot);

       

       

        // Tail

       

        taila = new ModelRenderer(this, 0, 95);

        taila.addBox(-5F, 2F, -8F, 10, 10, 7);

        taila.setRotationPoint(0F, 0F, 0F);

        taila.setTextureSize(256, 256);

        taila.mirror = true;

        setRotation(taila, 1.500983F - body.rotateAngleX, 0F, 0F);

        body.addChild(taila);

       

        tailb = new ModelRenderer(this, 40, 95);

        tailb.addBox(-4F, 11F, -7F, 8, 10, 5);

        tailb.setRotationPoint(0F, 0F, 0F);

        tailb.setTextureSize(256, 256);

        tailb.mirror = true;

        setRotation(tailb, 1.500983F - body.rotateAngleX, 0F, 0F);

        body.addChild(tailb);

       

        tailc = new ModelRenderer(this, 70, 95);

        tailc.addBox(-3F, 20F, -6F, 6, 10, 3);

        tailc.setRotationPoint(0F, 0F, 0F);

        tailc.setTextureSize(256, 256);

        tailc.mirror = true;

        setRotation(tailc, 1.500983F - body.rotateAngleX, 0F, 0F);

        body.addChild(tailc);

       

        taild = new ModelRenderer(this, 95, 95);

        taild.addBox(-2F, 29F, -5F, 4, 5, 1);

        taild.setRotationPoint(0F, 0F, 0F);

        taild.setTextureSize(256, 256);

        taild.mirror = true;

        setRotation(taild, 1.500983F - body.rotateAngleX, 0F, 0F);

        body.addChild(taild);

       

        taile = new ModelRenderer(this, 110, 95);

        taile.addBox(-1F, 33F, -5F, 2, 5, 1);

        taile.setRotationPoint(0F, 0F, 0F);

        taile.setTextureSize(256, 256);

        taile.mirror = true;

        setRotation(taile, 1.500983F - body.rotateAngleX, 0F, 0F);

        body.addChild(taile);

       

       

        // Lower Jaw Teeth

       

        tooth1a = new ModelRenderer(this, 250, 0);

        tooth1a.addBox(-3.9F, -19.5F, -8.1F, 1, 1, 1);

        tooth1a.setRotationPoint(0F, 0F, 0F);

        tooth1a.setTextureSize(256, 256);

        tooth1a.mirror = true;

        setRotation(tooth1a, 0.9075712F - headlowera.rotateAngleX, 0F, 0F);       

        headlowera.addChild(tooth1a);

       

        tooth2a = new ModelRenderer(this, 250, 0);

        tooth2a.addBox(2.9F, -19.5F, -8.1F, 1, 1, 1);

        tooth2a.setRotationPoint(0F, 0F, 0F);

        tooth2a.setTextureSize(256, 256);

        tooth2a.mirror = true;

        setRotation(tooth2a, 0.9075712F - headlowera.rotateAngleX, 0F - headlowera.rotateAngleY, 0F - headlowera.rotateAngleZ); 

        headlowera.addChild(tooth2a);

       

        tooth1b = new ModelRenderer(this, 250, 0);

        tooth1b.addBox(-3.9F, -18.6F, -7.1F, 1, 1, 1);

        tooth1b.setRotationPoint(0F, 0F, 0F);

        tooth1b.setTextureSize(256, 256);

        tooth1b.mirror = true;

        setRotation(tooth1b, 0.9075712F - headlowera.rotateAngleX, 0F - headlowera.rotateAngleY, 0F - headlowera.rotateAngleZ); 

        headlowera.addChild(tooth1b);

       

        tooth2b = new ModelRenderer(this, 250, 0);

        tooth2b.addBox(2.9F, -18.6F, -7.1F, 1, 1, 1);

        tooth2b.setRotationPoint(0F, 0F, 0F);

        tooth2b.setTextureSize(256, 256);

        tooth2b.mirror = true;

        setRotation(tooth2b, 0.9075712F - headlowera.rotateAngleX, 0F - headlowera.rotateAngleY, 0F - headlowera.rotateAngleZ); 

        headlowera.addChild(tooth2b);

       

        tooth1c = new ModelRenderer(this, 250, 0);

        tooth1c.addBox(-3.9F, -17.7F, -6.1F, 1, 1, 1);

        tooth1c.setRotationPoint(0F, 0F, 0F);

        tooth1c.setTextureSize(256, 256);

        tooth1c.mirror = true;

        setRotation(tooth1c, 0.9075712F - headlowera.rotateAngleX, 0F - headlowera.rotateAngleY, 0F - headlowera.rotateAngleZ); 

        headlowera.addChild(tooth1c);

       

        tooth2c = new ModelRenderer(this, 250, 0);

        tooth2c.addBox(2.9F, -17.7F, -6.1F, 1, 1, 1);

        tooth2c.setRotationPoint(0F, 0F, 0F);

        tooth2c.setTextureSize(256, 256);

        tooth2c.mirror = true;

        setRotation(tooth2c, 0.9075712F - headlowera.rotateAngleX, 0F - headlowera.rotateAngleY, 0F - headlowera.rotateAngleZ); 

        headlowera.addChild(tooth2c);

       

        tooth1d = new ModelRenderer(this, 250, 0);

        tooth1d.addBox(-3.9F, -16.8F, -5.1F, 1, 1, 1);

        tooth1d.setRotationPoint(0F, 0F, 0F);

        tooth1d.setTextureSize(256, 256);

        tooth1d.mirror = true;

        setRotation(tooth1d, 0.9075712F - headlowera.rotateAngleX, 0F - headlowera.rotateAngleY, 0F - headlowera.rotateAngleZ); 

        headlowera.addChild(tooth1d);

       

        tooth2d = new ModelRenderer(this, 250, 0);

        tooth2d.addBox(2.9F, -16.8F, -5.1F, 1, 1, 1);

        tooth2d.setRotationPoint(0F, 0F, 0F);

        tooth2d.setTextureSize(256, 256);

        tooth2d.mirror = true;

        setRotation(tooth2d, 0.9075712F - headlowera.rotateAngleX, 0F - headlowera.rotateAngleY, 0F - headlowera.rotateAngleZ); 

        headlowera.addChild(tooth2d);

       

        tooth1e = new ModelRenderer(this, 250, 0);

        tooth1e.addBox(-3.9F, -15.9F, -4.1F, 1, 1, 1);

        tooth1e.setRotationPoint(0F, 0F, 0F);

        tooth1e.setTextureSize(256, 256);

        tooth1e.mirror = true;

        setRotation(tooth1e, 0.9075712F - headlowera.rotateAngleX, 0F - headlowera.rotateAngleY, 0F - headlowera.rotateAngleZ); 

        headlowera.addChild(tooth1e);

       

        tooth2e = new ModelRenderer(this, 250, 0);

        tooth2e.addBox(2.9F, -15.9F, -4.1F, 1, 1, 1);

        tooth2e.setRotationPoint(0F, 0F, 0F);

        tooth2e.setTextureSize(256, 256);

        tooth2e.mirror = true;

        setRotation(tooth2e, 0.9075712F - headlowera.rotateAngleX, 0F - headlowera.rotateAngleY, 0F - headlowera.rotateAngleZ); 

        headlowera.addChild(tooth2e);

       

        tooth1f = new ModelRenderer(this, 250, 0);

        tooth1f.addBox(-3.9F, -15F, -3.1F, 1, 1, 1);

        tooth1f.setRotationPoint(0F, 0F, 0F);

        tooth1f.setTextureSize(256, 256);

        tooth1f.mirror = true;

        setRotation(tooth1f, 0.9075712F - headlowera.rotateAngleX, 0F - headlowera.rotateAngleY, 0F - headlowera.rotateAngleZ); 

        headlowera.addChild(tooth1f);

       

        tooth2f = new ModelRenderer(this, 250, 0);

        tooth2f.addBox(2.9F, -15F, -3.1F, 1, 1, 1);

        tooth2f.setRotationPoint(0F, 0F, 0F);

        tooth2f.setTextureSize(256, 256);

        tooth2f.mirror = true;

        setRotation(tooth2f, 0.9075712F - headlowera.rotateAngleX, 0F - headlowera.rotateAngleY, 0F - headlowera.rotateAngleZ); 

        headlowera.addChild(tooth2f);

       

        tooth1g = new ModelRenderer(this, 250, 0);

        tooth1g.addBox(-3.9F, -14.1F, -2.1F, 1, 1, 1);

        tooth1g.setRotationPoint(0F, 0F, 0F);

        tooth1g.setTextureSize(256, 256);

        tooth1g.mirror = true;

        setRotation(tooth1g, 0.9075712F - headlowera.rotateAngleX, 0F - headlowera.rotateAngleY, 0F - headlowera.rotateAngleZ); 

        headlowera.addChild(tooth1g);

       

        tooth2g = new ModelRenderer(this, 250, 0);

        tooth2g.addBox(2.9F, -14.1F, -2.1F, 1, 1, 1);

        tooth2g.setRotationPoint(0F, 0F, 0F);

        tooth2g.setTextureSize(256, 256);

        tooth2g.mirror = true;

        setRotation(tooth2g, 0.9075712F - headlowera.rotateAngleX, 0F - headlowera.rotateAngleY, 0F - headlowera.rotateAngleZ); 

        headlowera.addChild(tooth2g);

       

        tooth1h = new ModelRenderer(this, 250, 0);

        tooth1h.addBox(-3.9F, -13.2F, -1.1F, 1, 1, 1);

        tooth1h.setRotationPoint(0F, 0F, 0F);

        tooth1h.setTextureSize(256, 256);

        tooth1h.mirror = true;

        setRotation(tooth1h, 0.9075712F - headlowera.rotateAngleX, 0F - headlowera.rotateAngleY, 0F - headlowera.rotateAngleZ); 

        headlowera.addChild(tooth1h);

       

        tooth2h = new ModelRenderer(this, 250, 0);

        tooth2h.addBox(2.9F, -13.2F, -1.1F, 1, 1, 1);

        tooth2h.setRotationPoint(0F, 0F, 0F);

        tooth2h.setTextureSize(256, 256);

        tooth2h.mirror = true;

        setRotation(tooth2h, 0.9075712F - headlowera.rotateAngleX, 0F - headlowera.rotateAngleY, 0F - headlowera.rotateAngleZ); 

        headlowera.addChild(tooth2h);

       

       

        // Upper Jaw Teeth

       

        tooth1i = new ModelRenderer(this, 250, 0);

        tooth1i.addBox(-3.9F, -21.5F, -7.3F, 1, 1, 1);

        tooth1i.setRotationPoint(0F, 0F, 0F);

        tooth1i.setTextureSize(256, 256);

        tooth1i.mirror = true;

        setRotation(tooth1i, 0.7853982F, 0F, 0F);

        headuppera.addChild(tooth1i);

       

        tooth2i = new ModelRenderer(this, 250, 0);

        tooth2i.addBox(2.9F, -21.5F, -7.3F, 1, 1, 1);

        tooth2i.setRotationPoint(0F, 0F, 0F);

        tooth2i.setTextureSize(256, 256);

        tooth2i.mirror = true;

        setRotation(tooth2i, 0.7853982F, 0F, 0F);

        headuppera.addChild(tooth2i);

       

        tooth1j = new ModelRenderer(this, 250, 0);

        tooth1j.addBox(-3.9F, -20.5F, -6.3F, 1, 1, 1);

        tooth1j.setRotationPoint(0F, 0F, 0F);

        tooth1j.setTextureSize(256, 256);

        tooth1j.mirror = true;

        setRotation(tooth1j, 0.7853982F, 0F, 0F);

        headuppera.addChild(tooth1j);

       

        tooth2j = new ModelRenderer(this, 250, 0);

        tooth2j.addBox(2.9F, -20.5F, -6.3F, 1, 1, 1);

        tooth2j.setRotationPoint(0F, 0F, 0F);

        tooth2j.setTextureSize(256, 256);

        tooth2j.mirror = true;

        setRotation(tooth2j, 0.7853982F, 0F, 0F);

        headuppera.addChild(tooth2j);

       

        tooth1k = new ModelRenderer(this, 250, 0);

        tooth1k.addBox(-3.9F, -19.5F, -5.3F, 1, 1, 1);

        tooth1k.setRotationPoint(0F, 0F, 0F);

        tooth1k.setTextureSize(256, 256);

        tooth1k.mirror = true;

        setRotation(tooth1k, 0.7853982F, 0F, 0F);

        headuppera.addChild(tooth1k);

       

        tooth2k = new ModelRenderer(this, 250, 0);

        tooth2k.addBox(2.9F, -19.5F, -5.3F, 1, 1, 1);

        tooth2k.setRotationPoint(0F, 0F, 0F);

        tooth2k.setTextureSize(256, 256);

        tooth2k.mirror = true;

        setRotation(tooth2k, 0.7853982F, 0F, 0F);

        headuppera.addChild(tooth2k);

       

        tooth1l = new ModelRenderer(this, 250, 0);

        tooth1l.addBox(-3.9F, -18.5F, -4.3F, 1, 1, 1);

        tooth1l.setRotationPoint(0F, 0F, 0F);

        tooth1l.setTextureSize(256, 256);

        tooth1l.mirror = true;

        setRotation(tooth1l, 0.7853982F, 0F, 0F);

        headuppera.addChild(tooth1l);

       

        tooth2l = new ModelRenderer(this, 250, 0);

        tooth2l.addBox(2.9F, -18.5F, -4.3F, 1, 1, 1);

        tooth2l.setRotationPoint(0F, 0F, 0F);

        tooth2l.setTextureSize(256, 256);

        tooth2l.mirror = true;

        setRotation(tooth2l, 0.7853982F, 0F, 0F);

        headuppera.addChild(tooth2l);

       

        tooth1m = new ModelRenderer(this, 250, 0);

        tooth1m.addBox(-3.9F, -17.5F, -3.3F, 1, 1, 1);

        tooth1m.setRotationPoint(0F, 0F, 0F);

        tooth1m.setTextureSize(256, 256);

        tooth1m.mirror = true;

        setRotation(tooth1m, 0.7853982F, 0F, 0F);

        headuppera.addChild(tooth1m);

       

        tooth2m = new ModelRenderer(this, 250, 0);

        tooth2m.addBox(2.9F, -17.5F, -3.3F, 1, 1, 1);

        tooth2m.setRotationPoint(0F, 0F, 0F);

        tooth2m.setTextureSize(256, 256);

        tooth2m.mirror = true;

        setRotation(tooth2m, 0.7853982F, 0F, 0F);

        headuppera.addChild(tooth2m);

       

        tooth1n = new ModelRenderer(this, 250, 0);

        tooth1n.addBox(-3.9F, -16.5F, -2.3F, 1, 1, 1);

        tooth1n.setRotationPoint(0F, 0F, 0F);

        tooth1n.setTextureSize(256, 256);

        tooth1n.mirror = true;

        setRotation(tooth1n, 0.7853982F, 0F, 0F);

        headuppera.addChild(tooth1n);

       

        tooth2n = new ModelRenderer(this, 250, 0);

        tooth2n.addBox(2.9F, -16.5F, -2.3F, 1, 1, 1);

        tooth2n.setRotationPoint(0F, 0F, 0F);

        tooth2n.setTextureSize(256, 256);

        tooth2n.mirror = true;

        setRotation(tooth2n, 0.7853982F, 0F, 0F);

        headuppera.addChild(tooth2n);

       

        tooth1o = new ModelRenderer(this, 250, 0);

        tooth1o.addBox(-3.9F, -15.5F, -1.3F, 1, 1, 1);

        tooth1o.setRotationPoint(0F, 0F, 0F);

        tooth1o.setTextureSize(256, 256);

        tooth1o.mirror = true;

        setRotation(tooth1o, 0.7853982F, 0F, 0F);

        headuppera.addChild(tooth1o);

       

        tooth2o = new ModelRenderer(this, 250, 0);

        tooth2o.addBox(2.9F, -15.5F, -1.3F, 1, 1, 1);

        tooth2o.setRotationPoint(0F, 0F, 0F);

        tooth2o.setTextureSize(256, 256);

        tooth2o.mirror = true;

        setRotation(tooth2o, 0.7853982F, 0F, 0F);

        headuppera.addChild(tooth2o);

       

    }

 

    public void setRotation(ModelRenderer model, float x, float y, float z) {

   

        model.rotateAngleX = x;

        model.rotateAngleY = y;

        model.rotateAngleZ = z;

       

    }

 

    // f & f1 are some type of limb movement factors

   

    @Override

    public void setRotationAngles(float limb_angle, float limb_progress, float f2, float headY, float headX, float f5, Entity entity) {

        super.setRotationAngles(limb_angle, limb_progress, f2, headY, headX, f5, entity);

       

        // Handle Head Rotation

        head.rotateAngleY = headY / (180F / (float)Math.PI);

        head.rotateAngleX = headX / (180F / (float)Math.PI);

       

        // Handle Walking Animation

        float limb_angle_multiplier = 0.6662F;  // 0.6662F Original

        float limb_rotation_multiplier = 0.7F;  // 1.4F Original

             

        leftleg.rotateAngleX = MathHelper.cos(limb_angle * limb_angle_multiplier) * limb_rotation_multiplier * limb_progress;

        rightleg.rotateAngleX = MathHelper.cos(limb_angle * limb_angle_multiplier + (float)Math.PI) * limb_rotation_multiplier * limb_progress;

     

        // Handle Tail Wag Animation

        tail_angle = tail_angle  + tail_angle_incriment * tail_angle_direction;

        if (tail_angle >= tail_angle_limit) tail_angle_direction = -1;

        if (tail_angle <= (-tail_angle_limit)) tail_angle_direction = 1;

        //System.out.println("tail_angle of " + tail_angle);

       

        // Handle Jaw

        MyEntityRaptor raptor = (MyEntityRaptor) entity;

        float jaw_position = raptor.jaw_position();

       

        // Handle Tail Rotations

        taila.rotateAngleZ = body.rotateAngleZ + tail_angle * (1 + 0 * tail_angle_growth);

        tailb.rotateAngleZ = body.rotateAngleZ + tail_angle * (1 + 1 * tail_angle_growth);

        tailc.rotateAngleZ = body.rotateAngleZ + tail_angle * (1 + 2 * tail_angle_growth);

        taild.rotateAngleZ = body.rotateAngleZ + tail_angle * (1 + 3 * tail_angle_growth);

        taile.rotateAngleZ = body.rotateAngleZ + tail_angle * (1 + 4 * tail_angle_growth);

       

    }

   

    @Override

    public void render(Entity entity, float par2, float par3, float par4, float par5, float par6, float par7) {

   

    // Setup raptor

    MyEntityRaptor raptor = (MyEntityRaptor) entity;

   

    // Set Rotation

        this.setRotationAngles(par2, par3, par4, par5, par6, par7, entity);

       

        // Setup factors - can't just adjust this

        float shrink_factor = 2.0f;

       

        // Check for Child

        if (raptor.isChild()) shrink_factor = 3.0f;

 

        // Calculate Offset

        float shift_y = (24F /16F) - (1F / shrink_factor * 1.5F);

       

        // Initiate Matrix

        GL11.glPushMatrix();

       

        // Move the entity for the scale

        GL11.glTranslatef(0.0F, shift_y, 0.0F);

       

        // Set Scale       

        GL11.glScalef(1.0F / shrink_factor, 1.0F / shrink_factor, 1.0F / shrink_factor);

       

        // Render the Raptor

        this.head.render(par7);

 

        this.body.render(par7);

       

        this.leftarm.render(par7);

       

        this.rightarm.render(par7);

 

        this.leftleg.render(par7);

 

        this.rightleg.render(par7);

               

        // Finish Matrix

        GL11.glPopMatrix();

 

    }

   

    protected float degToRad(float degrees) {

   

        return degrees * (float)Math.PI / 180 ;

       

    }

   

}

 

 

 

Custom ModelRenderer

 

 

public class MyModelRenderer extends ModelRenderer {

 

// Setup Variables

  protected float MyScaleX = 1;

  protected float MyScaleY = 1;

  protected float MyScaleZ = 1;

 

  // Handle repeat variables

  protected int displayList;

  protected boolean compiled;

 

 

  public MyModelRenderer(ModelBase par1ModelBase, String par2Str) {

      super(par1ModelBase, par2Str);

       

  }

 

  public MyModelRenderer(ModelBase par1ModelBase) {

      super(par1ModelBase, null);

       

  }

 

  public MyModelRenderer(ModelBase par1ModelBase, int par2, int par3) { 

      this(par1ModelBase);

      this.setTextureOffset(par2, par3);

     

  }

 

  public void MyScale(float MyScaleX, float MyScaleY, float MyScaleZ) {

 

      // Set Variables

      this.MyScaleX = MyScaleX;

      this.MyScaleY = MyScaleY;

      this.MyScaleZ = MyScaleZ;

 

  }  

 

  protected void customCallList() {

 

      // Scale the render

      GL11.glScalef(1 * MyScaleX, 1 * MyScaleY, 1 * MyScaleZ);

     

      // Make the display call

      GL11.glCallList(this.displayList);

 

      // Remove the scale

      GL11.glScalef(1 / MyScaleX, 1 / MyScaleY, 1 / MyScaleZ);

     

  }

 

  @SideOnly(Side.CLIENT)

  private void compileDisplayList(float par1) {

 

      this.displayList = GLAllocation.generateDisplayLists(1);

      GL11.glNewList(this.displayList, GL11.GL_COMPILE);

      Tessellator tessellator = Tessellator.instance;

 

      for (int i = 0; i < this.cubeList.size(); ++i)

      {

          ((ModelBox)this.cubeList.get(i)).render(tessellator, par1);

      }

 

      GL11.glEndList();

      this.compiled = true;

     

  }

 

    @SideOnly(Side.CLIENT)

  @Override

    public void render(float par1)

    {

        if (!this.isHidden)

        {

            if (this.showModel)

            {

                if (!this.compiled)

                {

                    this.compileDisplayList(par1);

                }

 

                GL11.glTranslatef(this.offsetX, this.offsetY, this.offsetZ);

                int i;

 

                if (this.rotateAngleX == 0.0F && this.rotateAngleY == 0.0F && this.rotateAngleZ == 0.0F)

                {

                    if (this.rotationPointX == 0.0F && this.rotationPointY == 0.0F && this.rotationPointZ == 0.0F)

                    {

                        //GL11.glCallList(this.displayList);

                  customCallList();

 

                        if (this.childModels != null)

                        {

                            for (i = 0; i < this.childModels.size(); ++i)

                            {

                                ((ModelRenderer)this.childModels.get(i)).render(par1);

                            }

                        }

                    }

                    else

                    {

                        GL11.glTranslatef(this.rotationPointX * par1, this.rotationPointY * par1, this.rotationPointZ * par1);

                        //GL11.glCallList(this.displayList);

                  customCallList();

 

                        if (this.childModels != null)

                        {

                            for (i = 0; i < this.childModels.size(); ++i)

                            {

                                ((ModelRenderer)this.childModels.get(i)).render(par1);

                            }

                        }

 

                        GL11.glTranslatef(-this.rotationPointX * par1, -this.rotationPointY * par1, -this.rotationPointZ * par1);

                    }

                }

                else

                {

                    GL11.glPushMatrix();

                    GL11.glTranslatef(this.rotationPointX * par1, this.rotationPointY * par1, this.rotationPointZ * par1);

 

                    if (this.rotateAngleZ != 0.0F)

                    {

                        GL11.glRotatef(this.rotateAngleZ * (180F / (float)Math.PI), 0.0F, 0.0F, 1.0F);

                    }

 

                    if (this.rotateAngleY != 0.0F)

                    {

                        GL11.glRotatef(this.rotateAngleY * (180F / (float)Math.PI), 0.0F, 1.0F, 0.0F);

                    }

 

                    if (this.rotateAngleX != 0.0F)

                    {

                        GL11.glRotatef(this.rotateAngleX * (180F / (float)Math.PI), 1.0F, 0.0F, 0.0F);

                    }

 

                    //GL11.glCallList(this.displayList);

              customCallList();

 

                    if (this.childModels != null)

                    {

                        for (i = 0; i < this.childModels.size(); ++i)

                        {

                            ((ModelRenderer)this.childModels.get(i)).render(par1);

                        }

                    }

 

                    GL11.glPopMatrix();

                }

 

                GL11.glTranslatef(-this.offsetX, -this.offsetY, -this.offsetZ);

            }

        }

    }

 

  @SideOnly(Side.CLIENT)

  @Override

    public void renderWithRotation(float par1)

    {

        if (!this.isHidden)

        {

            if (this.showModel)

            {

                if (!this.compiled)

                {

                    this.compileDisplayList(par1);

                }

 

                GL11.glPushMatrix();

                GL11.glTranslatef(this.rotationPointX * par1, this.rotationPointY * par1, this.rotationPointZ * par1);

 

                if (this.rotateAngleY != 0.0F)

                {

                    GL11.glRotatef(this.rotateAngleY * (180F / (float)Math.PI), 0.0F, 1.0F, 0.0F);

                }

 

                if (this.rotateAngleX != 0.0F)

                {

                    GL11.glRotatef(this.rotateAngleX * (180F / (float)Math.PI), 1.0F, 0.0F, 0.0F);

                }

 

                if (this.rotateAngleZ != 0.0F)

                {

                    GL11.glRotatef(this.rotateAngleZ * (180F / (float)Math.PI), 0.0F, 0.0F, 1.0F);

                }

 

                //GL11.glCallList(this.displayList);

            customCallList();

                GL11.glPopMatrix();

            }

        }

    }

 

}

 

Long time Bukkit & Forge Programmer

Happy to try and help

Posted

Awesome.  I suggest that the setRotation() method be converted to use degrees as well (just takes a few minutes to update all the calls) -- as always just trying to protect your sanity!

 

I'm not sure about that last line in the order.  I used the formula, scaled it, and things looked good.

 

A formula is a series of steps - I was just using the concept of steps to explain why your formula should work.

 

In other words, your formula of: 1.5 - (1.5 * shrink) is exactly equivalent to me saying "take the steps to translate 1.5 then translate back by 1.5 times the scale factor."

 

It is great to have figured this out together.  I think now you can understand the powerful animation possibilities once you have the rotation points and hierarchy in proper place.

 

The only thing I still want to work on is to make the convertToChild() method so I can just take a Techne Java output as is and directly create the hierarchy without having to think much.  It should be pretty easy, provided you put the rotation points in the proper places in the Techne model.

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Posted

Yeh, that would make it a lot easier to have that method.

 

The one thing that I think will be really hard is the math for a child that is rotated.  Took some thinking to figure out the pattern of the teeth to the parent or the fingers to the hands.

Long time Bukkit & Forge Programmer

Happy to try and help

Posted

Yeh, that would make it a lot easier to have that method.

 

The one thing that I think will be really hard is the math for a child that is rotated.  Took some thinking to figure out the pattern of the teeth to the parent or the fingers to the hands.

 

No, there shouldn't be any math.  I haven't looked at your model class yet, but I suspect you didn't entirely adjust all the rotation points properly.  The rotation points should be at the point of connection between the parts (in most cases).  So for the teeth it could be the center of each tooth, and then each tooth is attached at different point to the jaw.

 

If in Techne you already put those rotation points in proper place, there shouldn't be any issue.  They were all just rotated 45degrees, and it doesn't matter whether the jaw is also rotated relative to the head and the head is relative to the neck and the neck relative to the body and the body relative to the world -- shouldn't be any math except to set rotation to 45degrees.

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Posted

I missed something big here.

 

I set the rotation point for the tooth at 0,0,0 to be the same as its parent.  This of course made it so the axis's were not typical so it was rather complicated to get it in place.

 

If I read what you are saying and thinking back to the rest of the conversation, I set the rotation point to the center of the tooth relative to the rotation point of the parent object.  Because it is a child, it will rotate with the parent just fine.  If I tell the tooth to rotate after that for animation, it will rotate on its own point?

 

Did I get that right?  I hope so, because what I did was a PITA!

 

 

I can't play with it till tonight, but let be let me know if that is the right understanding or if I still have it wrong.

Long time Bukkit & Forge Programmer

Happy to try and help

Posted

People run into trouble because the placement can look correct even if the rotation point is wrong.  This is because the offsets can hide the problem.  I just made a quick vid (

) to show you this -- I move the rotation point and offset of the arm and the arm still seems to be in correct place -- but you can see the problem when you try to rotate it.  This is what you've done with the teeth.

 

The child will automatically rotate around the parent's rotation point.  You don't need to align the child and parents rotation points in any way (you only have to align them if you don't have hierarchy).  Any further rotation on the child itself will be around its own rotation point

 

This is only really critical for child pieces you plan to dynamically rotate.  If you've already figured out a combination of rotation points, offsets and rotations for the teeth that work, I would just leave them.    But for anything that will move dynamically (legs, tail, etc.) you need to ensure you get it right.

 

In my tutorial, I recommend adding spinX(), spinY() and spinZ() function to use for debugging.  You can call this right before the render and can pass a child piece to it.  The child piece will then rotate and you will quickly understand whether the rotation point is correct.

 

    // spin methods are good for testing and debug rotation points and offsets in the model
    protected void spinX(ModelRenderer model)
    {
        model.rotateAngleX += degToRad(0.5F);
    }
    
    protected void spinY(ModelRenderer model)
    {
        model.rotateAngleY += degToRad(0.5F);
    }
    
    protected void spinZ(ModelRenderer model)
    {
        model.rotateAngleZ += degToRad(0.5F);
    }

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Posted

Okay, while I do want people to understand the concepts, I've come up with the (simple) convertToChild() method that will make taking the Techne Java output and creating hierarchy extremely easy.

 

The important thing is to first in Techne get the rotation points in right place (see the video I linked above).  Then export the Java and put it into your custom model class in Eclipse.

 

Then add the following method to your model class:

    // This is really useful for converting the source from a Techne model export
    // which will have absolute rotation points that need to be converted before
    // creating the addChild() relationship
    protected void convertToChild(ModelRenderer parParent, ModelRenderer parChild)
    {
    	// move child rotation point to be relative to parent
    	parChild.rotationPointX -= parParent.rotationPointX;
    	parChild.rotationPointY -= parParent.rotationPointY;
    	parChild.rotationPointZ -= parParent.rotationPointZ;
    	// make rotations relative to parent
    	parChild.rotateAngleX -= parParent.rotateAngleX;
    	parChild.rotateAngleY -= parParent.rotateAngleY;
    	parChild.rotateAngleZ -= parParent.rotateAngleZ;
    	// create relationship
    	parParent.addChild(parChild);
    }

 

Then call this method to create the hierarchy.  For example, I took the Techne default ModelBiped and output the Java then added this method, with the result being:

      head = new ModelRenderer(this, 0, 0);
      head.addBox(-4F, -8F, -4F, 8, 8, ;
      head.setRotationPoint(0F, 0F, 0F);
      head.setTextureSize(64, 32);
      head.mirror = true;
      setRotation(head, 0F, 0F, 0F);
      body = new ModelRenderer(this, 16, 16);
      body.addBox(-4F, 0F, -2F, 8, 12, 4);
      body.setRotationPoint(0F, 0F, 0F);
      body.setTextureSize(64, 32);
      body.mirror = true;
      setRotation(body, 0F, 0F, 0F);
      [color=blue]convertToChild(body, head);[/color]
      rightarm = new ModelRenderer(this, 40, 16);
      rightarm.addBox(-3F, -2F, -2F, 4, 12, 4);
      rightarm.setRotationPoint(-5F, 2F, 0F);
      rightarm.setTextureSize(64, 32);
      rightarm.mirror = true;
      setRotation(rightarm, 0F, 0F, 0F);
      [color=blue]convertToChild(body, rightarm);[/color]
      leftarm = new ModelRenderer(this, 40, 16);
      leftarm.addBox(-1F, -2F, -2F, 4, 12, 4);
      leftarm.setRotationPoint(5F, 2F, 0F);
      leftarm.setTextureSize(64, 32);
      leftarm.mirror = true;
      setRotation(leftarm, 0F, 0F, 0F);
      [color=blue]convertToChild(body, leftarm);[/color]
      rightleg = new ModelRenderer(this, 0, 16);
      rightleg.addBox(-2F, 0F, -2F, 4, 12, 4);
      rightleg.setRotationPoint(-2F, 12F, 0F);
      rightleg.setTextureSize(64, 32);
      rightleg.mirror = true;
      setRotation(rightleg, 0F, 0F, 0F);
      [color=blue]convertToChild(body, rightleg);[/color]
      leftleg = new ModelRenderer(this, 0, 16);
      leftleg.addBox(-2F, 0F, -2F, 4, 12, 4);
      leftleg.setRotationPoint(2F, 12F, 0F);
      leftleg.setTextureSize(64, 32);
      leftleg.mirror = true;
      setRotation(leftleg, 0F, 0F, 0F);
      [color=blue]convertToChild(body, leftleg);[/color]

 

Lastly, I got rid of the render calls for each child, and only called body.render(f5).

 

Hope this helps.  If you're getting tired of reworking your model, feel free to send me the Techne file and I'll be able to get it going pretty quickly.

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Posted

I'm going to keep messing with it.  Learning a lot which will help with some future ideas I have.

 

When I get home tonight, I'll play with the model and Tecne more. 

 

After that, I'll post th code.  If you don't mind, I'd appreciate you taking a look at it and seeing if anything else jumps out at you.

Long time Bukkit & Forge Programmer

Happy to try and help

Posted

I'm going to keep messing with it.  Learning a lot which will help with some future ideas I have.

 

When I get home tonight, I'll play with the model and Tecne more. 

 

After that, I'll post th code.  If you don't mind, I'd appreciate you taking a look at it and seeing if anything else jumps out at you.

 

Yes, it is worth understanding inside and out.

 

The only problem for you is you made a complicated model before fully understanding it, now the rework is extensive.  I was trying to fix just the teeth and it is a lot of work, after about half an hour on it I was only halfway there.

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Posted

Hit a snag.  If your parent is rotated, things seem to get weird with the child setup.

Long time Bukkit & Forge Programmer

Happy to try and help

Posted

Got a workaround.  Your base parent can't be rotated or the child doesn't position right.  I created some dummy parts that were not rotated with dimensions of 0,0,0 and it fixed it.

 

Next issue is order that the convertToChild is run.

 

For example, if headb is a child of head is a child of neckbase.

 

You have to run convert on headb before you run it on head or it has already subracted the angles and positions and things get weird.

 

Any ideas?

Long time Bukkit & Forge Programmer

Happy to try and help

Posted

Got a workaround.  Your base parent can't be rotated or the child doesn't position right.  I created some dummy parts that were not rotated with dimensions of 0,0,0 and it fixed it.

 

Next issue is order that the convertToChild is run.

 

For example, if headb is a child of head is a child of neckbase.

 

You have to run convert on headb before you run it on head or it has already subracted the angles and positions and things get weird.

 

Any ideas?

 

Yeah, I was a bit worried about that part (converting multiple levels).  I think we'll have to keep track of the previous absolute position for each child as well.  Probably easiest to add that as fields in an extended ModelRenderer class, but could also just be some sort of array in the Model class.  So the convertToChild() would look at the parent's originalRotationPointX, originalRotationPointY, originalRotationPointZ for the purpose of the conversion.  That should solve it, right?

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Posted

So far just keeping track of the order seems to be working.  It means I put the convertToChild all together at the end.  Not that bad.

Long time Bukkit & Forge Programmer

Happy to try and help

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



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • Version 1.19 - Forge 41.0.63 I want to create a wolf entity that I can ride, so far it seems to be working, but the problem is that when I get on the wolf, I can’t control it. I then discovered that the issue is that the server doesn’t detect that I’m riding the wolf, so I’m struggling with synchronization. However, it seems to not be working properly. As I understand it, the server receives the packet but doesn’t register it correctly. I’m a bit new to Java, and I’ll try to provide all the relevant code and prints *The comments and prints are translated by chatgpt since they were originally in Spanish* Thank you very much in advance No player is mounted, or the passenger is not a player. No player is mounted, or the passenger is not a player. No player is mounted, or the passenger is not a player. No player is mounted, or the passenger is not a player. No player is mounted, or the passenger is not a player. MountableWolfEntity package com.vals.valscraft.entity; import com.vals.valscraft.network.MountSyncPacket; import com.vals.valscraft.network.NetworkHandler; import net.minecraft.client.Minecraft; import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.network.syncher.SynchedEntityData; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.ai.attributes.AttributeSupplier; import net.minecraft.world.entity.ai.attributes.Attributes; import net.minecraft.world.entity.animal.Wolf; import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.Entity; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec3; import net.minecraftforge.event.TickEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.network.PacketDistributor; public class MountableWolfEntity extends Wolf { private boolean hasSaddle; private static final EntityDataAccessor<Byte> DATA_ID_FLAGS = SynchedEntityData.defineId(MountableWolfEntity.class, EntityDataSerializers.BYTE); public MountableWolfEntity(EntityType<? extends Wolf> type, Level level) { super(type, level); this.hasSaddle = false; } @Override protected void defineSynchedData() { super.defineSynchedData(); this.entityData.define(DATA_ID_FLAGS, (byte)0); } public static AttributeSupplier.Builder createAttributes() { return Wolf.createAttributes() .add(Attributes.MAX_HEALTH, 20.0) .add(Attributes.MOVEMENT_SPEED, 0.3); } @Override public InteractionResult mobInteract(Player player, InteractionHand hand) { ItemStack itemstack = player.getItemInHand(hand); if (itemstack.getItem() == Items.SADDLE && !this.hasSaddle()) { if (!player.isCreative()) { itemstack.shrink(1); } this.setSaddle(true); return InteractionResult.SUCCESS; } else if (!level.isClientSide && this.hasSaddle()) { player.startRiding(this); MountSyncPacket packet = new MountSyncPacket(true); // 'true' means the player is mounted NetworkHandler.CHANNEL.sendToServer(packet); // Ensure the server handles the packet return InteractionResult.SUCCESS; } return InteractionResult.PASS; } @Override public void travel(Vec3 travelVector) { if (this.isVehicle() && this.getControllingPassenger() instanceof Player) { System.out.println("The wolf has a passenger."); System.out.println("The passenger is a player."); Player player = (Player) this.getControllingPassenger(); // Ensure the player is the controller this.setYRot(player.getYRot()); this.yRotO = this.getYRot(); this.setXRot(player.getXRot() * 0.5F); this.setRot(this.getYRot(), this.getXRot()); this.yBodyRot = this.getYRot(); this.yHeadRot = this.yBodyRot; float forward = player.zza; float strafe = player.xxa; if (forward <= 0.0F) { forward *= 0.25F; } this.flyingSpeed = this.getSpeed() * 0.1F; this.setSpeed((float) this.getAttributeValue(Attributes.MOVEMENT_SPEED) * 1.5F); this.setDeltaMovement(new Vec3(strafe, travelVector.y, forward).scale(this.getSpeed())); this.calculateEntityAnimation(this, false); } else { // The wolf does not have a passenger or the passenger is not a player System.out.println("No player is mounted, or the passenger is not a player."); super.travel(travelVector); } } public boolean hasSaddle() { return this.hasSaddle; } public void setSaddle(boolean hasSaddle) { this.hasSaddle = hasSaddle; } @Override protected void dropEquipment() { super.dropEquipment(); if (this.hasSaddle()) { this.spawnAtLocation(Items.SADDLE); this.setSaddle(false); } } @SubscribeEvent public static void onServerTick(TickEvent.ServerTickEvent event) { if (event.phase == TickEvent.Phase.START) { MinecraftServer server = net.minecraftforge.server.ServerLifecycleHooks.getCurrentServer(); if (server != null) { for (ServerPlayer player : server.getPlayerList().getPlayers()) { if (player.isPassenger() && player.getVehicle() instanceof MountableWolfEntity) { MountableWolfEntity wolf = (MountableWolfEntity) player.getVehicle(); System.out.println("Tick: " + player.getName().getString() + " is correctly mounted on " + wolf); } } } } } private boolean lastMountedState = false; @Override public void tick() { super.tick(); if (!this.level.isClientSide) { // Only on the server boolean isMounted = this.isVehicle() && this.getControllingPassenger() instanceof Player; // Only print if the state changed if (isMounted != lastMountedState) { if (isMounted) { Player player = (Player) this.getControllingPassenger(); // Verify the passenger is a player System.out.println("Server: Player " + player.getName().getString() + " is now mounted."); } else { System.out.println("Server: The wolf no longer has a passenger."); } lastMountedState = isMounted; } } } @Override public void addPassenger(Entity passenger) { super.addPassenger(passenger); if (passenger instanceof Player) { Player player = (Player) passenger; if (!this.level.isClientSide && player instanceof ServerPlayer) { // Send the packet to the server to indicate the player is mounted NetworkHandler.CHANNEL.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) player), new MountSyncPacket(true)); } } } @Override public void removePassenger(Entity passenger) { super.removePassenger(passenger); if (passenger instanceof Player) { Player player = (Player) passenger; if (!this.level.isClientSide && player instanceof ServerPlayer) { // Send the packet to the server to indicate the player is no longer mounted NetworkHandler.CHANNEL.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) player), new MountSyncPacket(false)); } } } @Override public boolean isControlledByLocalInstance() { Entity entity = this.getControllingPassenger(); return entity instanceof Player; } @Override public void positionRider(Entity passenger) { if (this.hasPassenger(passenger)) { double xOffset = Math.cos(Math.toRadians(this.getYRot() + 90)) * 0.4; double zOffset = Math.sin(Math.toRadians(this.getYRot() + 90)) * 0.4; passenger.setPos(this.getX() + xOffset, this.getY() + this.getPassengersRidingOffset() + passenger.getMyRidingOffset(), this.getZ() + zOffset); } } } MountSyncPacket package com.vals.valscraft.network; import com.vals.valscraft.entity.MountableWolfEntity; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; import net.minecraftforge.network.NetworkEvent; import java.util.function.Supplier; public class MountSyncPacket { private final boolean isMounted; public MountSyncPacket(boolean isMounted) { this.isMounted = isMounted; } public void encode(FriendlyByteBuf buffer) { buffer.writeBoolean(isMounted); } public static MountSyncPacket decode(FriendlyByteBuf buffer) { return new MountSyncPacket(buffer.readBoolean()); } public void handle(NetworkEvent.Context context) { context.enqueueWork(() -> { ServerPlayer player = context.getSender(); // Get the player from the context if (player != null) { // Verifies if the player has dismounted if (!isMounted) { Entity vehicle = player.getVehicle(); if (vehicle instanceof MountableWolfEntity wolf) { // Logic to remove the player as a passenger wolf.removePassenger(player); System.out.println("Server: Player " + player.getName().getString() + " is no longer mounted."); } } } }); context.setPacketHandled(true); // Marks the packet as handled } } networkHandler package com.vals.valscraft.network; import com.vals.valscraft.valscraft; import net.minecraft.resources.ResourceLocation; import net.minecraftforge.network.NetworkRegistry; import net.minecraftforge.network.simple.SimpleChannel; import net.minecraftforge.network.NetworkEvent; import java.util.function.Supplier; public class NetworkHandler { private static final String PROTOCOL_VERSION = "1"; public static final SimpleChannel CHANNEL = NetworkRegistry.newSimpleChannel( new ResourceLocation(valscraft.MODID, "main"), () -> PROTOCOL_VERSION, PROTOCOL_VERSION::equals, PROTOCOL_VERSION::equals ); public static void init() { int packetId = 0; // Register the mount synchronization packet CHANNEL.registerMessage( packetId++, MountSyncPacket.class, MountSyncPacket::encode, MountSyncPacket::decode, (msg, context) -> msg.handle(context.get()) // Get the context with context.get() ); } }  
    • Do you use features of inventory profiles next (ipnext) or is there a change without it?
    • Remove rubidium - you are already using embeddium, which is a fork of rubidium
  • Topics

×
×
  • Create New...

Important Information

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