Skip to content

Commit eec695b

Browse files
committed
DTN dedicated Animation Format: Codec II
1 parent 1e2b25c commit eec695b

File tree

1 file changed

+107
-33
lines changed

1 file changed

+107
-33
lines changed

src/main/java/doggytalents/client/entity/model/animation/DTNAnimationCodec.java

Lines changed: 107 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,23 @@
11
package doggytalents.client.entity.model.animation;
22

33
import java.util.ArrayList;
4-
import java.util.Arrays;
54
import java.util.HashMap;
65
import java.util.List;
76
import java.util.Map;
8-
import java.util.stream.Collectors;
97

108
import org.joml.Vector3f;
119

1210
import com.google.common.collect.ImmutableBiMap;
11+
import com.google.common.collect.ImmutableMap;
1312
import com.mojang.serialization.Codec;
1413
import com.mojang.serialization.codecs.RecordCodecBuilder;
1514

1615
import net.minecraft.client.animation.AnimationChannel;
1716
import net.minecraft.client.animation.AnimationDefinition;
1817
import net.minecraft.client.animation.Keyframe;
18+
import net.minecraft.client.animation.KeyframeAnimations;
1919
import net.minecraft.util.ExtraCodecs;
20+
import net.minecraft.util.Mth;
2021

2122
public class DTNAnimationCodec {
2223

@@ -51,7 +52,7 @@ public class DTNAnimationCodec {
5152
builder -> builder.group(
5253
Codec.FLOAT.fieldOf("length")
5354
.forGetter(AnimationDefinition::lengthInSeconds),
54-
Codec.BOOL.fieldOf("loop")
55+
Codec.BOOL.optionalFieldOf("loop", false)
5556
.forGetter(AnimationDefinition::looping),
5657
channelWithPartCodec().listOf().xmap(
5758
DTNAnimationCodec::channelWithPartListToMap,
@@ -89,7 +90,8 @@ private static List<ChannelWithPart> channelWithPartListFromMap(
8990
private static final ImmutableBiMap<String, AnimationChannel.Target>
9091
CHANNEL_TYPE_BY_ID = ImmutableBiMap.of(
9192
"position", AnimationChannel.Targets.POSITION,
92-
"rotation", AnimationChannel.Targets.ROTATION
93+
"rotation", AnimationChannel.Targets.ROTATION,
94+
"scale", AnimationChannel.Targets.SCALE
9395
);
9496
private static final AnimationChannel.Target getChannelTypeFromId(String id) {
9597
return CHANNEL_TYPE_BY_ID.get(id);
@@ -100,41 +102,80 @@ private static final String getIdFromChannelType(AnimationChannel.Target interp)
100102
private record ChannelWithPart(String part, AnimationChannel channel) {
101103
public AnimationChannel.Target type() { return channel.target(); }
102104
public List<Keyframe> keyframesForEncode() {
103-
return fixChannelWhenEncode(channel);
105+
return processChannelWhenEncode(channel);
104106
}
105107
public static ChannelWithPart of(String part, AnimationChannel.Target type,
106108
List<Keyframe> keyframes) {
107109
return new ChannelWithPart(part,
108-
fixChannelWhenDecode(type, keyframes));
110+
processChannelWhenDecode(type, keyframes));
109111
}
110112
}
111-
private static AnimationChannel fixChannelWhenDecode(
112-
AnimationChannel.Target type, List<Keyframe> keyframes) {
113+
private static record KeyframeProcessor(
114+
KeyframeValueFunction whenDecode, KeyframeValueFunction whenEncode
115+
) {
116+
public static KeyframeProcessor of(KeyframeValueFunction whenDecode,
117+
KeyframeValueFunction whenEncode) {
118+
return new KeyframeProcessor(whenDecode, whenEncode);
119+
}
120+
}
121+
private static final ImmutableMap<AnimationChannel.Target, KeyframeProcessor>
122+
KEYFRAME_PROCESSORS = ImmutableMap.of(
123+
124+
AnimationChannel.Targets.POSITION,
125+
KeyframeProcessor.of(KeyframeAnimations::posVec, KeyframeAnimations::posVec),
126+
127+
AnimationChannel.Targets.ROTATION,
128+
KeyframeProcessor.of(KeyframeAnimations::degreeVec, DTNAnimationCodec::invertedRotationVec),
129+
130+
AnimationChannel.Targets.SCALE,
131+
KeyframeProcessor.of(KeyframeAnimations::scaleVec, DTNAnimationCodec::invertedScaleVec)
113132

114-
if (type != AnimationChannel.Targets.ROTATION)
115-
return new AnimationChannel(type, keyframes.toArray(Keyframe[]::new));
116-
117-
var new_keyframes = keyframes.stream()
118-
.map(kf -> {
119-
var old_value = kf.target();
120-
var new_value = new Vector3f(-old_value.x(), -old_value.y(), old_value.z());
121-
return new Keyframe(kf.timestamp(), new_value, kf.interpolation());
122-
})
123-
.toArray(Keyframe[]::new);
124-
return new AnimationChannel(type, new_keyframes);
125-
}
126-
private static List<Keyframe> fixChannelWhenEncode(AnimationChannel channel) {
133+
);
134+
private static AnimationChannel processChannelWhenDecode(
135+
AnimationChannel.Target type, List<Keyframe> rawKeyframes) {
136+
137+
final var keyframe_processor = KEYFRAME_PROCESSORS.get(type);
138+
final boolean fix_rotation = type == AnimationChannel.Targets.ROTATION;
139+
140+
var keyframes = new ArrayList<Keyframe>(rawKeyframes.size());
141+
for (var raw_keyframe : rawKeyframes) {
142+
var value = raw_keyframe.target();
143+
144+
value = keyframe_processor.whenDecode()
145+
.apply(value.x, value.y, value.z);
146+
147+
if (fix_rotation)
148+
value = new Vector3f(-value.x, -value.y, value.z);
149+
150+
var keyframe =
151+
new Keyframe(raw_keyframe.timestamp(), value, raw_keyframe.interpolation());
152+
keyframes.add(keyframe);
153+
}
154+
return new AnimationChannel(type, keyframes.toArray(Keyframe[]::new));
155+
}
156+
private static List<Keyframe> processChannelWhenEncode(AnimationChannel channel) {
127157
var type = channel.target();
128-
if (type != AnimationChannel.Targets.ROTATION)
129-
return Arrays.asList(channel.keyframes());
130-
131-
return Arrays.stream(channel.keyframes())
132-
.map(kf -> {
133-
var old_value = kf.target();
134-
var new_value = new Vector3f(-old_value.x(), -old_value.y(), old_value.z());
135-
return new Keyframe(kf.timestamp(), new_value, kf.interpolation());
136-
})
137-
.collect(Collectors.toList());
158+
final var keyframe_processor = KEYFRAME_PROCESSORS.get(type);
159+
final boolean fix_rotation = type == AnimationChannel.Targets.ROTATION;
160+
161+
var keyframes = channel.keyframes();
162+
var raw_keyframes = new ArrayList<Keyframe>(keyframes.length);
163+
for (var keyframe : keyframes) {
164+
var value = keyframe.target();
165+
166+
if (fix_rotation)
167+
value = new Vector3f(-value.x, -value.y, value.z);
168+
169+
value = keyframe_processor.whenEncode()
170+
.apply(value.x, value.y, value.z);
171+
172+
value = sanitizeWhenEncode(value);
173+
174+
var raw_keyframe =
175+
new Keyframe(keyframe.timestamp(), value, keyframe.interpolation());
176+
raw_keyframes.add(raw_keyframe);
177+
}
178+
return raw_keyframes;
138179
}
139180
private static Codec<ChannelWithPart> channelWithPartCodec() {
140181
return RecordCodecBuilder.create(
@@ -148,7 +189,7 @@ private static Codec<ChannelWithPart> channelWithPartCodec() {
148189
)
149190
.fieldOf("type")
150191
.forGetter(ChannelWithPart::type),
151-
keyframeCodec().listOf()
192+
rawKeyframeCodec().listOf()
152193
.fieldOf("keyframes")
153194
.forGetter(ChannelWithPart::keyframesForEncode)
154195
)
@@ -167,7 +208,8 @@ private static final AnimationChannel.Interpolation getInterpFromId(String id) {
167208
private static final String getIdFromInterp(AnimationChannel.Interpolation interp) {
168209
return INTERP_BY_ID.inverse().get(interp);
169210
}
170-
private static Codec<Keyframe> keyframeCodec() {
211+
212+
private static Codec<Keyframe> rawKeyframeCodec() {
171213
return RecordCodecBuilder.create(
172214
builder -> builder.group(
173215
Codec.FLOAT.fieldOf("at")
@@ -182,4 +224,36 @@ private static Codec<Keyframe> keyframeCodec() {
182224
.apply(builder, Keyframe::new)
183225
);
184226
}
227+
228+
public static Vector3f invertedRotationVec(float x, float y, float z) {
229+
return new Vector3f(x, y, z).mul(Mth.RAD_TO_DEG);
230+
}
231+
public static Vector3f invertedScaleVec(float x, float y, float z) {
232+
return new Vector3f(x, y, z).add(1, 1, 1);
233+
}
234+
private static Vector3f sanitizeWhenEncode(Vector3f vec) {
235+
vec = zeroSanitize(vec);
236+
vec = round(vec);
237+
return vec;
238+
}
239+
private static Vector3f zeroSanitize(Vector3f vec) {
240+
return new Vector3f(
241+
Mth.equal(vec.x(), 0) ? 0 : vec.x(),
242+
Mth.equal(vec.y(), 0) ? 0 : vec.y(),
243+
Mth.equal(vec.z(), 0) ? 0 : vec.z()
244+
);
245+
}
246+
private static Vector3f round(Vector3f vec) {
247+
final float rounding_mul = 100f;
248+
return new Vector3f(
249+
Math.round(vec.x * rounding_mul)/rounding_mul,
250+
Math.round(vec.y * rounding_mul)/rounding_mul,
251+
Math.round(vec.z * rounding_mul)/rounding_mul
252+
);
253+
}
254+
255+
@FunctionalInterface
256+
private static interface KeyframeValueFunction {
257+
public Vector3f apply(float x, float y, float z);
258+
}
185259
}

0 commit comments

Comments
 (0)