use of org.terasology.engine.rendering.assets.animation.MeshAnimationFrame in project Terasology by MovingBlocks.
the class GLTFAnimationFormat method loadAnimation.
private MeshAnimationData loadAnimation(GLTF gltf, GLTFAnimation animation, List<byte[]> loadedBuffers, TIntIntMap boneIndexMapping, List<String> boneNames, TIntList boneParents, List<Bone> bones) throws IOException {
List<ChannelReader> channelReaders = new ArrayList<>();
for (GLTFChannel channel : animation.getChannels()) {
GLTFAnimationSampler sampler = animation.getSamplers().get(channel.getSampler());
TFloatList times = getFloats(gltf, loadedBuffers, sampler.getInput());
int bone = boneIndexMapping.get(channel.getTarget().getNode());
switch(channel.getTarget().getPath()) {
case TRANSLATION:
{
List<Vector3f> data = getVector3fs(gltf, loadedBuffers, sampler.getOutput());
channelReaders.add(new BufferChannelReader<>(times, data, sampler.getInterpolation()::interpolate, x -> x.getPosition(bone)));
break;
}
case ROTATION:
{
List<Quaternionf> data = getQuat4fs(gltf, loadedBuffers, sampler.getOutput());
channelReaders.add(new BufferChannelReader<>(times, data, sampler.getInterpolation()::interpolate, x -> x.getRotation(bone)));
break;
}
case SCALE:
{
List<Vector3f> data = getVector3fs(gltf, loadedBuffers, sampler.getOutput());
channelReaders.add(new BufferChannelReader<>(times, data, sampler.getInterpolation()::interpolate, x -> x.getBoneScale(bone)));
break;
}
default:
break;
}
}
int frameCount = (int) (channelReaders.stream().map(ChannelReader::endTime).reduce(Float::max).orElse(0f) / TIME_PER_FRAME) + 1;
List<MeshAnimationFrame> frames = new ArrayList<>(frameCount);
for (int i = 0; i < frameCount; i++) {
float time = i * TIME_PER_FRAME;
List<Vector3f> boneLocations = new ArrayList<>();
List<Quaternionf> boneRotations = new ArrayList<>();
List<Vector3f> boneScales = new ArrayList<>();
for (Bone bone : bones) {
boneLocations.add(new Vector3f(bone.getLocalPosition()));
boneRotations.add(new Quaternionf(bone.getLocalRotation()));
boneScales.add(new Vector3f(bone.getLocalScale()));
}
MeshAnimationFrame frame = new MeshAnimationFrame(boneLocations, boneRotations, boneScales);
channelReaders.forEach(x -> x.updateFrame(time, frame));
frames.add(frame);
}
return new MeshAnimationData(boneNames, boneParents, frames, TIME_PER_FRAME, new AABBf(0, 0, 0));
}
use of org.terasology.engine.rendering.assets.animation.MeshAnimationFrame in project Terasology by MovingBlocks.
the class SkeletonRenderer method updateSkeletalMeshOfEntity.
private void updateSkeletalMeshOfEntity(EntityRef entity, float delta) {
SkeletalMeshComponent skeletalMeshComp = entity.getComponent(SkeletalMeshComponent.class);
if (skeletalMeshComp.mesh == null) {
return;
}
if (skeletalMeshComp.animation == null && skeletalMeshComp.animationPool != null) {
skeletalMeshComp.animation = randomAnimationData(skeletalMeshComp, random);
}
if (skeletalMeshComp.animation == null) {
return;
}
if (skeletalMeshComp.animation.getFrameCount() < 1) {
return;
}
skeletalMeshComp.animationTime += delta * skeletalMeshComp.animationRate;
float animationDuration = getDurationOfAnimation(skeletalMeshComp);
while (skeletalMeshComp.animationTime >= animationDuration) {
MeshAnimation newAnimation;
if (!skeletalMeshComp.loop) {
newAnimation = null;
} else if (skeletalMeshComp.animationPool != null && !skeletalMeshComp.animationPool.isEmpty()) {
newAnimation = randomAnimationData(skeletalMeshComp, random);
} else {
newAnimation = skeletalMeshComp.animation;
}
if (newAnimation == null) {
MeshAnimation finishedAnimation = skeletalMeshComp.animation;
skeletalMeshComp.animationTime = animationDuration;
MeshAnimationFrame frame = skeletalMeshComp.animation.getFrame(skeletalMeshComp.animation.getFrameCount() - 1);
updateSkeleton(skeletalMeshComp, frame, frame, 1.0f);
// Set animation to null so that AnimEndEvent fires only once
skeletalMeshComp.animation = null;
entity.saveComponent(skeletalMeshComp);
entity.send(new AnimEndEvent(finishedAnimation));
return;
}
skeletalMeshComp.animationTime -= animationDuration;
if (skeletalMeshComp.animationTime < 0) {
// In case the float calculation wasn't exact:
skeletalMeshComp.animationTime = 0;
}
skeletalMeshComp.animation = newAnimation;
animationDuration = getDurationOfAnimation(skeletalMeshComp);
}
float framePos = skeletalMeshComp.animationTime / skeletalMeshComp.animation.getTimePerFrame();
int frameAId = (int) framePos;
int frameBId = frameAId + 1;
if (frameBId >= skeletalMeshComp.animation.getFrameCount()) {
// In case the float calcuation wasn't exact:
frameBId = skeletalMeshComp.animation.getFrameCount() - 1;
}
MeshAnimationFrame frameA = skeletalMeshComp.animation.getFrame(frameAId);
MeshAnimationFrame frameB = skeletalMeshComp.animation.getFrame(frameBId);
updateSkeleton(skeletalMeshComp, frameA, frameB, framePos - frameAId);
entity.saveComponent(skeletalMeshComp);
}
Aggregations