implement character limb swing animation

(cherry picked from commit 19c59e38feff562ccbaade8e38fdd303bba784a5)
This commit is contained in:
LabyStudio
2022-04-14 00:45:23 +02:00
parent 7df2806456
commit 62d7ba24b9
9 changed files with 211 additions and 70 deletions
+10 -8
View File
@@ -18,20 +18,20 @@ window.Entity = class {
this.sneaking = false;
this.yaw = 0;
this.pitch = 0;
this.renderYawOffset = 0;
this.rotationYaw = 0;
this.rotationPitch = 0;
this.prevX = 0;
this.prevY = 0;
this.prevZ = 0;
this.prevYaw = 0;
this.prevPitch = 0;
this.prevRenderYawOffset = 0;
this.prevRotationYaw = 0;
this.prevRotationPitch = 0;
this.distanceWalked = 0;
this.nextStepDistance = 1;
this.ticksExisted = 0;
}
onUpdate() {
@@ -43,8 +43,10 @@ window.Entity = class {
this.prevY = this.y;
this.prevZ = this.z;
this.prevPitch = this.pitch;
this.prevYaw = this.yaw;
this.prevRotationPitch = this.rotationPitch;
this.prevRotationYaw = this.rotationYaw;
this.ticksExisted++;
}
}
@@ -9,19 +9,71 @@ window.EntityLiving = class extends Entity {
this.moveForward = 0.0;
this.moveStrafing = 0.0;
this.swingProgress = 0;
this.renderYawOffset = 0;
this.rotationYawHead = 0;
this.prevRotationYawHead = 0;
this.prevRenderYawOffset = 0;
this.limbSwing = 0;
this.limbSwingAmount = 0;
this.prevLimbSwingAmount = 0;
}
onUpdate() {
super.onUpdate();
this.onLivingUpdate();
let motionX = this.x - this.prevX;
let motionZ = this.z - this.prevZ;
let bodyRotation = this.renderYawOffset;
let distanceTravelled = motionX * motionX + motionZ * motionZ;
let distanceTravelledSqrt = 0.0;
if (distanceTravelled > 0.0025000002) {
distanceTravelledSqrt = Math.sqrt(distanceTravelled) * 3.0;
bodyRotation = Math.atan2(motionZ, motionX) * 180.0 / Math.PI - 90.0;
}
if (this.swingProgress > 0.0) {
bodyRotation = this.rotationYaw;
}
// TODO handle travel distance
distanceTravelledSqrt = this.updateBodyRotation(bodyRotation, distanceTravelledSqrt);
while (this.rotationYaw - this.prevRotationYaw < -180.0) {
this.prevRotationYaw -= 360.0;
}
while (this.rotationYaw - this.prevRotationYaw >= 180.0) {
this.prevRotationYaw += 360.0;
}
while (this.renderYawOffset - this.prevRenderYawOffset < -180.0) {
this.prevRenderYawOffset -= 360.0;
}
while (this.renderYawOffset - this.prevRenderYawOffset >= 180.0) {
this.prevRenderYawOffset += 360.0;
}
while (this.rotationPitch - this.prevRotationPitch < -180.0) {
this.prevRotationPitch -= 360.0;
}
while (this.rotationPitch - this.prevRotationPitch >= 180.0) {
this.prevRotationPitch += 360.0;
}
while (this.rotationYawHead - this.prevRotationYawHead < -180.0) {
this.prevRotationYawHead -= 360.0;
}
while (this.rotationYawHead - this.prevRotationYawHead >= 180.0) {
this.prevRotationYawHead += 360.0;
}
}
onLivingUpdate() {
@@ -40,6 +92,8 @@ window.EntityLiving = class extends Entity {
this.motionZ = 0.0;
}
this.rotationYawHead = this.rotationYaw;
// Jump
if (this.jumping) {
if (this.isInWater()) {
@@ -70,13 +124,60 @@ window.EntityLiving = class extends Entity {
this.travel(moveForward, 0, moveStrafing);
}
}
this.prevLimbSwingAmount = this.limbSwingAmount;
let motionX = this.x - this.prevX;
let motionZ = this.z - this.prevZ;
let distance = Math.sqrt(motionX * motionX + motionZ * motionZ) * 4.0;
if (distance > 1.0) {
distance = 1.0;
}
this.limbSwingAmount += (distance - this.limbSwingAmount) * 0.4;
this.limbSwing += this.limbSwingAmount;
}
onEntityUpdate() {
this.prevRenderYawOffset = this.renderYawOffset;
this.prevRotationYawHead = this.rotationYawHead;
super.onEntityUpdate();
}
updateBodyRotation(bodyRotation, distanceTravelledSqrt) {
let bodyRotationDifference = MathHelper.wrapAngleTo180(bodyRotation - this.renderYawOffset);
this.renderYawOffset += bodyRotationDifference * 0.3;
let yaw = MathHelper.wrapAngleTo180(this.rotationYaw - this.renderYawOffset);
let turn = yaw < -90.0 || yaw >= 90.0;
if (yaw < -75.0) {
yaw = -75.0;
}
if (yaw >= 75.0) {
yaw = 75.0;
}
this.renderYawOffset = this.rotationYaw - yaw;
if (yaw * yaw > 2500.0) {
this.renderYawOffset += yaw * 0.2;
}
if (turn) {
distanceTravelledSqrt *= -1.0;
}
return distanceTravelledSqrt;
}
computeAngleWithBound(value, subtract, limit) {
let wrapped = MathHelper.wrapAngleTo180(value - subtract);
if (wrapped < -limit) {
wrapped = -limit;
}
if (wrapped >= limit) {
wrapped = limit;
}
return value - wrapped;
}
}
@@ -51,15 +51,15 @@ window.PlayerEntity = class extends EntityLiving {
}
turn(motionX, motionY) {
this.yaw = this.yaw + motionX * 0.15;
this.pitch = this.pitch - motionY * 0.15;
this.rotationYaw = this.rotationYaw + motionX * 0.15;
this.rotationPitch = this.rotationPitch - motionY * 0.15;
if (this.pitch < -90.0) {
this.pitch = -90.0;
if (this.rotationPitch < -90.0) {
this.rotationPitch = -90.0;
}
if (this.pitch > 90.0) {
this.pitch = 90.0;
if (this.rotationPitch > 90.0) {
this.rotationPitch = 90.0;
}
}
@@ -131,7 +131,7 @@ window.PlayerEntity = class extends EntityLiving {
this.motionY = 0.42;
if (this.sprinting) {
let radiansYaw = MathHelper.toRadians(this.yaw + 180);
let radiansYaw = MathHelper.toRadians(this.rotationYaw + 180);
this.motionX -= Math.sin(radiansYaw) * 0.2;
this.motionZ += Math.cos(radiansYaw) * 0.2;
}
@@ -259,7 +259,7 @@ window.PlayerEntity = class extends EntityLiving {
up = up * distance;
forward = forward * distance;
let yawRadians = MathHelper.toRadians(this.yaw + 180);
let yawRadians = MathHelper.toRadians(this.rotationYaw + 180);
let sin = Math.sin(yawRadians);
let cos = Math.cos(yawRadians);
@@ -469,7 +469,7 @@ window.PlayerEntity = class extends EntityLiving {
*/
getLook(partialTicks) {
// TODO interpolation
return this.getVectorForRotation(this.pitch, this.yaw);
return this.getVectorForRotation(this.rotationPitch, this.rotationYaw);
}
/**
@@ -104,8 +104,8 @@ window.WorldRenderer = class {
orientCamera(partialTicks) {
let player = this.minecraft.player;
let rotationY = -MathHelper.toRadians(player.yaw + 180);
let rotationX = -MathHelper.toRadians(player.pitch);
let rotationY = -MathHelper.toRadians(player.rotationYaw + 180);
let rotationX = -MathHelper.toRadians(player.rotationPitch);
// Position
let x = player.prevX + (player.x - player.prevX) * partialTicks;
@@ -116,8 +116,10 @@ window.WorldRenderer = class {
let mode = this.minecraft.settings.thirdPersonView;
if (mode !== 0) {
// Flip for front view
if (mode === 2) {
let frontView = mode === 2;
if (frontView) {
rotationY += Math.PI;
rotationX *= -1;
}
// Shift camera
@@ -11,9 +11,15 @@ window.EntityRenderer = class {
render(entity, partialTicks) {
let group = entity.group;
let rotationOffset = this.interpolateRotation(entity.prevRenderYawOffset, entity.renderYawOffset, partialTicks);
let rotationBody = this.interpolateRotation(entity.prevRenderYawOffset, entity.renderYawOffset, partialTicks);
let rotationHead = this.interpolateRotation(entity.prevRotationYawHead, entity.rotationYawHead, partialTicks);
let limbSwing = entity.prevLimbSwingAmount + (entity.limbSwingAmount - entity.prevLimbSwingAmount) * partialTicks;
let limbSwingAmount = entity.limbSwing - entity.limbSwingAmount * (1.0 - partialTicks);
let yaw = rotationHead - rotationBody;
let pitch = entity.prevRotationPitch + (entity.rotationPitch - entity.prevRotationPitch) * partialTicks;
// Interpolate entity position
let interpolatedX = entity.prevX + (entity.x - entity.prevX) * partialTicks;
let interpolatedY = entity.prevY + (entity.y - entity.prevY) * partialTicks;
@@ -29,11 +35,11 @@ window.EntityRenderer = class {
group.scale.set(scale, -scale, scale);
// Rotate entity model
group.rotation.y = MathHelper.toRadians(-entity.yaw + 180);
group.rotation.y = MathHelper.toRadians(-rotationBody + 180);
// Render entity model
let time = Date.now() / 100;
this.model.render(group, time);
let timeAlive = entity.ticksExisted + partialTicks;
this.model.render(entity, limbSwingAmount, limbSwing, timeAlive, yaw, pitch);
}
interpolateRotation(prevValue, value, partialTicks) {
@@ -10,14 +10,8 @@ window.ModelBase = class {
}
/**
* Render the model
*
* @param group Group to render
* @param time Animation offset
*/
render(group, time) {
group.updateMatrix();
render(entity, limbSwingAmount, limbSwing, timeAlive, yaw, pitch) {
entity.group.updateMatrix();
}
}
@@ -22,25 +22,25 @@ window.ModelPlayer = class extends ModelBase {
// Right arm ModelRenderer
this.rightArm = new ModelRenderer(width, height)
.setTextureOffset(40, 16)
.setPosition(-5.0, 2.0, 0.0)
.setRotationPoint(-5.0, 2.0, 0.0)
.setBox(-3.0, -2.0, -2.0, 4, 12, 4);
// Left arm ModelRenderer
this.leftArm = new ModelRenderer(width, height)
.setTextureOffset(40, 16)
.setPosition(5.0, 2.0, 0.0)
.setRotationPoint(5.0, 2.0, 0.0)
.setBox(-1.0, -2.0, -2.0, 4, 12, 4);
// Right Legs ModelRenderer
this.rightLeg = new ModelRenderer(width, height)
.setTextureOffset(0, 16)
.setPosition(-2.0, 12.0, 0.0)
.setRotationPoint(-2.0, 12.0, 0.0)
.setBox(-2.0, 0.0, -2.0, 4, 12, 4);
// Left leg ModelRenderer
this.leftLeg = new ModelRenderer(width, height)
.setTextureOffset(0, 16)
.setPosition(2.0, 12.0, 0.0)
.setRotationPoint(2.0, 12.0, 0.0)
.setBox(-2.0, 0.0, -2.0, 4, 12, 4);
}
@@ -55,22 +55,47 @@ window.ModelPlayer = class extends ModelBase {
this.rightLeg.rebuild(tessellator, group);
}
/**
* Render the model
*
* @param group Group to update position and rotation of
* @param time Animation offset
*/
render(group, time) {
// Set rotation of cubes
this.head.yRotation = Math.sin(time * 0.83);
this.head.xRotation = Math.sin(time) * 0.8;
this.rightArm.xRotation = Math.sin(time * 0.6662 + Math.PI) * 2.0;
this.rightArm.zRotation = (Math.sin(time * 0.2312) + 1.0);
this.leftArm.xRotation = Math.sin(time * 0.6662) * 2.0;
this.leftArm.zRotation = (Math.sin(time * 0.2812) - 1.0);
this.rightLeg.xRotation = Math.sin(time * 0.6662) * 1.4;
this.leftLeg.xRotation = Math.sin(time * 0.6662 + Math.PI) * 1.4;
render(entity, limbSwingAmount, limbSwing, timeAlive, yaw, pitch) {
let group = entity.group;
this.head.rotateAngleY = MathHelper.toRadians(yaw);
this.head.rotateAngleX = MathHelper.toRadians(pitch);
this.rightArm.rotateAngleX = Math.cos(limbSwingAmount * 0.6662 + Math.PI) * 2.0 * limbSwing * 0.5;
this.leftArm.rotateAngleX = Math.cos(limbSwingAmount * 0.6662) * 2.0 * limbSwing * 0.5;
this.rightArm.rotateAngleZ = 0.0;
this.leftArm.rotateAngleZ = 0.0;
this.rightLeg.rotateAngleX = Math.cos(limbSwingAmount * 0.6662) * 1.4 * limbSwing;
this.leftLeg.rotateAngleX = Math.cos(limbSwingAmount * 0.6662 + Math.PI) * 1.4 * limbSwing;
this.rightLeg.rotateAngleY = 0.0;
this.leftLeg.rotateAngleY = 0.0;
this.rightArm.rotateAngleY = 0.0;
this.rightArm.rotateAngleZ = 0.0;
if (entity.sneaking) {
this.body.rotateAngleX = 0.5;
this.rightArm.rotateAngleX += 0.4;
this.leftArm.rotateAngleX += 0.4;
this.rightLeg.rotationPointZ = 4.0;
this.leftLeg.rotationPointZ = 4.0;
this.rightLeg.rotationPointY = 9.0;
this.leftLeg.rotationPointY = 9.0;
this.head.rotationPointY = 1.0;
group.translateY(-0.2);
} else {
this.body.rotateAngleX = 0.0;
this.rightLeg.rotationPointZ = 0.1;
this.leftLeg.rotationPointZ = 0.1;
this.rightLeg.rotationPointY = 12.0;
this.leftLeg.rotationPointY = 12.0;
this.head.rotationPointY = 0.0;
}
this.rightArm.rotateAngleZ += Math.cos(timeAlive * 0.09) * 0.05 + 0.05;
this.leftArm.rotateAngleZ -= Math.cos(timeAlive * 0.09) * 0.05 + 0.05;
this.rightArm.rotateAngleX += Math.sin(timeAlive * 0.067) * 0.05;
this.leftArm.rotateAngleX -= Math.sin(timeAlive * 0.067) * 0.05;
// Render cubes
this.head.render(group);
@@ -80,7 +105,7 @@ window.ModelPlayer = class extends ModelBase {
this.rightLeg.render(group);
this.leftLeg.render(group);
super.render(group, time);
super.render(entity, limbSwingAmount, limbSwing, timeAlive, yaw, pitch);
}
}
@@ -10,13 +10,13 @@ window.ModelRenderer = class {
this.textureOffsetX = 0;
this.textureOffsetY = 0;
this.xRotation = 0;
this.yRotation = 0;
this.zRotation = 0;
this.rotateAngleX = 0;
this.rotateAngleY = 0;
this.rotateAngleZ = 0;
this.x = 0;
this.y = 0;
this.z = 0;
this.rotationPointX = 0;
this.rotationPointY = 0;
this.rotationPointZ = 0;
this.bone = new THREE.Object3D();
}
@@ -128,10 +128,10 @@ window.ModelRenderer = class {
* @param y Absolute y position of cube
* @param z Absolute z position of cube
*/
setPosition(x, y, z) {
this.x = x;
this.y = y;
this.z = z;
setRotationPoint(x, y, z) {
this.rotationPointX = x;
this.rotationPointY = y;
this.rotationPointZ = z;
return this;
}
@@ -151,14 +151,14 @@ window.ModelRenderer = class {
}
render(group) {
this.bone.position.setX(this.x);
this.bone.position.setY(this.y);
this.bone.position.setZ(this.z);
this.bone.position.setX(this.rotationPointX);
this.bone.position.setY(this.rotationPointY);
this.bone.position.setZ(this.rotationPointZ);
this.bone.rotation.order = 'ZYX';
this.bone.rotation.x = this.xRotation;
this.bone.rotation.y = this.yRotation;
this.bone.rotation.z = this.zRotation;
this.bone.rotation.x = this.rotateAngleX;
this.bone.rotation.y = -this.rotateAngleY;
this.bone.rotation.z = this.rotateAngleZ;
this.bone.updateMatrix();
}
+11
View File
@@ -33,6 +33,17 @@ window.MathHelper = class {
return angle;
}
static wrapAngleTo180(value) {
value = value % 360.0;
if (value >= 180.0) {
value -= 360.0;
}
if (value < -180.0) {
value += 360.0;
}
return value;
}
static hsbToRgb(hue, saturation, brightness) {
let r = 0, g = 0, b = 0;
if (saturation === 0) {