Merge pull request #1821 from MellowArpeggiation/master

A few animation fixes more
This commit is contained in:
HbmMods 2024-12-23 21:32:18 +01:00 committed by GitHub
commit e04e5aff1d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 89 additions and 31 deletions

View File

@ -52,15 +52,31 @@ public class AnimationLoader {
// Effectively, this removes double translation AND ensures that rotations occur around the individual object origin, rather than the weapon origin // Effectively, this removes double translation AND ensures that rotations occur around the individual object origin, rather than the weapon origin
HashMap<String, double[]> offsets = new HashMap<String, double[]>(); HashMap<String, double[]> offsets = new HashMap<String, double[]>();
for(Map.Entry<String, JsonElement> root : json.getAsJsonObject("offset").entrySet()) { for(Map.Entry<String, JsonElement> root : json.getAsJsonObject("offset").entrySet()) {
double[] offset = new double[3]; JsonArray array = root.getValue().getAsJsonArray();
double[] offset = new double[3];
for(int i = 0; i < 3; i++) { for(int i = 0; i < 3; i++) {
offset[i] = root.getValue().getAsJsonArray().get(i).getAsDouble(); offset[i] = array.get(i).getAsDouble();
} }
offsets.put(root.getKey(), offset); offsets.put(root.getKey(), offset);
} }
// Rotation modes, swizzled into our local space. YZX in blender becomes XYZ due to:
// * rotation order reversed in blender (XYZ -> ZYX)
// * dimensions Y and Z are swapped in blender (ZYX -> YZX)
HashMap<String, double[]> rotModes = new HashMap<String, double[]>();
if(json.has("rotmode")) {
for(Map.Entry<String, JsonElement> root : json.getAsJsonObject("rotmode").entrySet()) {
String mode = root.getValue().getAsString();
double[] rotMode = new double[3];
rotMode[0] = getRot(mode.charAt(2));
rotMode[1] = getRot(mode.charAt(0));
rotMode[2] = getRot(mode.charAt(1));
}
}
// Top level parsing, this is for the animation name as set in Blender // Top level parsing, this is for the animation name as set in Blender
for(Map.Entry<String, JsonElement> root : json.getAsJsonObject("anim").entrySet()) { for(Map.Entry<String, JsonElement> root : json.getAsJsonObject("anim").entrySet()) {
@ -71,8 +87,10 @@ public class AnimationLoader {
for(Map.Entry<String, JsonElement> model : entryObject.entrySet()) { for(Map.Entry<String, JsonElement> model : entryObject.entrySet()) {
String modelName = model.getKey(); String modelName = model.getKey();
double[] offset = new double[3]; double[] offset = new double[3];
if (offsets.containsKey(modelName)) offset = offsets.get(modelName); double[] rotMode = new double[] { 0, 1, 2 };
animation.addBus(modelName, loadSequence(model.getValue().getAsJsonObject(), offset)); if(offsets.containsKey(modelName)) offset = offsets.get(modelName);
if(rotModes.containsKey(modelName)) rotMode = rotModes.get(modelName);
animation.addBus(modelName, loadSequence(model.getValue().getAsJsonObject(), offset, rotMode));
} }
animations.put(root.getKey(), animation); animations.put(root.getKey(), animation);
@ -81,7 +99,16 @@ public class AnimationLoader {
return animations; return animations;
} }
private static BusAnimationSequence loadSequence(JsonObject json, double[] offset) { private static double getRot(char value) {
switch(value) {
case 'X': return 0;
case 'Y': return 1;
case 'Z': return 2;
default: return 0;
}
}
private static BusAnimationSequence loadSequence(JsonObject json, double[] offset, double[] rotMode) {
BusAnimationSequence sequence = new BusAnimationSequence(); BusAnimationSequence sequence = new BusAnimationSequence();
// Location fcurves // Location fcurves
@ -130,6 +157,7 @@ public class AnimationLoader {
} }
sequence.offset = offset; sequence.offset = offset;
sequence.rotMode = rotMode;
return sequence; return sequence;
} }

View File

@ -591,11 +591,11 @@ public class BusAnimationKeyframe {
} }
double BLI_easing_sine_ease_in(double time, double begin, double change, double duration) { double BLI_easing_sine_ease_in(double time, double begin, double change, double duration) {
return -change * Math.cos(time / duration * (double) Math.PI * 2) + change + begin; return -change * Math.cos(time / duration * (double) Math.PI / 2) + change + begin;
} }
double BLI_easing_sine_ease_out(double time, double begin, double change, double duration) { double BLI_easing_sine_ease_out(double time, double begin, double change, double duration) {
return change * Math.sin(time / duration * (double) Math.PI * 2) + begin; return change * Math.sin(time / duration * (double) Math.PI / 2) + begin;
} }
double BLI_easing_sine_ease_in_out(double time, double begin, double change, double duration) { double BLI_easing_sine_ease_in_out(double time, double begin, double change, double duration) {

View File

@ -26,6 +26,9 @@ public class BusAnimationSequence {
public double[] offset = new double[3]; public double[] offset = new double[3];
// swizzle me timbers
public double[] rotMode = new double[] { 0, 1, 2 };
public BusAnimationSequence() { public BusAnimationSequence() {
// Initialise our keyframe storage, since it's multidimensional // Initialise our keyframe storage, since it's multidimensional
@ -68,7 +71,7 @@ public class BusAnimationSequence {
//all transformation data is absolute, additive transformations have not yet been implemented //all transformation data is absolute, additive transformations have not yet been implemented
public double[] getTransformation(int millis) { public double[] getTransformation(int millis) {
double[] transform = new double[12]; double[] transform = new double[15];
for(int i = 0; i < 9; i++) { for(int i = 0; i < 9; i++) {
List<BusAnimationKeyframe> keyframes = transformKeyframes.get(i); List<BusAnimationKeyframe> keyframes = transformKeyframes.get(i);
@ -109,6 +112,10 @@ public class BusAnimationSequence {
transform[10] = offset[1]; transform[10] = offset[1];
transform[11] = offset[2]; transform[11] = offset[2];
transform[12] = rotMode[0];
transform[13] = rotMode[1];
transform[14] = rotMode[2];
return transform; return transform;
} }

View File

@ -110,18 +110,20 @@ public class HbmAnimations {
0, 0, 0, // position 0, 0, 0, // position
0, 0, 0, // rotation 0, 0, 0, // rotation
1, 1, 1, // scale 1, 1, 1, // scale
0, 0, 0 // offset 0, 0, 0, // offset
0, 1, 2, // XYZ order
}; };
} }
public static void applyRelevantTransformation(String bus) { applyRelevantTransformation(bus, 0); } public static void applyRelevantTransformation(String bus) { applyRelevantTransformation(bus, 0); }
public static void applyRelevantTransformation(String bus, int index) { public static void applyRelevantTransformation(String bus, int index) {
double[] transform = getRelevantTransformation(bus, index); double[] transform = getRelevantTransformation(bus, index);
int[] rot = new int[] { (int)transform[12], (int)transform[13], (int)transform[14] };
GL11.glTranslated(transform[0], transform[1], transform[2]); GL11.glTranslated(transform[0], transform[1], transform[2]);
GL11.glRotated(transform[3], 1, 0, 0); GL11.glRotated(transform[3 + rot[0]], rot[0] == 0 ? 1 : 0, rot[0] == 1 ? 1 : 0, rot[0] == 2 ? 1 : 0);
GL11.glRotated(transform[4], 0, 1, 0); GL11.glRotated(transform[3 + rot[1]], rot[1] == 0 ? 1 : 0, rot[1] == 1 ? 1 : 0, rot[1] == 2 ? 1 : 0);
GL11.glRotated(transform[5], 0, 0, 1); GL11.glRotated(transform[3 + rot[2]], rot[2] == 0 ? 1 : 0, rot[2] == 1 ? 1 : 0, rot[2] == 2 ? 1 : 0);
GL11.glTranslated(-transform[9], -transform[10], -transform[11]); GL11.glTranslated(-transform[9], -transform[10], -transform[11]);
GL11.glScaled(transform[6], transform[7], transform[8]); GL11.glScaled(transform[6], transform[7], transform[8]);
} }

File diff suppressed because one or more lines are too long

View File

@ -41,7 +41,7 @@ class ExportJSONAnimation(Operator, ExportHelper):
print("writing JSON data to file...") print("writing JSON data to file...")
f = open(self.filepath, 'w', encoding='utf-8') f = open(self.filepath, 'w', encoding='utf-8')
collection = {"anim": {}, "offset": {}, "hierarchy": {}} collection = {"anim": {}, "offset": {}, "hierarchy": {}, "rotmode": {}}
dimensions = ["x", "z", "y"] # Swizzled to X, Z, Y dimensions = ["x", "z", "y"] # Swizzled to X, Z, Y
mult = [1, -1, 1] # +X, -Z, +Y mult = [1, -1, 1] # +X, -Z, +Y
@ -51,6 +51,7 @@ class ExportJSONAnimation(Operator, ExportHelper):
animations = collection['anim'] animations = collection['anim']
offsets = collection['offset'] offsets = collection['offset']
modes = collection['rotmode']
hierarchy = collection['hierarchy'] hierarchy = collection['hierarchy']
actions = bpy.data.actions actions = bpy.data.actions
@ -112,10 +113,11 @@ class ExportJSONAnimation(Operator, ExportHelper):
if object.parent: if object.parent:
hierarchy[object.name] = object.parent.name hierarchy[object.name] = object.parent.name
if object.location == mathutils.Vector(): # don't export 0,0,0 if object.location != mathutils.Vector(): # don't export 0,0,0
continue offsets[object.name] = [object.location.x, object.location.z, -object.location.y]
offsets[object.name] = [object.location.x, object.location.z, -object.location.y] if object.rotation_mode != 'YZX':
modes[object.name] = object.rotation_mode
@ -229,14 +231,19 @@ class ImportJSONAnimation(Operator, ImportHelper):
bpy.ops.object.transform_apply(location=False, rotation=True, scale=False) bpy.ops.object.transform_apply(location=False, rotation=True, scale=False)
object.rotation_mode = 'YZX' object.rotation_mode = 'YZX'
if 'rotmode' in collection:
modes = collection['rotmode']
for mode in modes:
bpy.data.objects[mode].rotation_mode = modes[mode]
if 'hierarchy' in collection: if 'hierarchy' in collection:
hierarchy = collection["hierarchy"] hierarchy = collection['hierarchy']
for name in hierarchy: for name in hierarchy:
parent = hierarchy[name] parent = hierarchy[name]
bpy.data.objects[name].parent = bpy.data.objects[parent] bpy.data.objects[name].parent = bpy.data.objects[parent]
offsets = collection["offset"] offsets = collection['offset']
for name in offsets: for name in offsets:
offset = offsets[name] offset = offsets[name]

View File

@ -41,7 +41,7 @@ class ExportJSONAnimation(Operator, ExportHelper):
print("writing JSON data to file...") print("writing JSON data to file...")
f = open(self.filepath, 'w', encoding='utf-8') f = open(self.filepath, 'w', encoding='utf-8')
collection = {"anim": {}, "offset": {}, "hierarchy": {}} collection = {"anim": {}, "offset": {}, "hierarchy": {}, "rotmode": {}}
dimensions = ["x", "z", "y"] # Swizzled to X, Z, Y dimensions = ["x", "z", "y"] # Swizzled to X, Z, Y
mult = [1, -1, 1] # +X, -Z, +Y mult = [1, -1, 1] # +X, -Z, +Y
@ -51,6 +51,7 @@ class ExportJSONAnimation(Operator, ExportHelper):
animations = collection['anim'] animations = collection['anim']
offsets = collection['offset'] offsets = collection['offset']
modes = collection['rotmode']
hierarchy = collection['hierarchy'] hierarchy = collection['hierarchy']
actions = bpy.data.actions actions = bpy.data.actions
@ -112,10 +113,11 @@ class ExportJSONAnimation(Operator, ExportHelper):
if object.parent: if object.parent:
hierarchy[object.name] = object.parent.name hierarchy[object.name] = object.parent.name
if object.location == mathutils.Vector(): # don't export 0,0,0 if object.location != mathutils.Vector(): # don't export 0,0,0
continue offsets[object.name] = [object.location.x, object.location.z, -object.location.y]
offsets[object.name] = [object.location.x, object.location.z, -object.location.y] if object.rotation_mode != 'YZX':
modes[object.name] = object.rotation_mode
@ -230,14 +232,19 @@ class ImportJSONAnimation(Operator, ImportHelper):
bpy.ops.object.transform_apply(location=False, rotation=True, scale=False, properties=False) bpy.ops.object.transform_apply(location=False, rotation=True, scale=False, properties=False)
object.rotation_mode = 'YZX' object.rotation_mode = 'YZX'
if 'rotmode' in collection:
modes = collection['rotmode']
for mode in modes:
bpy.data.objects[mode].rotation_mode = modes[mode]
if 'hierarchy' in collection: if 'hierarchy' in collection:
hierarchy = collection["hierarchy"] hierarchy = collection['hierarchy']
for name in hierarchy: for name in hierarchy:
parent = hierarchy[name] parent = hierarchy[name]
bpy.data.objects[name].parent = bpy.data.objects[parent] bpy.data.objects[name].parent = bpy.data.objects[parent]
offsets = collection["offset"] offsets = collection['offset']
for name in offsets: for name in offsets:
offset = offsets[name] offset = offsets[name]

View File

@ -41,7 +41,7 @@ class ExportJSONAnimation(Operator, ExportHelper):
print("writing JSON data to file...") print("writing JSON data to file...")
f = open(self.filepath, 'w', encoding='utf-8') f = open(self.filepath, 'w', encoding='utf-8')
collection = {"anim": {}, "offset": {}, "hierarchy": {}} collection = {"anim": {}, "offset": {}, "hierarchy": {}, "rotmode": {}}
dimensions = ["x", "z", "y"] # Swizzled to X, Z, Y dimensions = ["x", "z", "y"] # Swizzled to X, Z, Y
mult = [1, -1, 1] # +X, -Z, +Y mult = [1, -1, 1] # +X, -Z, +Y
@ -51,6 +51,7 @@ class ExportJSONAnimation(Operator, ExportHelper):
animations = collection['anim'] animations = collection['anim']
offsets = collection['offset'] offsets = collection['offset']
modes = collection['rotmode']
hierarchy = collection['hierarchy'] hierarchy = collection['hierarchy']
actions = bpy.data.actions actions = bpy.data.actions
@ -112,10 +113,11 @@ class ExportJSONAnimation(Operator, ExportHelper):
if object.parent: if object.parent:
hierarchy[object.name] = object.parent.name hierarchy[object.name] = object.parent.name
if object.location == mathutils.Vector(): # don't export 0,0,0 if object.location != mathutils.Vector(): # don't export 0,0,0
continue offsets[object.name] = [object.location.x, object.location.z, -object.location.y]
offsets[object.name] = [object.location.x, object.location.z, -object.location.y] if object.rotation_mode != 'YZX':
modes[object.name] = object.rotation_mode
@ -227,14 +229,19 @@ class ImportJSONAnimation(Operator, ImportHelper):
bpy.ops.object.transform_apply(location=False, rotation=True, scale=False, properties=False) bpy.ops.object.transform_apply(location=False, rotation=True, scale=False, properties=False)
object.rotation_mode = 'YZX' object.rotation_mode = 'YZX'
if 'rotmode' in collection:
modes = collection['rotmode']
for mode in modes:
bpy.data.objects[mode].rotation_mode = modes[mode]
if 'hierarchy' in collection: if 'hierarchy' in collection:
hierarchy = collection["hierarchy"] hierarchy = collection['hierarchy']
for name in hierarchy: for name in hierarchy:
parent = hierarchy[name] parent = hierarchy[name]
bpy.data.objects[name].parent = bpy.data.objects[parent] bpy.data.objects[name].parent = bpy.data.objects[parent]
offsets = collection["offset"] offsets = collection['offset']
for name in offsets: for name in offsets:
offset = offsets[name] offset = offsets[name]