New animation loader! COLLADA supports all the cool things we want to do, but nothing that _implements_ COLLADA as an exporter does... aint that grand

Animation set for Colt/Python added
This commit is contained in:
George Paton 2024-01-30 14:00:14 +11:00
parent 37490f35a2
commit a067e437a5
13 changed files with 1935 additions and 2039 deletions

BIN
ntm-animator.blend Normal file

Binary file not shown.

View File

@ -3,6 +3,7 @@ package com.hbm.handler;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.function.Consumer;
import com.hbm.lib.HbmCollection.EnumGunManufacturer;
import com.hbm.render.anim.BusAnimation;
@ -35,7 +36,10 @@ public class GunConfiguration implements Cloneable {
public int durability;
//animations!
public HashMap<AnimType, BusAnimation> animations = new HashMap();
public HashMap<AnimType, BusAnimation> animations = new HashMap<AnimType, BusAnimation>();
//lazy-ish loading for animations, required for loading animations from ResourceManager, since that occurs after we've initialised the guns
public Consumer<Void> loadAnimations;
public boolean animationsLoaded = false;
//when sneaking, disables crosshair and centers the bullet spawn point
public boolean hasSights;
//texture overlay when sneaking
@ -79,10 +83,10 @@ public class GunConfiguration implements Cloneable {
public String name = "";
public EnumGunManufacturer manufacturer = EnumGunManufacturer.NONE;
public List<String> comment = new ArrayList();
public List<String> comment = new ArrayList<String>();
//bullet configs for main and alt fire
public List<Integer> config = new ArrayList();
public List<Integer> config = new ArrayList<Integer>();
//crosshair
public Crosshair crosshair;

View File

@ -10,10 +10,12 @@ import com.hbm.inventory.RecipesCommon.ComparableStack;
import com.hbm.items.ModItems;
import com.hbm.items.ItemAmmoEnums.Ammo357Magnum;
import com.hbm.lib.HbmCollection.EnumGunManufacturer;
import com.hbm.main.ResourceManager;
import com.hbm.particle.SpentCasing;
import com.hbm.particle.SpentCasing.CasingType;
import com.hbm.lib.ModDamageSource;
import com.hbm.potion.HbmPotion;
import com.hbm.render.anim.HbmAnimations.AnimType;
import com.hbm.render.util.RenderScreenOverlay.Crosshair;
import net.minecraft.potion.PotionEffect;
@ -39,7 +41,7 @@ public class Gun357MagnumFactory {
config.roundsPerCycle = 1;
config.gunMode = GunConfiguration.MODE_NORMAL;
config.firingMode = GunConfiguration.FIRE_MANUAL;
config.reloadDuration = 10;
config.reloadDuration = 30;
config.firingDuration = 0;
config.ammoCap = 6;
config.reloadType = GunConfiguration.RELOAD_FULL;
@ -50,6 +52,11 @@ public class Gun357MagnumFactory {
config.reloadSoundEnd = false;
config.ejector = EJECTOR_REVOLVER;
config.loadAnimations = i -> {
config.animations.put(AnimType.CYCLE, ResourceManager.python_anim.get("Fire"));
config.animations.put(AnimType.RELOAD, ResourceManager.python_anim.get("Reload"));
};
return config;
}
@ -242,7 +249,7 @@ public class Gun357MagnumFactory {
bullet.dmgMin = 10;
bullet.dmgMax = 15;
bullet.effects = new ArrayList();
bullet.effects = new ArrayList<PotionEffect>();
bullet.effects.add(new PotionEffect(HbmPotion.radiation.id, 10 * 20, 4));
bullet.spentCasing = CASING357.clone().register("357Nuc").setColor(0xFEFEFE);
@ -328,8 +335,8 @@ public class Gun357MagnumFactory {
bullet.dmgMax = 100;
bullet.doesRicochet = false;
bullet.destroysBlocks = true;
bullet.style = bullet.STYLE_BOLT;
bullet.trail = bullet.BOLT_NIGHTMARE;
bullet.style = BulletConfiguration.STYLE_BOLT;
bullet.trail = BulletConfiguration.BOLT_NIGHTMARE;
bullet.damageType = ModDamageSource.s_laser;

View File

@ -784,6 +784,10 @@ public class ItemGunBase extends Item implements IHoldableWeapon, IItemHUD, IEqu
@SideOnly(Side.CLIENT)
public BusAnimation getAnimation(ItemStack stack, AnimType type) {
GunConfiguration config = ((ItemGunBase) stack.getItem()).mainConfig;
if (!config.animationsLoaded && config.loadAnimations != null) {
config.loadAnimations.accept(null);
config.animationsLoaded = true;
}
return config.animations.get(type);
}

View File

@ -136,7 +136,6 @@ public class ClientProxy extends ServerProxy {
registerClientEventHandler(theInfoSystem);
AdvancedModelLoader.registerModelHandler(new HmfModelLoader());
ResourceManager.loadAnimatedModels();
registerTileEntitySpecialRenderer();
registerItemRenderer();

View File

@ -1,9 +1,13 @@
package com.hbm.main;
import java.util.HashMap;
import com.hbm.animloader.AnimatedModel;
import com.hbm.animloader.Animation;
import com.hbm.animloader.ColladaLoader;
import com.hbm.lib.RefStrings;
import com.hbm.render.anim.AnimationLoader;
import com.hbm.render.anim.BusAnimation;
import com.hbm.render.loader.HFRWavefrontObject;
import com.hbm.render.loader.WavefrontObjDisplayList;
@ -318,12 +322,12 @@ public class ResourceManager {
public static final ResourceLocation sliding_blast_door_variant1_tex = new ResourceLocation(RefStrings.MODID, "textures/models/doors/sliding_blast_door_variant1.png");
public static final ResourceLocation sliding_blast_door_variant2_tex = new ResourceLocation(RefStrings.MODID, "textures/models/doors/sliding_blast_door_variant2.png");
public static AnimatedModel sliding_blast_door;
public static Animation sliding_blast_door_anim;
public static AnimatedModel sliding_blast_door = ColladaLoader.load(new ResourceLocation(RefStrings.MODID, "models/doors/sliding_blast_door.dae"));
public static Animation sliding_blast_door_anim = ColladaLoader.loadAnim(1200, new ResourceLocation(RefStrings.MODID, "models/doors/sliding_blast_door.dae"));
//Doors
public static AnimatedModel transition_seal;
public static Animation transition_seal_anim;
public static AnimatedModel transition_seal = ColladaLoader.load(new ResourceLocation(RefStrings.MODID, "models/doors/seal.dae"), true);
public static Animation transition_seal_anim = ColladaLoader.loadAnim(24040, new ResourceLocation(RefStrings.MODID, "models/doors/seal.dae"));
public static final WavefrontObjDisplayList fire_door = new HFRWavefrontObject(new ResourceLocation(RefStrings.MODID, "models/doors/fire_door.obj")).asDisplayList();
//Secure Access Door
@ -840,6 +844,8 @@ public class ResourceManager {
public static final IModelCustom uac_pistol = new HFRWavefrontObject(new ResourceLocation(RefStrings.MODID, "models/weapons/UAC pistol.obj")).asDisplayList();
public static final IModelCustom congolake = new HFRWavefrontObject(new ResourceLocation(RefStrings.MODID, "models/weapons/congolake.obj")).asDisplayList();
public static final IModelCustom lilmac = new HFRWavefrontObject(new ResourceLocation(RefStrings.MODID, "models/weapons/lilmac.obj")).asDisplayList();
public static final HashMap<String, BusAnimation> python_anim = AnimationLoader.load(new ResourceLocation(RefStrings.MODID, "models/weapons/animations/python.json"));
public static final IModelCustom lance = new HFRWavefrontObject(new ResourceLocation(RefStrings.MODID, "models/weapons/lance.obj"));
@ -1508,11 +1514,4 @@ public class ResourceManager {
public static final IModelCustom deb_zirnox_exchanger = AdvancedModelLoader.loadModel(new ResourceLocation(RefStrings.MODID, "models/zirnox/deb_exchanger.obj"));
public static final IModelCustom deb_zirnox_shrapnel = AdvancedModelLoader.loadModel(new ResourceLocation(RefStrings.MODID, "models/zirnox/deb_shrapnel.obj"));
public static void loadAnimatedModels(){
transition_seal = ColladaLoader.load(new ResourceLocation(RefStrings.MODID, "models/doors/seal.dae"), true);
transition_seal_anim = ColladaLoader.loadAnim(24040, new ResourceLocation(RefStrings.MODID, "models/doors/seal.dae"));
sliding_blast_door = ColladaLoader.load(new ResourceLocation(RefStrings.MODID, "models/doors/sliding_blast_door.dae"));
sliding_blast_door_anim = ColladaLoader.loadAnim(1200, new ResourceLocation(RefStrings.MODID, "models/doors/sliding_blast_door.dae"));
}
}

View File

@ -0,0 +1,135 @@
package com.hbm.render.anim;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonElement;
import com.google.gson.JsonArray;
import net.minecraft.client.Minecraft;
import net.minecraft.util.ResourceLocation;
import com.hbm.render.anim.BusAnimationSequence.Dimension;
public class AnimationLoader {
// The collada loader is great, but is not so backwards compatible and spews keyframes rather than doing interpolation
// Yeah - more animation loading is not so great, but 3mb for a single door opening is maybe overkill on a 50mb mod
// and even though the format supports multiple animations, no fucking animation software will actually export multiple animations,
// (even though blender even has a fucking toggle for it, but it doesn't _do_ anything)
// This instead just loads transformation data from a JSON file, turning it into a set of BusAnimations
// See ntm-animator.blend for a JSON format creation script
// "How do I make animations?"
// See ntm-animator.blend, it has the Colt/Python already setup and animated as an example, it'll generate JSON data that this can load
public static final Gson gson = new Gson();
public static HashMap<String, BusAnimation> load(ResourceLocation file) {
HashMap<String, BusAnimation> animations = new HashMap<String, BusAnimation>();
InputStream in;
try {
in = Minecraft.getMinecraft().getResourceManager().getResource(file).getInputStream();
} catch (IOException ex) {
return null;
}
InputStreamReader reader = new InputStreamReader(in);
JsonObject json = gson.fromJson(reader, JsonObject.class);
// Top level parsing, this is for the animation name as set in Blender
for (Map.Entry<String, JsonElement> root : json.entrySet()) {
BusAnimation animation = new BusAnimation();
// Loading the buses for this animation
JsonObject entryObject = root.getValue().getAsJsonObject();
for (Map.Entry<String, JsonElement> model : entryObject.entrySet()) {
animation.addBus(model.getKey(), loadSequence(model.getValue().getAsJsonObject()));
}
animations.put(root.getKey(), animation);
}
return animations;
}
private static BusAnimationSequence loadSequence(JsonObject json) {
BusAnimationSequence sequence = new BusAnimationSequence();
// Location fcurves
if (json.has("location")) {
JsonObject location = json.getAsJsonObject("location");
if (location.has("x")) {
addToSequence(sequence, Dimension.TX, location.getAsJsonArray("x"));
}
if (location.has("y")) {
addToSequence(sequence, Dimension.TY, location.getAsJsonArray("y"));
}
if (location.has("z")) {
addToSequence(sequence, Dimension.TZ, location.getAsJsonArray("z"));
}
}
// Rotation fcurves, only euler at the moment
if (json.has("rotation_euler")) {
JsonObject rotation = json.getAsJsonObject("rotation_euler");
if (rotation.has("x")) {
addToSequence(sequence, Dimension.RX, rotation.getAsJsonArray("x"));
}
if (rotation.has("y")) {
addToSequence(sequence, Dimension.RY, rotation.getAsJsonArray("y"));
}
if (rotation.has("z")) {
addToSequence(sequence, Dimension.RZ, rotation.getAsJsonArray("z"));
}
}
// Scale fcurves
if (json.has("scale")) {
JsonObject scale = json.getAsJsonObject("scale");
if (scale.has("x")) {
addToSequence(sequence, Dimension.SX, scale.getAsJsonArray("x"));
}
if (scale.has("y")) {
addToSequence(sequence, Dimension.SY, scale.getAsJsonArray("y"));
}
if (scale.has("z")) {
addToSequence(sequence, Dimension.SZ, scale.getAsJsonArray("z"));
}
}
// The first location must be undone to return everything to 0,0,0
// This is required to ensure that rotations occur around the origin of the part, not 0,0,0
sequence.offset[0] = sequence.getFirstValue(Dimension.TX);
sequence.offset[1] = sequence.getFirstValue(Dimension.TY);
sequence.offset[2] = sequence.getFirstValue(Dimension.TZ);
return sequence;
}
private static void addToSequence(BusAnimationSequence sequence, Dimension dimension, JsonArray array) {
for (JsonElement element : array) {
sequence.addKeyframe(dimension, loadKeyframe(element));
}
}
private static BusAnimationKeyframe loadKeyframe(JsonElement element) {
JsonArray array = element.getAsJsonArray();
double value = array.get(0).getAsDouble();
int duration = array.get(1).getAsInt();
return new BusAnimationKeyframe(value, duration);
}
}

View File

@ -10,25 +10,13 @@ public class BusAnimationKeyframe {
NONE,
LINEAR
}
// public double x;
// public double y;
// public double z;
public double value;
public InterpolationType interpolationType;
public int duration;
// public double[] toArray() {
// return new double[] {x, y, z};
// }
//this one can be used for "reset" type keyframes
public BusAnimationKeyframe() {
// this.x = 0;
// this.y = 0;
// this.z = 0;
this.value = 0;
this.duration = 1;
this.interpolationType = InterpolationType.LINEAR;
@ -44,19 +32,5 @@ public class BusAnimationKeyframe {
this(value, duration);
this.interpolationType = interpolation;
}
// public BusAnimationKeyframe(double x, double y, double z, int duration) {
// this();
// this.x = x;
// this.y = y;
// this.z = z;
// this.duration = duration;
// }
// public BusAnimationKeyframe(double x, double y, double z, int duration, InterpolationType interpolation) {
// this(x, y, z, duration);
// this.interpolationType = interpolation;
// }
}

View File

@ -24,6 +24,8 @@ public class BusAnimationSequence {
// Storing a matrix of keyframe data, each keyframe stores a SINGLE dimension, so we can stagger frames over each parameter
private List<List<BusAnimationKeyframe>> transformKeyframes = new ArrayList<List<BusAnimationKeyframe>>(9);
public double[] offset = new double[3];
public BusAnimationSequence() {
// Initialise our keyframe storage, since it's multidimensional
@ -42,9 +44,7 @@ public class BusAnimationSequence {
}
public BusAnimationSequence addKeyframe(Dimension dimension, double value, int duration) {
transformKeyframes.get(dimension.ordinal()).add(new BusAnimationKeyframe(value, duration));
return this;
return addKeyframe(dimension, new BusAnimationKeyframe(value, duration));
}
@ -66,11 +66,15 @@ public class BusAnimationSequence {
}
public double getFirstValue(Dimension dimension) {
List<BusAnimationKeyframe> keyframes = transformKeyframes.get(dimension.ordinal());
if (keyframes.size() == 0) return 0;
return keyframes.get(0).value;
}
//all transformation data is absolute, additive transformations have not yet been implemented
public double[] getTransformation(int millis) {
double[] transform = new double[9];
double[] transform = new double[12];
for (int i = 0; i < 9; i++) {
List<BusAnimationKeyframe> keyframes = transformKeyframes.get(i);
@ -88,13 +92,13 @@ public class BusAnimationSequence {
if (millis < endTime) break;
}
if (currentFrame == null || millis >= endTime) {
if (currentFrame == null) {
// Scale defaults to 1, others are 0
transform[i] = i >= 6 ? 1 : 0;
continue;
}
if (currentFrame.interpolationType == InterpolationType.NONE) {
if (currentFrame.interpolationType == InterpolationType.NONE || millis >= endTime) {
transform[i] = currentFrame.value;
continue;
}
@ -106,6 +110,10 @@ public class BusAnimationSequence {
transform[i] = (a - b) * t + b;
}
transform[9] = offset[0];
transform[10] = offset[1];
transform[11] = offset[2];
return transform;
}

View File

@ -84,21 +84,23 @@ public class HbmAnimations {
return trans;
}
}
return new double[] {
0, 0, 0, // position
0, 0, 0, // rotation
1, 1, 1 // scale
1, 1, 1, // scale
0, 0, 0 // offset
};
}
public static void applyRelevantTransformation(String bus) {
double[] transform = getRelevantTransformation(bus);
GL11.glTranslated(transform[0], transform[1], transform[2]);
GL11.glRotated(transform[3], 1, 0, 0);
GL11.glRotated(transform[4], 0, 1, 0);
GL11.glRotated(transform[5], 0, 0, 1);
GL11.glTranslated(-transform[9], -transform[10], -transform[11]);
GL11.glScaled(transform[6], transform[7], transform[8]);
}

View File

@ -3,6 +3,7 @@ package com.hbm.render.item.weapon;
import org.lwjgl.opengl.GL11;
import com.hbm.main.ResourceManager;
import com.hbm.render.anim.HbmAnimations;
import net.minecraft.client.Minecraft;
import net.minecraft.item.ItemStack;
@ -55,8 +56,26 @@ public class ItemRenderWeaponFFColt implements IItemRenderer {
GL11.glScaled(s0, s0, s0);
GL11.glRotated(100, 0, -1, 0);
GL11.glRotated(25, 1, 0, 0);
HbmAnimations.applyRelevantTransformation("Body");
Minecraft.getMinecraft().renderEngine.bindTexture(main);
ResourceManager.ff_python.renderPart("Body");
GL11.glPushMatrix();
HbmAnimations.applyRelevantTransformation("Cylinder");
ResourceManager.ff_python.renderPart("Cylinder");
GL11.glPopMatrix();
Minecraft.getMinecraft().renderEngine.bindTexture(grip);
ResourceManager.ff_python.renderPart("Grip");
HbmAnimations.applyRelevantTransformation("Hammer");
Minecraft.getMinecraft().renderEngine.bindTexture(hammer);
ResourceManager.ff_python.renderPart("Hammer");
break;
GL11.glPopMatrix();
return;
case EQUIPPED:

View File

@ -0,0 +1 @@
{"Fire": {"Body": {"location": {"z": [[-0.0, 0.0], [0.1901400089263916, 50.0], [-0.0, 283.3333333333333]], "y": [[0.0, 0.0], [0.22623062133789062, 50.0], [0.0, 283.3333333333333]]}, "rotation_euler": {"x": [[0.0, 16.666666666666668], [50.512076610560676, 66.66666666666666], [0.0, 250.0]]}}, "Hammer": {"rotation_euler": {"x": [[0.0, 0.0], [-44.61753114928588, 16.666666666666668], [-44.61753114928588, 183.33333333333334], [0.0, 300.0]]}, "location": {"x": [[0.00012800097465515137, 0.0]], "z": [[0.1478099822998047, 0.0]], "y": [[0.1151699647307396, 0.0]]}}}, "Reload": {"Body": {"location": {"x": [[0.0, 0.0], [0.1266033947467804, 216.66666666666669], [-0.1256844699382782, 66.66666666666663], [-0.10699314624071121, 100.0], [-0.05540347099304199, 183.33333333333331], [-0.04984791576862335, 83.33333333333337], [-0.04814600944519043, 100.0], [-0.0495946928858757, 50.0], [-0.1901838481426239, 216.66666666666663], [-0.209717258810997, 366.66666666666663], [-0.2682616710662842, 83.33333333333326], [0.06351689994335175, 100.00000000000023], [0.059162016957998276, 83.33333333333326], [0.0, 199.99999999999977]], "z": [[-0.0, 0.0], [0.018239933997392654, 216.66666666666669], [-0.003715081140398979, 66.66666666666663], [0.003378540277481079, 100.0], [0.06673367321491241, 183.33333333333331], [0.13605912029743195, 83.33333333333337], [0.11836071312427521, 100.0], [0.13753235340118408, 50.0], [0.2322661280632019, 216.66666666666663], [0.20868675410747528, 366.66666666666663], [0.15863937139511108, 83.33333333333326], [0.2003980427980423, 100.00000000000023], [0.09448619186878204, 83.33333333333326], [-0.0, 199.99999999999977]], "y": [[0.0, 0.0], [0.04348362237215042, 216.66666666666669], [0.04043026641011238, 66.66666666666663], [0.0498494915664196, 100.0], [0.21255171298980713, 183.33333333333331], [0.027551360428333282, 83.33333333333337], [0.09703753143548965, 100.0], [0.024584002792835236, 50.0], [-0.3309659957885742, 216.66666666666663], [-0.3340303301811218, 366.66666666666663], [-0.1700890064239502, 83.33333333333326], [0.016301512718200684, 100.00000000000023], [-0.015913818031549454, 83.33333333333326], [0.0, 199.99999999999977]]}, "rotation_euler": {"x": [[0.0, 0.0], [3.3686347844983024, 150.0], [0.02222707974050119, 166.66666666666663], [4.537149524119608, 100.00000000000006], [61.414745582626026, 233.33333333333331], [52.280518454609116, 133.33333333333337], [-71.68136001842309, 199.9999999999999], [-67.29034068404862, 366.66666666666674], [-53.072130549224426, 116.66666666666652], [-7.130840436898373, 100.00000000000023], [-2.7997762896148553, 83.33333333333326], [0.0, 199.99999999999977]], "z": [[0.0, 0.0], [-17.712562234959403, 150.0], [13.30397138517142, 166.66666666666663], [5.758366003376731, 100.00000000000006], [5.603675025280636, 233.33333333333331], [6.040763589705493, 133.33333333333337], [-1.4811513876747122, 199.9999999999999], [-0.9937320130296772, 366.66666666666674], [5.75973417564485, 116.66666666666652], [-7.87355264592462, 100.00000000000023], [-5.935155631645579, 83.33333333333326], [-0.0, 199.99999999999977]], "y": [[0.0, 0.0], [-3.362418245136533, 150.0], [5.488280686800564, 166.66666666666663], [2.9251945710321565, 100.00000000000006], [-3.2122371128833507, 233.33333333333331], [-2.2836878362589266, 133.33333333333337], [6.285038902068653, 199.9999999999999], [6.379913644734715, 366.66666666666674], [24.273973215848397, 116.66666666666652], [-30.381999654726528, 100.00000000000023], [-9.056688259237983, 83.33333333333326], [0.0, 199.99999999999977]]}}, "Cylinder": {"location": {"x": [[-0.0010489225387573242, 0.0], [-0.0010489225387573242, 283.3333333333333], [-0.07956840097904205, 83.33333333333331], [-0.07956840097904205, 1200.0], [-0.0010489225387573242, 83.33333333333326]], "z": [[0.07426249980926514, 0.0], [0.07426249980926514, 283.3333333333333], [0.07129553705453873, 83.33333333333331], [0.07129553705453873, 1200.0], [0.07426249980926514, 83.33333333333326]], "y": [[0.10388392210006714, 0.0], [0.10388392210006714, 283.3333333333333], [0.07195358723402023, 83.33333333333331], [0.07195358723402023, 1200.0], [0.10388392210006714, 83.33333333333326]]}}}}

File diff suppressed because it is too large Load Diff